reorganize directories
authorMichael Wallner <mike@php.net>
Tue, 18 Feb 2020 09:04:55 +0000 (10:04 +0100)
committerMichael Wallner <mike@php.net>
Tue, 18 Feb 2020 09:04:55 +0000 (10:04 +0100)
846 files changed:
.gitignore
CMakeLists.txt
COPYING
README.FIRST [deleted file]
clients/CMakeLists.txt [deleted file]
clients/client_options.h [deleted file]
clients/execute.cc [deleted file]
clients/execute.h [deleted file]
clients/generator.cc [deleted file]
clients/generator.h [deleted file]
clients/memaslap.c [deleted file]
clients/memcapable.cc [deleted file]
clients/memcapable.sh [deleted file]
clients/memcat.cc [deleted file]
clients/memcat.sh [deleted file]
clients/memcp.cc [deleted file]
clients/memcp.sh [deleted file]
clients/memdump.cc [deleted file]
clients/memdump.sh [deleted file]
clients/memerror.cc [deleted file]
clients/memerror.sh [deleted file]
clients/memexist.cc [deleted file]
clients/memexist.sh [deleted file]
clients/memflush.cc [deleted file]
clients/memflush.sh [deleted file]
clients/memparse.cc [deleted file]
clients/memparse.sh [deleted file]
clients/memping.cc [deleted file]
clients/memping.sh [deleted file]
clients/memrm.cc [deleted file]
clients/memrm.sh [deleted file]
clients/memslap.cc [deleted file]
clients/memslap.sh [deleted file]
clients/memstat.cc [deleted file]
clients/memstat.sh [deleted file]
clients/memtouch.cc [deleted file]
clients/memtouch.sh [deleted file]
clients/ms_atomic.h [deleted file]
clients/ms_conn.c [deleted file]
clients/ms_conn.h [deleted file]
clients/ms_memslap.h [deleted file]
clients/ms_setting.c [deleted file]
clients/ms_setting.h [deleted file]
clients/ms_sigsegv.c [deleted file]
clients/ms_sigsegv.h [deleted file]
clients/ms_stats.c [deleted file]
clients/ms_stats.h [deleted file]
clients/ms_task.c [deleted file]
clients/ms_task.h [deleted file]
clients/ms_thread.c [deleted file]
clients/ms_thread.h [deleted file]
clients/utilities.cc [deleted file]
clients/utilities.h [deleted file]
docs/gh-pages/publish.sh [new file with mode: 0755]
gh-pages.sh [deleted file]
include/CMakeLists.txt [new file with mode: 0644]
include/libhashkit-1.0/CMakeLists.txt [new file with mode: 0644]
include/libhashkit-1.0/algorithm.h [new file with mode: 0644]
include/libhashkit-1.0/basic_string.h [new file with mode: 0644]
include/libhashkit-1.0/behavior.h [new file with mode: 0644]
include/libhashkit-1.0/configure.h.in [new file with mode: 0644]
include/libhashkit-1.0/digest.h [new file with mode: 0644]
include/libhashkit-1.0/function.h [new file with mode: 0644]
include/libhashkit-1.0/has.h [new file with mode: 0644]
include/libhashkit-1.0/hashkit.h [new file with mode: 0644]
include/libhashkit-1.0/hashkit.hpp [new file with mode: 0644]
include/libhashkit-1.0/str_algorithm.h [new file with mode: 0644]
include/libhashkit-1.0/strerror.h [new file with mode: 0644]
include/libhashkit-1.0/string.h [new file with mode: 0644]
include/libhashkit-1.0/types.h [new file with mode: 0644]
include/libhashkit-1.0/visibility.h [new file with mode: 0644]
include/libmemcached-1.0/CMakeLists.txt [new file with mode: 0644]
include/libmemcached-1.0/alloc.h [new file with mode: 0644]
include/libmemcached-1.0/allocators.h [new file with mode: 0644]
include/libmemcached-1.0/analyze.h [new file with mode: 0644]
include/libmemcached-1.0/auto.h [new file with mode: 0644]
include/libmemcached-1.0/basic_string.h [new file with mode: 0644]
include/libmemcached-1.0/behavior.h [new file with mode: 0644]
include/libmemcached-1.0/callback.h [new file with mode: 0644]
include/libmemcached-1.0/callbacks.h [new file with mode: 0644]
include/libmemcached-1.0/configure.h.in [new file with mode: 0644]
include/libmemcached-1.0/defaults.h [new file with mode: 0644]
include/libmemcached-1.0/delete.h [new file with mode: 0644]
include/libmemcached-1.0/deprecated_types.h [new file with mode: 0644]
include/libmemcached-1.0/dump.h [new file with mode: 0644]
include/libmemcached-1.0/encoding_key.h [new file with mode: 0644]
include/libmemcached-1.0/error.h [new file with mode: 0644]
include/libmemcached-1.0/exception.hpp [new file with mode: 0644]
include/libmemcached-1.0/exist.h [new file with mode: 0644]
include/libmemcached-1.0/fetch.h [new file with mode: 0644]
include/libmemcached-1.0/flush.h [new file with mode: 0644]
include/libmemcached-1.0/flush_buffers.h [new file with mode: 0644]
include/libmemcached-1.0/get.h [new file with mode: 0644]
include/libmemcached-1.0/hash.h [new file with mode: 0644]
include/libmemcached-1.0/limits.h [new file with mode: 0644]
include/libmemcached-1.0/memcached.h [new file with mode: 0644]
include/libmemcached-1.0/memcached.hpp [new file with mode: 0644]
include/libmemcached-1.0/options.h [new file with mode: 0644]
include/libmemcached-1.0/parse.h [new file with mode: 0644]
include/libmemcached-1.0/platform.h [new file with mode: 0644]
include/libmemcached-1.0/quit.h [new file with mode: 0644]
include/libmemcached-1.0/result.h [new file with mode: 0644]
include/libmemcached-1.0/return.h [new file with mode: 0644]
include/libmemcached-1.0/sasl.h [new file with mode: 0644]
include/libmemcached-1.0/server.h [new file with mode: 0644]
include/libmemcached-1.0/server_list.h [new file with mode: 0644]
include/libmemcached-1.0/stats.h [new file with mode: 0644]
include/libmemcached-1.0/storage.h [new file with mode: 0644]
include/libmemcached-1.0/strerror.h [new file with mode: 0644]
include/libmemcached-1.0/struct/allocator.h [new file with mode: 0644]
include/libmemcached-1.0/struct/analysis.h [new file with mode: 0644]
include/libmemcached-1.0/struct/callback.h [new file with mode: 0644]
include/libmemcached-1.0/struct/memcached.h [new file with mode: 0644]
include/libmemcached-1.0/struct/result.h [new file with mode: 0644]
include/libmemcached-1.0/struct/sasl.h [new file with mode: 0644]
include/libmemcached-1.0/struct/server.h [new file with mode: 0644]
include/libmemcached-1.0/struct/stat.h [new file with mode: 0644]
include/libmemcached-1.0/struct/string.h [new file with mode: 0644]
include/libmemcached-1.0/t/c_sasl_test.c [new file with mode: 0644]
include/libmemcached-1.0/t/c_test.c [new file with mode: 0644]
include/libmemcached-1.0/t/cc_test.cc [new file with mode: 0644]
include/libmemcached-1.0/touch.h [new file with mode: 0644]
include/libmemcached-1.0/triggers.h [new file with mode: 0644]
include/libmemcached-1.0/types.h [new file with mode: 0644]
include/libmemcached-1.0/types/behavior.h [new file with mode: 0644]
include/libmemcached-1.0/types/callback.h [new file with mode: 0644]
include/libmemcached-1.0/types/connection.h [new file with mode: 0644]
include/libmemcached-1.0/types/hash.h [new file with mode: 0644]
include/libmemcached-1.0/types/return.h [new file with mode: 0644]
include/libmemcached-1.0/types/server_distribution.h [new file with mode: 0644]
include/libmemcached-1.0/verbosity.h [new file with mode: 0644]
include/libmemcached-1.0/version.h [new file with mode: 0644]
include/libmemcached-1.0/visibility.h [new file with mode: 0644]
include/libmemcachedprotocol-0.0/binary.h [new file with mode: 0644]
include/libmemcachedprotocol-0.0/callback.h [new file with mode: 0644]
include/libmemcachedprotocol-0.0/handler.h [new file with mode: 0644]
include/libmemcachedprotocol-0.0/vbucket.h [new file with mode: 0644]
include/libmemcachedutil-1.0/CMakeLists.txt [new file with mode: 0644]
include/libmemcachedutil-1.0/flush.h [new file with mode: 0644]
include/libmemcachedutil-1.0/ostream.hpp [new file with mode: 0644]
include/libmemcachedutil-1.0/pid.h [new file with mode: 0644]
include/libmemcachedutil-1.0/ping.h [new file with mode: 0644]
include/libmemcachedutil-1.0/pool.h [new file with mode: 0644]
include/libmemcachedutil-1.0/util.h [new file with mode: 0644]
include/libmemcachedutil-1.0/version.h [new file with mode: 0644]
libhashkit-1.0/CMakeLists.txt [deleted file]
libhashkit-1.0/algorithm.h [deleted file]
libhashkit-1.0/basic_string.h [deleted file]
libhashkit-1.0/behavior.h [deleted file]
libhashkit-1.0/configure.h.in [deleted file]
libhashkit-1.0/digest.h [deleted file]
libhashkit-1.0/function.h [deleted file]
libhashkit-1.0/has.h [deleted file]
libhashkit-1.0/hashkit.h [deleted file]
libhashkit-1.0/hashkit.hpp [deleted file]
libhashkit-1.0/str_algorithm.h [deleted file]
libhashkit-1.0/strerror.h [deleted file]
libhashkit-1.0/string.h [deleted file]
libhashkit-1.0/types.h [deleted file]
libhashkit-1.0/visibility.h [deleted file]
libhashkit/CMakeLists.txt [deleted file]
libhashkit/aes.cc [deleted file]
libhashkit/aes.h [deleted file]
libhashkit/algorithm.cc [deleted file]
libhashkit/algorithm.h [deleted file]
libhashkit/behavior.cc [deleted file]
libhashkit/common.h [deleted file]
libhashkit/crc32.cc [deleted file]
libhashkit/digest.cc [deleted file]
libhashkit/encrypt.cc [deleted file]
libhashkit/fnv_32.cc [deleted file]
libhashkit/fnv_64.cc [deleted file]
libhashkit/function.cc [deleted file]
libhashkit/has.cc [deleted file]
libhashkit/hashkit.cc [deleted file]
libhashkit/hashkit.h [deleted file]
libhashkit/hashkitcon.h.in [deleted file]
libhashkit/hsieh.cc [deleted file]
libhashkit/is.h [deleted file]
libhashkit/jenkins.cc [deleted file]
libhashkit/ketama.cc [deleted file]
libhashkit/md5.cc [deleted file]
libhashkit/murmur.cc [deleted file]
libhashkit/murmur3.cc [deleted file]
libhashkit/murmur3.h [deleted file]
libhashkit/murmur3_api.cc [deleted file]
libhashkit/nohsieh.cc [deleted file]
libhashkit/one_at_a_time.cc [deleted file]
libhashkit/rijndael.cc [deleted file]
libhashkit/rijndael.hpp [deleted file]
libhashkit/str_algorithm.cc [deleted file]
libhashkit/strerror.cc [deleted file]
libhashkit/string.cc [deleted file]
libhashkit/string.h [deleted file]
libmemcached-1.0/CMakeLists.txt [deleted file]
libmemcached-1.0/alloc.h [deleted file]
libmemcached-1.0/allocators.h [deleted file]
libmemcached-1.0/analyze.h [deleted file]
libmemcached-1.0/auto.h [deleted file]
libmemcached-1.0/basic_string.h [deleted file]
libmemcached-1.0/behavior.h [deleted file]
libmemcached-1.0/callback.h [deleted file]
libmemcached-1.0/callbacks.h [deleted file]
libmemcached-1.0/configure.h.in [deleted file]
libmemcached-1.0/defaults.h [deleted file]
libmemcached-1.0/delete.h [deleted file]
libmemcached-1.0/deprecated_types.h [deleted file]
libmemcached-1.0/dump.h [deleted file]
libmemcached-1.0/encoding_key.h [deleted file]
libmemcached-1.0/error.h [deleted file]
libmemcached-1.0/exception.hpp [deleted file]
libmemcached-1.0/exist.h [deleted file]
libmemcached-1.0/fetch.h [deleted file]
libmemcached-1.0/flush.h [deleted file]
libmemcached-1.0/flush_buffers.h [deleted file]
libmemcached-1.0/get.h [deleted file]
libmemcached-1.0/hash.h [deleted file]
libmemcached-1.0/limits.h [deleted file]
libmemcached-1.0/memcached.h [deleted file]
libmemcached-1.0/memcached.hpp [deleted file]
libmemcached-1.0/options.h [deleted file]
libmemcached-1.0/parse.h [deleted file]
libmemcached-1.0/platform.h [deleted file]
libmemcached-1.0/quit.h [deleted file]
libmemcached-1.0/result.h [deleted file]
libmemcached-1.0/return.h [deleted file]
libmemcached-1.0/sasl.h [deleted file]
libmemcached-1.0/server.h [deleted file]
libmemcached-1.0/server_list.h [deleted file]
libmemcached-1.0/stats.h [deleted file]
libmemcached-1.0/storage.h [deleted file]
libmemcached-1.0/strerror.h [deleted file]
libmemcached-1.0/struct/allocator.h [deleted file]
libmemcached-1.0/struct/analysis.h [deleted file]
libmemcached-1.0/struct/callback.h [deleted file]
libmemcached-1.0/struct/memcached.h [deleted file]
libmemcached-1.0/struct/result.h [deleted file]
libmemcached-1.0/struct/sasl.h [deleted file]
libmemcached-1.0/struct/server.h [deleted file]
libmemcached-1.0/struct/stat.h [deleted file]
libmemcached-1.0/struct/string.h [deleted file]
libmemcached-1.0/t/c_sasl_test.c [deleted file]
libmemcached-1.0/t/c_test.c [deleted file]
libmemcached-1.0/t/cc_test.cc [deleted file]
libmemcached-1.0/touch.h [deleted file]
libmemcached-1.0/triggers.h [deleted file]
libmemcached-1.0/types.h [deleted file]
libmemcached-1.0/types/behavior.h [deleted file]
libmemcached-1.0/types/callback.h [deleted file]
libmemcached-1.0/types/connection.h [deleted file]
libmemcached-1.0/types/hash.h [deleted file]
libmemcached-1.0/types/return.h [deleted file]
libmemcached-1.0/types/server_distribution.h [deleted file]
libmemcached-1.0/verbosity.h [deleted file]
libmemcached-1.0/version.h [deleted file]
libmemcached-1.0/visibility.h [deleted file]
libmemcached/CMakeLists.txt [deleted file]
libmemcached/allocators.cc [deleted file]
libmemcached/allocators.hpp [deleted file]
libmemcached/analyze.cc [deleted file]
libmemcached/array.c [deleted file]
libmemcached/array.h [deleted file]
libmemcached/assert.hpp [deleted file]
libmemcached/auto.cc [deleted file]
libmemcached/backtrace.cc [deleted file]
libmemcached/backtrace.hpp [deleted file]
libmemcached/behavior.cc [deleted file]
libmemcached/behavior.hpp [deleted file]
libmemcached/byteorder.cc [deleted file]
libmemcached/byteorder.h [deleted file]
libmemcached/callback.cc [deleted file]
libmemcached/callback.h [deleted file]
libmemcached/common.h [deleted file]
libmemcached/connect.cc [deleted file]
libmemcached/connect.hpp [deleted file]
libmemcached/continuum.hpp [deleted file]
libmemcached/csl/common.h [deleted file]
libmemcached/csl/context.cc [deleted file]
libmemcached/csl/context.h [deleted file]
libmemcached/csl/parser.yy [deleted file]
libmemcached/csl/scanner.l [deleted file]
libmemcached/csl/server.h [deleted file]
libmemcached/csl/symbol.h [deleted file]
libmemcached/delete.cc [deleted file]
libmemcached/do.cc [deleted file]
libmemcached/do.hpp [deleted file]
libmemcached/dump.cc [deleted file]
libmemcached/encoding_key.cc [deleted file]
libmemcached/encoding_key.h [deleted file]
libmemcached/error.cc [deleted file]
libmemcached/error.hpp [deleted file]
libmemcached/exist.cc [deleted file]
libmemcached/fetch.cc [deleted file]
libmemcached/flag.cc [deleted file]
libmemcached/flag.hpp [deleted file]
libmemcached/flush.cc [deleted file]
libmemcached/flush_buffers.cc [deleted file]
libmemcached/get.cc [deleted file]
libmemcached/hash.cc [deleted file]
libmemcached/hash.hpp [deleted file]
libmemcached/hosts.cc [deleted file]
libmemcached/initialize_query.cc [deleted file]
libmemcached/initialize_query.h [deleted file]
libmemcached/instance.cc [deleted file]
libmemcached/instance.hpp [deleted file]
libmemcached/internal.h [deleted file]
libmemcached/io.cc [deleted file]
libmemcached/io.h [deleted file]
libmemcached/io.hpp [deleted file]
libmemcached/is.h [deleted file]
libmemcached/key.cc [deleted file]
libmemcached/key.hpp [deleted file]
libmemcached/libmemcached_probes.d [deleted file]
libmemcached/libmemcached_probes.h [deleted file]
libmemcached/memcached.cc [deleted file]
libmemcached/memcached.h [deleted file]
libmemcached/memcached.hpp [deleted file]
libmemcached/memcached/README.txt [deleted file]
libmemcached/memcached/protocol_binary.h [deleted file]
libmemcached/memcached/vbucket.h [deleted file]
libmemcached/memory.h [deleted file]
libmemcached/namespace.cc [deleted file]
libmemcached/namespace.h [deleted file]
libmemcached/options.cc [deleted file]
libmemcached/options.hpp [deleted file]
libmemcached/parse.cc [deleted file]
libmemcached/poll.cc [deleted file]
libmemcached/poll.h [deleted file]
libmemcached/purge.cc [deleted file]
libmemcached/quit.cc [deleted file]
libmemcached/quit.hpp [deleted file]
libmemcached/response.cc [deleted file]
libmemcached/response.h [deleted file]
libmemcached/result.cc [deleted file]
libmemcached/result.h [deleted file]
libmemcached/sasl.cc [deleted file]
libmemcached/sasl.hpp [deleted file]
libmemcached/server.cc [deleted file]
libmemcached/server.hpp [deleted file]
libmemcached/server_instance.h [deleted file]
libmemcached/server_list.cc [deleted file]
libmemcached/server_list.hpp [deleted file]
libmemcached/socket.hpp [deleted file]
libmemcached/stats.cc [deleted file]
libmemcached/storage.cc [deleted file]
libmemcached/strerror.cc [deleted file]
libmemcached/string.cc [deleted file]
libmemcached/string.hpp [deleted file]
libmemcached/touch.cc [deleted file]
libmemcached/udp.cc [deleted file]
libmemcached/udp.hpp [deleted file]
libmemcached/util.h [deleted file]
libmemcached/util/Makefile.am [deleted file]
libmemcached/verbosity.cc [deleted file]
libmemcached/version.cc [deleted file]
libmemcached/version.hpp [deleted file]
libmemcached/virtual_bucket.c [deleted file]
libmemcached/virtual_bucket.h [deleted file]
libmemcached/watchpoint.h [deleted file]
libmemcached/windows.hpp [deleted file]
libmemcachedprotocol-0.0/binary.h [deleted file]
libmemcachedprotocol-0.0/callback.h [deleted file]
libmemcachedprotocol-0.0/handler.h [deleted file]
libmemcachedprotocol-0.0/vbucket.h [deleted file]
libmemcachedprotocol/ascii_handler.c [deleted file]
libmemcachedprotocol/ascii_handler.h [deleted file]
libmemcachedprotocol/binary_handler.c [deleted file]
libmemcachedprotocol/binary_handler.h [deleted file]
libmemcachedprotocol/cache.c [deleted file]
libmemcachedprotocol/cache.h [deleted file]
libmemcachedprotocol/common.h [deleted file]
libmemcachedprotocol/handler.c [deleted file]
libmemcachedprotocol/pedantic.c [deleted file]
libmemcachedutil-1.0/CMakeLists.txt [deleted file]
libmemcachedutil-1.0/flush.h [deleted file]
libmemcachedutil-1.0/ostream.hpp [deleted file]
libmemcachedutil-1.0/pid.h [deleted file]
libmemcachedutil-1.0/ping.h [deleted file]
libmemcachedutil-1.0/pool.h [deleted file]
libmemcachedutil-1.0/util.h [deleted file]
libmemcachedutil-1.0/version.h [deleted file]
libmemcachedutil/CMakeLists.txt [deleted file]
libmemcachedutil/common.h [deleted file]
libmemcachedutil/flush.cc [deleted file]
libmemcachedutil/pid.cc [deleted file]
libmemcachedutil/ping.cc [deleted file]
libmemcachedutil/pool.cc [deleted file]
libmemcachedutil/version.cc [deleted file]
libtest/CMakeLists.txt [deleted file]
libtest/alarm.cc [deleted file]
libtest/alarm.h [deleted file]
libtest/backtrace_test.cc [deleted file]
libtest/binaries.cc [deleted file]
libtest/binaries.h [deleted file]
libtest/blobslap_worker.cc [deleted file]
libtest/blobslap_worker.h [deleted file]
libtest/callbacks.h [deleted file]
libtest/client.cc [deleted file]
libtest/client.hpp [deleted file]
libtest/cmdline.cc [deleted file]
libtest/cmdline.h [deleted file]
libtest/collection.cc [deleted file]
libtest/collection.h [deleted file]
libtest/common.h [deleted file]
libtest/comparison.cc [deleted file]
libtest/comparison.hpp [deleted file]
libtest/core.cc [deleted file]
libtest/core.h [deleted file]
libtest/core_count.cc [deleted file]
libtest/cpu.cc [deleted file]
libtest/cpu.hpp [deleted file]
libtest/dns.cc [deleted file]
libtest/dns.hpp [deleted file]
libtest/dream.cc [deleted file]
libtest/dream.h [deleted file]
libtest/drizzled.cc [deleted file]
libtest/drizzled.h [deleted file]
libtest/error.h [deleted file]
libtest/exception.cc [deleted file]
libtest/exception.hpp [deleted file]
libtest/exception/disconnected.hpp [deleted file]
libtest/exception/fatal.cc [deleted file]
libtest/exception/fatal.hpp [deleted file]
libtest/failed.cc [deleted file]
libtest/formatter.cc [deleted file]
libtest/formatter.hpp [deleted file]
libtest/framework.cc [deleted file]
libtest/framework.h [deleted file]
libtest/gearmand.cc [deleted file]
libtest/gearmand.h [deleted file]
libtest/get.h [deleted file]
libtest/has.cc [deleted file]
libtest/has.hpp [deleted file]
libtest/http.cc [deleted file]
libtest/http.hpp [deleted file]
libtest/is_local.cc [deleted file]
libtest/is_local.hpp [deleted file]
libtest/is_pid.hpp [deleted file]
libtest/killpid.cc [deleted file]
libtest/killpid.h [deleted file]
libtest/libtool.cc [deleted file]
libtest/libtool.hpp [deleted file]
libtest/lite.h [deleted file]
libtest/main.cc [deleted file]
libtest/memcached.cc [deleted file]
libtest/memcached.h [deleted file]
libtest/memcached.hpp [deleted file]
libtest/poll_error.hpp [deleted file]
libtest/port.cc [deleted file]
libtest/port.h [deleted file]
libtest/result.cc [deleted file]
libtest/result.hpp [deleted file]
libtest/result/base.hpp [deleted file]
libtest/result/fail.hpp [deleted file]
libtest/result/skip.hpp [deleted file]
libtest/result/success.hpp [deleted file]
libtest/run-ci.gdb [deleted file]
libtest/run.gdb [deleted file]
libtest/runner.cc [deleted file]
libtest/runner.h [deleted file]
libtest/server.cc [deleted file]
libtest/server.h [deleted file]
libtest/server_container.cc [deleted file]
libtest/server_container.h [deleted file]
libtest/signal.cc [deleted file]
libtest/signal.h [deleted file]
libtest/skiptest.cc [deleted file]
libtest/socket.cc [deleted file]
libtest/socket.hpp [deleted file]
libtest/stream.h [deleted file]
libtest/strerror.cc [deleted file]
libtest/strerror.h [deleted file]
libtest/string.hpp [deleted file]
libtest/test.h [deleted file]
libtest/test.hpp [deleted file]
libtest/thread.hpp [deleted file]
libtest/timer.cc [deleted file]
libtest/timer.hpp [deleted file]
libtest/tmpfile.cc [deleted file]
libtest/tmpfile.hpp [deleted file]
libtest/unittest.cc [deleted file]
libtest/valgrind.h [deleted file]
libtest/vchar.cc [deleted file]
libtest/vchar.hpp [deleted file]
libtest/version.h.in [deleted file]
libtest/visibility.h [deleted file]
libtest/wait.cc [deleted file]
libtest/wait.h [deleted file]
libtest/yatl.h [deleted file]
libtest/yatlcon.h.in [deleted file]
mem_config.h.in [deleted file]
src/CMakeLists.txt [new file with mode: 0644]
src/bin/CMakeLists.txt [new file with mode: 0644]
src/bin/client_options.h [new file with mode: 0644]
src/bin/execute.cc [new file with mode: 0644]
src/bin/execute.h [new file with mode: 0644]
src/bin/generator.cc [new file with mode: 0644]
src/bin/generator.h [new file with mode: 0644]
src/bin/memaslap.c [new file with mode: 0644]
src/bin/memcapable.cc [new file with mode: 0644]
src/bin/memcapable.sh [new file with mode: 0755]
src/bin/memcat.cc [new file with mode: 0644]
src/bin/memcat.sh [new file with mode: 0755]
src/bin/memcp.cc [new file with mode: 0644]
src/bin/memcp.sh [new file with mode: 0755]
src/bin/memdump.cc [new file with mode: 0644]
src/bin/memdump.sh [new file with mode: 0755]
src/bin/memerror.cc [new file with mode: 0644]
src/bin/memerror.sh [new file with mode: 0755]
src/bin/memexist.cc [new file with mode: 0644]
src/bin/memexist.sh [new file with mode: 0755]
src/bin/memflush.cc [new file with mode: 0644]
src/bin/memflush.sh [new file with mode: 0755]
src/bin/memparse.cc [new file with mode: 0644]
src/bin/memparse.sh [new file with mode: 0755]
src/bin/memping.cc [new file with mode: 0644]
src/bin/memping.sh [new file with mode: 0755]
src/bin/memrm.cc [new file with mode: 0644]
src/bin/memrm.sh [new file with mode: 0755]
src/bin/memslap.cc [new file with mode: 0644]
src/bin/memslap.sh [new file with mode: 0755]
src/bin/memstat.cc [new file with mode: 0644]
src/bin/memstat.sh [new file with mode: 0755]
src/bin/memtouch.cc [new file with mode: 0644]
src/bin/memtouch.sh [new file with mode: 0755]
src/bin/ms_atomic.h [new file with mode: 0644]
src/bin/ms_conn.c [new file with mode: 0644]
src/bin/ms_conn.h [new file with mode: 0644]
src/bin/ms_memslap.h [new file with mode: 0644]
src/bin/ms_setting.c [new file with mode: 0644]
src/bin/ms_setting.h [new file with mode: 0644]
src/bin/ms_sigsegv.c [new file with mode: 0644]
src/bin/ms_sigsegv.h [new file with mode: 0644]
src/bin/ms_stats.c [new file with mode: 0644]
src/bin/ms_stats.h [new file with mode: 0644]
src/bin/ms_task.c [new file with mode: 0644]
src/bin/ms_task.h [new file with mode: 0644]
src/bin/ms_thread.c [new file with mode: 0644]
src/bin/ms_thread.h [new file with mode: 0644]
src/bin/utilities.cc [new file with mode: 0644]
src/bin/utilities.h [new file with mode: 0644]
src/libhashkit/CMakeLists.txt [new file with mode: 0644]
src/libhashkit/aes.cc [new file with mode: 0644]
src/libhashkit/aes.h [new file with mode: 0644]
src/libhashkit/algorithm.cc [new file with mode: 0644]
src/libhashkit/algorithm.h [new file with mode: 0644]
src/libhashkit/behavior.cc [new file with mode: 0644]
src/libhashkit/common.h [new file with mode: 0644]
src/libhashkit/crc32.cc [new file with mode: 0644]
src/libhashkit/digest.cc [new file with mode: 0644]
src/libhashkit/encrypt.cc [new file with mode: 0644]
src/libhashkit/fnv_32.cc [new file with mode: 0644]
src/libhashkit/fnv_64.cc [new file with mode: 0644]
src/libhashkit/function.cc [new file with mode: 0644]
src/libhashkit/has.cc [new file with mode: 0644]
src/libhashkit/hashkit.cc [new file with mode: 0644]
src/libhashkit/hashkit.h [new file with mode: 0644]
src/libhashkit/hashkitcon.h.in [new file with mode: 0644]
src/libhashkit/hsieh.cc [new file with mode: 0644]
src/libhashkit/is.h [new file with mode: 0644]
src/libhashkit/jenkins.cc [new file with mode: 0644]
src/libhashkit/ketama.cc [new file with mode: 0644]
src/libhashkit/md5.cc [new file with mode: 0644]
src/libhashkit/murmur.cc [new file with mode: 0644]
src/libhashkit/murmur3.cc [new file with mode: 0644]
src/libhashkit/murmur3.h [new file with mode: 0644]
src/libhashkit/murmur3_api.cc [new file with mode: 0644]
src/libhashkit/nohsieh.cc [new file with mode: 0644]
src/libhashkit/one_at_a_time.cc [new file with mode: 0644]
src/libhashkit/rijndael.cc [new file with mode: 0644]
src/libhashkit/rijndael.hpp [new file with mode: 0644]
src/libhashkit/str_algorithm.cc [new file with mode: 0644]
src/libhashkit/strerror.cc [new file with mode: 0644]
src/libhashkit/string.cc [new file with mode: 0644]
src/libhashkit/string.h [new file with mode: 0644]
src/libmemcached/CMakeLists.txt [new file with mode: 0644]
src/libmemcached/allocators.cc [new file with mode: 0644]
src/libmemcached/allocators.hpp [new file with mode: 0644]
src/libmemcached/analyze.cc [new file with mode: 0644]
src/libmemcached/array.c [new file with mode: 0644]
src/libmemcached/array.h [new file with mode: 0644]
src/libmemcached/assert.hpp [new file with mode: 0644]
src/libmemcached/auto.cc [new file with mode: 0644]
src/libmemcached/backtrace.cc [new file with mode: 0644]
src/libmemcached/backtrace.hpp [new file with mode: 0644]
src/libmemcached/behavior.cc [new file with mode: 0644]
src/libmemcached/behavior.hpp [new file with mode: 0644]
src/libmemcached/byteorder.cc [new file with mode: 0644]
src/libmemcached/byteorder.h [new file with mode: 0644]
src/libmemcached/callback.cc [new file with mode: 0644]
src/libmemcached/callback.h [new file with mode: 0644]
src/libmemcached/common.h [new file with mode: 0644]
src/libmemcached/connect.cc [new file with mode: 0644]
src/libmemcached/connect.hpp [new file with mode: 0644]
src/libmemcached/continuum.hpp [new file with mode: 0644]
src/libmemcached/csl/common.h [new file with mode: 0644]
src/libmemcached/csl/context.cc [new file with mode: 0644]
src/libmemcached/csl/context.h [new file with mode: 0644]
src/libmemcached/csl/parser.yy [new file with mode: 0644]
src/libmemcached/csl/scanner.l [new file with mode: 0644]
src/libmemcached/csl/server.h [new file with mode: 0644]
src/libmemcached/csl/symbol.h [new file with mode: 0644]
src/libmemcached/delete.cc [new file with mode: 0644]
src/libmemcached/do.cc [new file with mode: 0644]
src/libmemcached/do.hpp [new file with mode: 0644]
src/libmemcached/dump.cc [new file with mode: 0644]
src/libmemcached/encoding_key.cc [new file with mode: 0644]
src/libmemcached/encoding_key.h [new file with mode: 0644]
src/libmemcached/error.cc [new file with mode: 0644]
src/libmemcached/error.hpp [new file with mode: 0644]
src/libmemcached/exist.cc [new file with mode: 0644]
src/libmemcached/fetch.cc [new file with mode: 0644]
src/libmemcached/flag.cc [new file with mode: 0644]
src/libmemcached/flag.hpp [new file with mode: 0644]
src/libmemcached/flush.cc [new file with mode: 0644]
src/libmemcached/flush_buffers.cc [new file with mode: 0644]
src/libmemcached/get.cc [new file with mode: 0644]
src/libmemcached/hash.cc [new file with mode: 0644]
src/libmemcached/hash.hpp [new file with mode: 0644]
src/libmemcached/hosts.cc [new file with mode: 0644]
src/libmemcached/initialize_query.cc [new file with mode: 0644]
src/libmemcached/initialize_query.h [new file with mode: 0644]
src/libmemcached/instance.cc [new file with mode: 0644]
src/libmemcached/instance.hpp [new file with mode: 0644]
src/libmemcached/internal.h [new file with mode: 0644]
src/libmemcached/io.cc [new file with mode: 0644]
src/libmemcached/io.h [new file with mode: 0644]
src/libmemcached/io.hpp [new file with mode: 0644]
src/libmemcached/is.h [new file with mode: 0644]
src/libmemcached/key.cc [new file with mode: 0644]
src/libmemcached/key.hpp [new file with mode: 0644]
src/libmemcached/libmemcached_probes.d [new file with mode: 0644]
src/libmemcached/libmemcached_probes.h [new file with mode: 0644]
src/libmemcached/memcached.cc [new file with mode: 0644]
src/libmemcached/memcached.h [new file with mode: 0644]
src/libmemcached/memcached.hpp [new file with mode: 0644]
src/libmemcached/memcached/README.txt [new file with mode: 0644]
src/libmemcached/memcached/protocol_binary.h [new file with mode: 0644]
src/libmemcached/memcached/vbucket.h [new file with mode: 0644]
src/libmemcached/memory.h [new file with mode: 0644]
src/libmemcached/namespace.cc [new file with mode: 0644]
src/libmemcached/namespace.h [new file with mode: 0644]
src/libmemcached/options.cc [new file with mode: 0644]
src/libmemcached/options.hpp [new file with mode: 0644]
src/libmemcached/parse.cc [new file with mode: 0644]
src/libmemcached/poll.cc [new file with mode: 0644]
src/libmemcached/poll.h [new file with mode: 0644]
src/libmemcached/purge.cc [new file with mode: 0644]
src/libmemcached/quit.cc [new file with mode: 0644]
src/libmemcached/quit.hpp [new file with mode: 0644]
src/libmemcached/response.cc [new file with mode: 0644]
src/libmemcached/response.h [new file with mode: 0644]
src/libmemcached/result.cc [new file with mode: 0644]
src/libmemcached/result.h [new file with mode: 0644]
src/libmemcached/sasl.cc [new file with mode: 0644]
src/libmemcached/sasl.hpp [new file with mode: 0644]
src/libmemcached/server.cc [new file with mode: 0644]
src/libmemcached/server.hpp [new file with mode: 0644]
src/libmemcached/server_instance.h [new file with mode: 0644]
src/libmemcached/server_list.cc [new file with mode: 0644]
src/libmemcached/server_list.hpp [new file with mode: 0644]
src/libmemcached/socket.hpp [new file with mode: 0644]
src/libmemcached/stats.cc [new file with mode: 0644]
src/libmemcached/storage.cc [new file with mode: 0644]
src/libmemcached/strerror.cc [new file with mode: 0644]
src/libmemcached/string.cc [new file with mode: 0644]
src/libmemcached/string.hpp [new file with mode: 0644]
src/libmemcached/touch.cc [new file with mode: 0644]
src/libmemcached/udp.cc [new file with mode: 0644]
src/libmemcached/udp.hpp [new file with mode: 0644]
src/libmemcached/util.h [new file with mode: 0644]
src/libmemcached/util/Makefile.am [new file with mode: 0644]
src/libmemcached/verbosity.cc [new file with mode: 0644]
src/libmemcached/version.cc [new file with mode: 0644]
src/libmemcached/version.hpp [new file with mode: 0644]
src/libmemcached/virtual_bucket.c [new file with mode: 0644]
src/libmemcached/virtual_bucket.h [new file with mode: 0644]
src/libmemcached/watchpoint.h [new file with mode: 0644]
src/libmemcached/windows.hpp [new file with mode: 0644]
src/libmemcachedprotocol/ascii_handler.c [new file with mode: 0644]
src/libmemcachedprotocol/ascii_handler.h [new file with mode: 0644]
src/libmemcachedprotocol/binary_handler.c [new file with mode: 0644]
src/libmemcachedprotocol/binary_handler.h [new file with mode: 0644]
src/libmemcachedprotocol/cache.c [new file with mode: 0644]
src/libmemcachedprotocol/cache.h [new file with mode: 0644]
src/libmemcachedprotocol/common.h [new file with mode: 0644]
src/libmemcachedprotocol/handler.c [new file with mode: 0644]
src/libmemcachedprotocol/pedantic.c [new file with mode: 0644]
src/libmemcachedutil/CMakeLists.txt [new file with mode: 0644]
src/libmemcachedutil/common.h [new file with mode: 0644]
src/libmemcachedutil/flush.cc [new file with mode: 0644]
src/libmemcachedutil/pid.cc [new file with mode: 0644]
src/libmemcachedutil/ping.cc [new file with mode: 0644]
src/libmemcachedutil/pool.cc [new file with mode: 0644]
src/libmemcachedutil/version.cc [new file with mode: 0644]
src/libtest/CMakeLists.txt [new file with mode: 0644]
src/libtest/alarm.cc [new file with mode: 0644]
src/libtest/alarm.h [new file with mode: 0644]
src/libtest/backtrace_test.cc [new file with mode: 0644]
src/libtest/binaries.cc [new file with mode: 0644]
src/libtest/binaries.h [new file with mode: 0644]
src/libtest/blobslap_worker.cc [new file with mode: 0644]
src/libtest/blobslap_worker.h [new file with mode: 0644]
src/libtest/callbacks.h [new file with mode: 0644]
src/libtest/client.cc [new file with mode: 0644]
src/libtest/client.hpp [new file with mode: 0644]
src/libtest/cmdline.cc [new file with mode: 0644]
src/libtest/cmdline.h [new file with mode: 0644]
src/libtest/collection.cc [new file with mode: 0644]
src/libtest/collection.h [new file with mode: 0644]
src/libtest/common.h [new file with mode: 0644]
src/libtest/comparison.cc [new file with mode: 0644]
src/libtest/comparison.hpp [new file with mode: 0644]
src/libtest/core.cc [new file with mode: 0644]
src/libtest/core.h [new file with mode: 0644]
src/libtest/core_count.cc [new file with mode: 0644]
src/libtest/cpu.cc [new file with mode: 0644]
src/libtest/cpu.hpp [new file with mode: 0644]
src/libtest/dns.cc [new file with mode: 0644]
src/libtest/dns.hpp [new file with mode: 0644]
src/libtest/dream.cc [new file with mode: 0644]
src/libtest/dream.h [new file with mode: 0644]
src/libtest/drizzled.cc [new file with mode: 0644]
src/libtest/drizzled.h [new file with mode: 0644]
src/libtest/error.h [new file with mode: 0644]
src/libtest/exception.cc [new file with mode: 0644]
src/libtest/exception.hpp [new file with mode: 0644]
src/libtest/exception/disconnected.hpp [new file with mode: 0644]
src/libtest/exception/fatal.cc [new file with mode: 0644]
src/libtest/exception/fatal.hpp [new file with mode: 0644]
src/libtest/failed.cc [new file with mode: 0644]
src/libtest/formatter.cc [new file with mode: 0644]
src/libtest/formatter.hpp [new file with mode: 0644]
src/libtest/framework.cc [new file with mode: 0644]
src/libtest/framework.h [new file with mode: 0644]
src/libtest/gearmand.cc [new file with mode: 0644]
src/libtest/gearmand.h [new file with mode: 0644]
src/libtest/get.h [new file with mode: 0644]
src/libtest/has.cc [new file with mode: 0644]
src/libtest/has.hpp [new file with mode: 0644]
src/libtest/http.cc [new file with mode: 0644]
src/libtest/http.hpp [new file with mode: 0644]
src/libtest/is_local.cc [new file with mode: 0644]
src/libtest/is_local.hpp [new file with mode: 0644]
src/libtest/is_pid.hpp [new file with mode: 0644]
src/libtest/killpid.cc [new file with mode: 0644]
src/libtest/killpid.h [new file with mode: 0644]
src/libtest/libtool.cc [new file with mode: 0644]
src/libtest/libtool.hpp [new file with mode: 0644]
src/libtest/lite.h [new file with mode: 0644]
src/libtest/main.cc [new file with mode: 0644]
src/libtest/memcached.cc [new file with mode: 0644]
src/libtest/memcached.h [new file with mode: 0644]
src/libtest/memcached.hpp [new file with mode: 0644]
src/libtest/poll_error.hpp [new file with mode: 0644]
src/libtest/port.cc [new file with mode: 0644]
src/libtest/port.h [new file with mode: 0644]
src/libtest/result.cc [new file with mode: 0644]
src/libtest/result.hpp [new file with mode: 0644]
src/libtest/result/base.hpp [new file with mode: 0644]
src/libtest/result/fail.hpp [new file with mode: 0644]
src/libtest/result/skip.hpp [new file with mode: 0644]
src/libtest/result/success.hpp [new file with mode: 0644]
src/libtest/run-ci.gdb [new file with mode: 0644]
src/libtest/run.gdb [new file with mode: 0644]
src/libtest/runner.cc [new file with mode: 0644]
src/libtest/runner.h [new file with mode: 0644]
src/libtest/server.cc [new file with mode: 0644]
src/libtest/server.h [new file with mode: 0644]
src/libtest/server_container.cc [new file with mode: 0644]
src/libtest/server_container.h [new file with mode: 0644]
src/libtest/signal.cc [new file with mode: 0644]
src/libtest/signal.h [new file with mode: 0644]
src/libtest/skiptest.cc [new file with mode: 0644]
src/libtest/socket.cc [new file with mode: 0644]
src/libtest/socket.hpp [new file with mode: 0644]
src/libtest/stream.h [new file with mode: 0644]
src/libtest/strerror.cc [new file with mode: 0644]
src/libtest/strerror.h [new file with mode: 0644]
src/libtest/string.hpp [new file with mode: 0644]
src/libtest/test.h [new file with mode: 0644]
src/libtest/test.hpp [new file with mode: 0644]
src/libtest/thread.hpp [new file with mode: 0644]
src/libtest/timer.cc [new file with mode: 0644]
src/libtest/timer.hpp [new file with mode: 0644]
src/libtest/tmpfile.cc [new file with mode: 0644]
src/libtest/tmpfile.hpp [new file with mode: 0644]
src/libtest/unittest.cc [new file with mode: 0644]
src/libtest/valgrind.h [new file with mode: 0644]
src/libtest/vchar.cc [new file with mode: 0644]
src/libtest/vchar.hpp [new file with mode: 0644]
src/libtest/version.h.in [new file with mode: 0644]
src/libtest/visibility.h [new file with mode: 0644]
src/libtest/wait.cc [new file with mode: 0644]
src/libtest/wait.h [new file with mode: 0644]
src/libtest/yatl.h [new file with mode: 0644]
src/libtest/yatlcon.h.in [new file with mode: 0644]
src/mem_config.h.in [new file with mode: 0644]
src/util/daemon.cc [new file with mode: 0644]
src/util/daemon.hpp [new file with mode: 0644]
src/util/instance.cc [new file with mode: 0644]
src/util/instance.hpp [new file with mode: 0644]
src/util/log.hpp [new file with mode: 0644]
src/util/logfile.cc [new file with mode: 0644]
src/util/logfile.hpp [new file with mode: 0644]
src/util/operation.cc [new file with mode: 0644]
src/util/operation.hpp [new file with mode: 0644]
src/util/pidfile.cc [new file with mode: 0644]
src/util/pidfile.hpp [new file with mode: 0644]
src/util/signal.cc [new file with mode: 0644]
src/util/signal.hpp [new file with mode: 0644]
src/util/string.hpp [new file with mode: 0644]
src/win32/wrappers.h [new file with mode: 0644]
tests/CMakeLists.txt
tests/cli.am [deleted file]
tests/libmemcached-1.0/CMakeLists.txt
tests/libmemcached-1.0/atomsmasher.cc
tests/libmemcached-1.0/generate.cc
tests/libmemcached-1.0/mem_functions.cc
tests/memcapable.cc
tests/memcat.cc
tests/memcp.cc
tests/memdump.cc
tests/memerror.cc
tests/memexist.cc
tests/memflush.cc
tests/memping.cc
tests/memrm.cc
tests/memslap.cc
tests/memstat.cc
tests/memtouch.cc
util/daemon.cc [deleted file]
util/daemon.hpp [deleted file]
util/instance.cc [deleted file]
util/instance.hpp [deleted file]
util/log.hpp [deleted file]
util/logfile.cc [deleted file]
util/logfile.hpp [deleted file]
util/operation.cc [deleted file]
util/operation.hpp [deleted file]
util/pidfile.cc [deleted file]
util/pidfile.hpp [deleted file]
util/signal.cc [deleted file]
util/signal.hpp [deleted file]
util/string.hpp [deleted file]
win32/wrappers.h [deleted file]

index d2b042d4b420783c1525d799d9cb0eef8ecc087a..dffd1bf99d494ded8424e5bc8c6f0415cced0be1 100644 (file)
@@ -1,6 +1,5 @@
 *~
 *.log
-*.trs
 *.exe
 *.gz
 *.lo
 .idea/
 .project
 .settings/
-INSTALL
-Makefile
-Makefile.in
-TAGS
-aclocal.m4
-aminclude.am
-artifacts
-autom4te.cache
-autoscan.log
-build-aux/
-clients/memaslap
-clients/memcapable
-clients/memcat
-clients/memcp
-clients/memdump
-clients/memerror
-clients/memexist
-clients/memflush
-clients/memparse
-clients/memping
-clients/memrm
-clients/memslap
-clients/memstat
-clients/memtouch
+src/bin/memaslap
+src/bin/memcapable
+src/bin/memcat
+src/bin/memcp
+src/bin/memdump
+src/bin/memerror
+src/bin/memexist
+src/bin/memflush
+src/bin/memparse
+src/bin/memping
+src/bin/memrm
+src/bin/memslap
+src/bin/memstat
+src/bin/memtouch
 cmake-build-*/
-config.cache
-config.log
-config.status
-config/compile
-config/config.guess
-config/config.sub
-config/depcomp
-config/install-sh
-config/ltmain.sh
-config/missing
-config/pandora_vc_revinfo
-config/top.h
-configure
-configure.scan
-docs/*.[13]
-docs/*.html
-docs/build
-docs/changes
-docs/source/conf.py
-docs/doctest/
-docs/doctrees/
-docs/html/
-docs/linkcheck/
-docs/text
 example/memcached_light
 example/t/memcached_light
-libhashkit-1.0/configure.h
-libhashkit/hashkitcon.h
-libmemcached-1.0/configure.h
-libmemcached-1.0/t/c_sasl_test
-libmemcached-1.0/t/c_test
-libmemcached-1.0/t/cc_test
-libmemcached-1.2/configure.h
-libmemcached-2.0/configure.h
-libmemcached-?.??/
-libmemcached/configure.h
-libmemcached/csl/parser.cc
-libmemcached/csl/parser.h
-libmemcached/csl/scanner.cc
-libmemcached/csl/scanner.h
-libmemcached/dtrace_probes.h
-libmemcached/generated_probes.h
-libmemcached/memcached_configure.h
-libtest/.hg/
-libtest/.hgignore
-libtest/abort
-libtest/backtrace
-libtest/core-count
-libtest/skiptest
-libtest/unittest
-libtest/version.h
-libtest/wait
-libtest/yatlcon.h
-libtool
-m4/libtool.m4
-m4/libtool.m4 
-m4/ltoptions.m4
-m4/ltsugar.m4
-m4/ltversion.m4
-m4/lt~obsolete.m4
-man/*.1
-man/*.3
-man/*.8
-man/.doctrees/
-mem_config.h
-mem_config.in
-out
-patch
-patch2
-stamp-h1
-support/example.cnf
-support/Makefile
-support/Makefile.in
-support/libmemcached-fc.spec
-support/libmemcached.pc
-support/libmemcached.spec
 tags
-tests/atomsmasher
-tests/c_sasl_test
-tests/c_test
-tests/cycle
-tests/failure
-tests/hash_plus
-tests/hashplus
-tests/internals
-tests/libmemcached-1.0/internals
-tests/libmemcached-1.0/sasl
-tests/libmemcached-1.0/testapp
-tests/libmemcached-1.0/testsocket
-tests/memcapable
-tests/memcat
-tests/memcp
-tests/memdump
-tests/memerror
-tests/memexist
-tests/memflush
-tests/memping
-tests/memplus
-tests/memrm
-tests/memslap
-tests/memstat
-tests/memtouch
-tests/output.cmp
-tests/parser
-tests/sasl
-tests/startservers
-tests/testapp
-tests/testhashkit
-tests/testplus
-tests/testudp
-tests/var/
-tmp_chroot
-unittests/unittests
 venv/
 /infer-out/
-/gh-pages/
-/gh-pages-build/
+/docs/gh-pages/source/
+/docs/gh-pages/build/
index 1f12aaca80600960f630c5929b3f7ba070b2c9a1..36ca49888eee470476afaa34c9419cfd0b09aa2b 100644 (file)
@@ -17,7 +17,13 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON)
 
 include(CMakeConfig.txt)
 
-include_directories(${CMAKE_BINARY_DIR})
+foreach(INCLUDE IN ITEMS ${CMAKE_BINARY_DIR} .)
+    include_directories(
+            ${INCLUDE}/
+            ${INCLUDE}/include
+            ${INCLUDE}/src
+            )
+endforeach()
 set(AUTOHEADER_FILE mem_config.h)
 
 set(CLIENTS
@@ -36,21 +42,14 @@ set(CLIENTS
         memtouch
         )
 
-add_subdirectory(clients)
-add_subdirectory(libhashkit)
-add_subdirectory(libhashkit-1.0)
-add_subdirectory(libmemcached)
-add_subdirectory(libmemcached-1.0)
-add_subdirectory(libmemcachedutil)
-add_subdirectory(libmemcachedutil-1.0)
+add_subdirectory(include)
+add_subdirectory(src)
+add_subdirectory(docs)
+add_subdirectory(support)
 
 if(BUILD_TESTING)
-    add_subdirectory(libtest)
     add_subdirectory(tests)
 endif()
 
-add_subdirectory(docs)
-add_subdirectory(support)
-
 # keep last
-configure_file(mem_config.h.in ${CMAKE_BINARY_DIR}/${AUTOHEADER_FILE} @ONLY)
+configure_file(src/mem_config.h.in ${AUTOHEADER_FILE} @ONLY)
diff --git a/COPYING b/COPYING
index 0957f61a165dfb312a6def5805939c0151fc1fb6..0985e79d873b7507f6773f7f924203abdf2d163f 100644 (file)
--- a/COPYING
+++ b/COPYING
@@ -1,32 +1,29 @@
-Software License Agreement (BSD License)
+Copyright (c) 2011-2013 Brian Aker, DataDifferential, https://datadifferential.com/
+Copyright (c) 2020 Michael Wallner, SmugMug Inc, https://smugmug.com/
 
-Copyright (c) 2012, Data Differential (http://datadifferential.com/)
 All rights reserved.
 
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
 
-    * Redistributions of source code must retain the above copyright
-notice, this list of conditions and the following disclaimer.
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
 
-    * Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the following disclaimer
-in the documentation and/or other materials provided with the
-distribution.
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
 
-    * Neither the name of TangentOrg nor the names of its
-contributors may be used to endorse or promote products derived from
-this software without specific prior written permission.
+3. Neither the name of the copyright holder nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.FIRST b/README.FIRST
deleted file mode 100644 (file)
index 7c93b9b..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-Hi!
-
-If you are getting this code from http://launchpad.net/libmemcached then
-continue reading. Otherwise these directions are not for you (well maybe...).
-
-To obtain code from http://bazaar.launchpad.net/libmemcached you will need to
-issue the following command:
-
-bzr branch lp:libmemcached
-
-Once the tree is cloned you will need to build the "configure" script. You
-can do this by running the script:
-
-./bootstrap.sh autoreconf
-
-It will set up all of the files you need to build libmemcached. At that
-point it is just the typical "./configure; make; make test; make install"
-
-For a tarball release do a "make dist" and for an RPM type "make rpm".
-
-For patches, we prefer you push a branch to launchpad and then submit that 
-branch to be merged. For more information, see:
-
-https://help.launchpad.net/Code/UploadingABranch
-https://help.launchpad.net/Code/Review
-
-Thanks and keep hacking!
-
-Cheers,
-  -Brian
-  Seattle, WA.
diff --git a/clients/CMakeLists.txt b/clients/CMakeLists.txt
deleted file mode 100644 (file)
index b7815db..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-
-add_library(libclient_utilities STATIC utilities.cc generator.cc execute.cc)
-add_library(client_utilities ALIAS libclient_utilities)
-target_include_directories(libclient_utilities PRIVATE ..)
-target_link_libraries(libclient_utilities libmemcachedinternal)
-
-foreach(CLIENT IN LISTS CLIENTS)
-    add_executable(${CLIENT} ${CLIENT}.cc)
-    target_include_directories(${CLIENT} PRIVATE ..)
-    target_link_libraries(${CLIENT} libclient_utilities)
-    install(TARGETS ${CLIENT}
-            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-endforeach()
-
-# extra sources
-
-target_sources(memcapable PRIVATE ../libmemcached/byteorder.cc)
-
-# extra libs
-
-target_link_libraries(memcapable Threads::Threads)
-target_link_libraries(memping libmemcachedutil)
-target_link_libraries(memslap Threads::Threads)
-
-# memaslap is special
-
-if(ENABLE_MEMASLAP)
-    if(LIBEVENT AND HAVE_C_STDATOMIC)
-        add_executable(memaslap memaslap.c
-                ms_conn.c ms_setting.c ms_sigsegv.c ms_stats.c ms_task.c ms_thread.c)
-        target_include_directories(memaslap PRIVATE .. ${LIBEVENT_INCLUDEDIR})
-        target_link_libraries(memaslap libclient_utilities ${LIBEVENT_LIBRARIES} Threads::Threads)
-        install(TARGETS memaslap
-                RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-    endif()
-endif()
diff --git a/clients/client_options.h b/clients/client_options.h
deleted file mode 100644 (file)
index 16ce4be..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-#pragma once
-
-typedef struct memcached_help_text_st memcached_help_text_st;
-
-enum memcached_options {
-  OPT_SERVERS= 's',
-  OPT_VERSION= 'V',
-  OPT_HELP= 'h',
-  OPT_VERBOSE= 'v',
-  OPT_DEBUG= 'd',
-  OPT_ANALYZE= 'a',
-  OPT_FLAG= 257,
-  OPT_EXPIRE,
-  OPT_SET,
-  OPT_REPLACE,
-  OPT_ADD,
-  OPT_SLAP_EXECUTE_NUMBER,
-  OPT_SLAP_INITIAL_LOAD,
-  OPT_SLAP_TEST,
-  OPT_SLAP_CONCURRENCY,
-  OPT_SLAP_NON_BLOCK,
-  OPT_SLAP_TCP_NODELAY,
-  OPT_FLUSH,
-  OPT_HASH,
-  OPT_BINARY,
-  OPT_UDP,
-  OPT_BUFFER,
-  OPT_USERNAME,
-  OPT_PASSWD,
-  OPT_STAT_ARGS,
-  OPT_SERVER_VERSION,
-  OPT_QUIET,
-  OPT_FILE= 'f'
-};
diff --git a/clients/execute.cc b/clients/execute.cc
deleted file mode 100644 (file)
index 4731977..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-/*
-  Execute a memcached_set() a set of pairs.
-  Return the number of rows set.
-*/
-
-#include <mem_config.h>
-#include "clients/execute.h"
-
-unsigned int execute_set(memcached_st *memc, pairs_st *pairs, unsigned int number_of)
-{
-  uint32_t count= 0;
-  for (; count < number_of; ++count)
-  {
-    memcached_return_t rc= memcached_set(memc, pairs[count].key, pairs[count].key_length,
-                                         pairs[count].value, pairs[count].value_length,
-                                         0, 0);
-    if (memcached_failed(rc))
-    {
-      fprintf(stderr, "%s:%d Failure on %u insert (%s) of %.*s\n",
-              __FILE__, __LINE__, count,
-              memcached_last_error_message(memc),
-              (unsigned int)pairs[count].key_length, pairs[count].key);
-      
-      // We will try to reconnect and see if that fixes the issue
-      memcached_quit(memc);
-
-      return count;
-    }
-  }
-
-  return count;
-}
-
-/*
-  Execute a memcached_get() on a set of pairs.
-  Return the number of rows retrieved.
-*/
-unsigned int execute_get(memcached_st *memc, pairs_st *pairs, unsigned int number_of)
-{
-  unsigned int x;
-  unsigned int retrieved;
-
-
-  for (retrieved= 0,x= 0; x < number_of; x++)
-  {
-    size_t value_length;
-    uint32_t flags;
-
-    unsigned int fetch_key= (unsigned int)((unsigned int)random() % number_of);
-
-    memcached_return_t rc;
-    char *value= memcached_get(memc, pairs[fetch_key].key, pairs[fetch_key].key_length,
-                               &value_length, &flags, &rc);
-
-    if (memcached_failed(rc))
-    {
-      fprintf(stderr, "%s:%d Failure on read(%s) of %.*s\n",
-              __FILE__, __LINE__,
-              memcached_last_error_message(memc),
-              (unsigned int)pairs[fetch_key].key_length, pairs[fetch_key].key);
-    }
-    else
-    {
-      retrieved++;
-    }
-
-    ::free(value);
-  }
-
-  return retrieved;
-}
-
-/**
- * Callback function to count the number of results
- */
-static memcached_return_t callback_counter(const memcached_st *ptr,
-                                           memcached_result_st *result,
-                                           void *context)
-{
-  (void)ptr;
-  (void)result;
-  unsigned int *counter= (unsigned int *)context;
-  *counter= *counter + 1;
-
-  return MEMCACHED_SUCCESS;
-}
-
-/**
- * Try to run a large mget to get all of the keys
- * @param memc memcached handle
- * @param keys the keys to get
- * @param key_length the length of the keys
- * @param number_of the number of keys to try to get
- * @return the number of keys received
- */
-unsigned int execute_mget(memcached_st *memc,
-                          const char * const *keys,
-                          size_t *key_length,
-                          unsigned int number_of)
-{
-  unsigned int retrieved= 0;
-  memcached_execute_fn callbacks[]= { callback_counter };
-  memcached_return_t rc;
-  rc= memcached_mget_execute(memc, keys, key_length,
-                             (size_t)number_of, callbacks, &retrieved, 1);
-
-  if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_NOTFOUND ||
-          rc == MEMCACHED_BUFFERED || rc == MEMCACHED_END)
-  {
-    rc= memcached_fetch_execute(memc, callbacks, (void *)&retrieved, 1);
-    if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_NOTFOUND && rc != MEMCACHED_END)
-    {
-      fprintf(stderr, "%s:%d Failed to execute mget: %s\n",
-              __FILE__, __LINE__,
-              memcached_strerror(memc, rc));
-      memcached_quit(memc);
-      return 0;
-    }
-  }
-  else
-  {
-    fprintf(stderr, "%s:%d Failed to execute mget: %s\n",
-            __FILE__, __LINE__,
-            memcached_strerror(memc, rc));
-    memcached_quit(memc);
-    return 0;
-  }
-
-  return retrieved;
-}
diff --git a/clients/execute.h b/clients/execute.h
deleted file mode 100644 (file)
index ebf92f6..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-#pragma once 
-
-#include <stdio.h>
-
-#include <libmemcached-1.0/memcached.h>
-#include "clients/generator.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-unsigned int execute_set(memcached_st *memc, pairs_st *pairs, unsigned int number_of);
-unsigned int execute_get(memcached_st *memc, pairs_st *pairs, unsigned int number_of);
-unsigned int execute_mget(memcached_st *memc, const char * const *keys, size_t *key_length,
-                          unsigned int number_of);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/clients/generator.cc b/clients/generator.cc
deleted file mode 100644 (file)
index 1f40dae..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-#include <mem_config.h>
-
-#include <stdint.h>
-
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <iostream>
-#include <unistd.h>
-
-#include "clients/generator.h"
-
-#define KEY_BYTES 20
-
-/* Use this for string generation */
-static const char ALPHANUMERICS[]=
-  "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
-
-#define ALPHANUMERICS_SIZE (sizeof(ALPHANUMERICS)-1)
-
-static size_t get_alpha_num(void)
-{
-  return (size_t)random() % ALPHANUMERICS_SIZE;
-}
-
-void get_random_string(char *buffer, size_t size)
-{
-  char *buffer_ptr= buffer;
-
-  while (--size)
-  {
-    *buffer_ptr++= ALPHANUMERICS[get_alpha_num()];
-  }
-  *buffer_ptr++= ALPHANUMERICS[get_alpha_num()];
-}
-
-void pairs_free(pairs_st *pairs)
-{
-  if (pairs == NULL)
-  {
-    return;
-  }
-
-  /* We free until we hit the null pair we stores during creation */
-  for (uint32_t x= 0; pairs[x].key; x++)
-  {
-    free(pairs[x].key);
-    if (pairs[x].value)
-    {
-      free(pairs[x].value);
-    }
-  }
-
-  free(pairs);
-}
-
-pairs_st *pairs_generate(uint64_t number_of, size_t value_length)
-{
-  pairs_st *pairs= (pairs_st*)calloc((size_t)number_of + 1, sizeof(pairs_st));
-
-  if (pairs == NULL)
-  {
-    goto error;
-  }
-
-  for (uint64_t x= 0; x < number_of; x++)
-  {
-    pairs[x].key= (char *)calloc(KEY_BYTES, sizeof(char));
-
-    if (pairs[x].key == NULL)
-      goto error;
-
-    get_random_string(pairs[x].key, KEY_BYTES);
-    pairs[x].key_length= KEY_BYTES;
-
-    if (value_length)
-    {
-      pairs[x].value= (char *)calloc(value_length, sizeof(char));
-
-      if (pairs[x].value == NULL)
-        goto error;
-
-      get_random_string(pairs[x].value, value_length);
-      pairs[x].value_length= value_length;
-    }
-    else
-    {
-      pairs[x].value= NULL;
-      pairs[x].value_length= 0;
-    }
-  }
-
-  return pairs;
-error:
-  std::cerr << "Memory Allocation failure in pairs_generate." << std::endl;
-  exit(EXIT_SUCCESS);
-}
diff --git a/clients/generator.h b/clients/generator.h
deleted file mode 100644 (file)
index e60bfb3..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-/*
-  Code to generate data to be pushed into memcached
-*/
-
-#pragma once
-
-typedef struct pairs_st pairs_st;
-
-struct pairs_st {
-  char *key;
-  size_t key_length;
-  char *value;
-  size_t value_length;
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-pairs_st *pairs_generate(uint64_t number_of, size_t value_length);
-void pairs_free(pairs_st *pairs);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/clients/memaslap.c b/clients/memaslap.c
deleted file mode 100644 (file)
index dc41135..0000000
+++ /dev/null
@@ -1,917 +0,0 @@
-/*
- *  memslap
- *
- *  (c) Copyright 2009, Schooner Information Technology, Inc.
- *  All rights reserved.
- *  http://www.schoonerinfotech.com/
- *
- *  Use and distribution licensed under the BSD license.  See
- *  the COPYING file for full text.
- *
- *  Authors:
- *      Brian Aker
- *      Mingqiang Zhuang <mingqiangzhuang@hengtiansoft.com>
- *
- */
-#include "mem_config.h"
-
-#include <stdlib.h>
-#include <getopt.h>
-#include <limits.h>
-
-#if defined(HAVE_SYS_TIME_H)
-# include <sys/time.h>
-#endif
-
-#if defined(HAVE_TIME_H)
-# include <time.h>
-#endif
-
-
-#include "ms_sigsegv.h"
-#include "ms_setting.h"
-#include "ms_thread.h"
-
-#define PROGRAM_NAME    "memslap"
-#define PROGRAM_DESCRIPTION \
-                        "Generates workload against memcached servers."
-
-#ifdef __sun
-  /* For some odd reason the option struct on solaris defines the argument
-   * as char* and not const char*
-   */
-#define OPTIONSTRING char*
-#else
-#define OPTIONSTRING const char*
-#endif
-
-/* options */
-static struct option long_options[]=
-{
-  { (OPTIONSTRING)"servers",        required_argument,            NULL,
-    OPT_SERVERS            },
-  { (OPTIONSTRING)"threads",        required_argument,            NULL,
-    OPT_THREAD_NUMBER      },
-  { (OPTIONSTRING)"concurrency",    required_argument,            NULL,
-    OPT_CONCURRENCY        },
-  { (OPTIONSTRING)"conn_sock",      required_argument,            NULL,
-    OPT_SOCK_PER_CONN      },
-  { (OPTIONSTRING)"execute_number", required_argument,            NULL,
-    OPT_EXECUTE_NUMBER     },
-  { (OPTIONSTRING)"time",           required_argument,            NULL,
-    OPT_TIME               },
-  { (OPTIONSTRING)"cfg_cmd",        required_argument,            NULL,
-    OPT_CONFIG_CMD         },
-  { (OPTIONSTRING)"win_size",       required_argument,            NULL,
-    OPT_WINDOW_SIZE        },
-  { (OPTIONSTRING)"fixed_size",     required_argument,            NULL,
-    OPT_FIXED_LTH          },
-  { (OPTIONSTRING)"verify",         required_argument,            NULL,
-    OPT_VERIFY             },
-  { (OPTIONSTRING)"division",       required_argument,            NULL,
-    OPT_GETS_DIVISION      },
-  { (OPTIONSTRING)"stat_freq",      required_argument,            NULL,
-    OPT_STAT_FREQ          },
-  { (OPTIONSTRING)"exp_verify",     required_argument,            NULL,
-    OPT_EXPIRE             },
-  { (OPTIONSTRING)"overwrite",      required_argument,            NULL,
-    OPT_OVERWRITE          },
-  { (OPTIONSTRING)"reconnect",      no_argument,                  NULL,
-    OPT_RECONNECT          },
-  { (OPTIONSTRING)"udp",            no_argument,                  NULL,
-    OPT_UDP                },
-  { (OPTIONSTRING)"facebook",       no_argument,                  NULL,
-    OPT_FACEBOOK_TEST      },
-  { (OPTIONSTRING)"binary",         no_argument,                  NULL,
-    OPT_BINARY_PROTOCOL    },
-  { (OPTIONSTRING)"tps",            required_argument,            NULL,
-    OPT_TPS                },
-  { (OPTIONSTRING)"rep_write",      required_argument,            NULL,
-    OPT_REP_WRITE_SRV      },
-  { (OPTIONSTRING)"verbose",        no_argument,                  NULL,
-    OPT_VERBOSE            },
-  { (OPTIONSTRING)"help",           no_argument,                  NULL,
-    OPT_HELP               },
-  { (OPTIONSTRING)"version",        no_argument,                  NULL,
-    OPT_VERSION            },
-  { 0, 0, 0, 0 },
-};
-
-/* Prototypes */
-static void ms_sync_lock_init(void);
-static void ms_sync_lock_destroy(void);
-static void ms_global_struct_init(void);
-static void ms_global_struct_destroy(void);
-static void ms_version_command(const char *command_name);
-static const char *ms_lookup_help(ms_options_t option);
-static int64_t ms_parse_time(void);
-static int64_t ms_parse_size(void);
-static void ms_options_parse(int argc, char *argv[]);
-static int ms_check_para(void);
-static void ms_statistic_init(void);
-static void ms_stats_init(void);
-static void ms_print_statistics(int in_time);
-static void ms_print_memslap_stats(struct timeval *start_time,
-                                   struct timeval *end_time);
-static void ms_monitor_slap_mode(void);
-
-/**
- * output the help information
- *
- * @param command_name, the string of this process
- * @param description, description of this process
- * @param long_options, global options array
- */
-static __attribute__((noreturn)) void ms_help_command(const char *command_name, const char *description)
-{
-  char *help_message= NULL;
-
-  printf("%s v%u.%u\n", command_name, 1U, 0U);
-  printf("    %s\n\n", description);
-  printf(
-    "Usage:\n"
-    "    memslap -hV | -s servers [-F config_file] [-t time | -x exe_num] [...]\n\n"
-    "Options:\n");
-
-  for (int x= 0; long_options[x].name; x++)
-  {
-    printf("    -%c, --%s%c\n", long_options[x].val, long_options[x].name,
-           long_options[x].has_arg ? '=' : ' ');
-
-    if ((help_message= (char *)ms_lookup_help(long_options[x].val)) != NULL)
-    {
-      printf("        %s\n", help_message);
-    }
-  }
-
-  printf(
-    "\nExamples:\n"
-    "    memslap -s 127.0.0.1:11211 -S 5s\n"
-    "    memslap -s 127.0.0.1:11211 -t 2m -v 0.2 -e 0.05 -b\n"
-    "    memslap -s 127.0.0.1:11211 -F config -t 2m -w 40k -S 20s -o 0.2\n"
-    "    memslap -s 127.0.0.1:11211 -F config -t 2m -T 4 -c 128 -d 20 -P 40k\n"
-    "    memslap -s 127.0.0.1:11211 -F config -t 2m -d 50 -a -n 40\n"
-    "    memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m\n"
-    "    memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m -p 2\n\n");
-
-  exit(0);
-} /* ms_help_command */
-
-
-/* initialize the global locks */
-static void ms_sync_lock_init()
-{
-  ms_global.init_lock.count= 0;
-  pthread_mutex_init(&ms_global.init_lock.lock, NULL);
-  pthread_cond_init(&ms_global.init_lock.cond, NULL);
-
-  ms_global.warmup_lock.count = 0;
-  pthread_mutex_init(&ms_global.warmup_lock.lock, NULL);
-  pthread_cond_init(&ms_global.warmup_lock.cond, NULL);
-
-  ms_global.run_lock.count= 0;
-  pthread_mutex_init(&ms_global.run_lock.lock, NULL);
-  pthread_cond_init(&ms_global.run_lock.cond, NULL);
-
-  pthread_mutex_init(&ms_global.quit_mutex, NULL);
-  pthread_mutex_init(&ms_global.seq_mutex, NULL);
-} /* ms_sync_lock_init */
-
-
-/* destroy the global locks */
-static void ms_sync_lock_destroy()
-{
-  pthread_mutex_destroy(&ms_global.init_lock.lock);
-  pthread_cond_destroy(&ms_global.init_lock.cond);
-
-  pthread_mutex_destroy(&ms_global.warmup_lock.lock);
-  pthread_cond_destroy(&ms_global.warmup_lock.cond);
-
-  pthread_mutex_destroy(&ms_global.run_lock.lock);
-  pthread_cond_destroy(&ms_global.run_lock.cond);
-
-  pthread_mutex_destroy(&ms_global.quit_mutex);
-  pthread_mutex_destroy(&ms_global.seq_mutex);
-
-  if (ms_setting.stat_freq > 0)
-  {
-    pthread_mutex_destroy(&ms_statistic.stat_mutex);
-  }
-} /* ms_sync_lock_destroy */
-
-
-/* initialize the global structure */
-static void ms_global_struct_init()
-{
-  ms_sync_lock_init();
-  ms_global.finish_warmup= false;
-  ms_global.time_out= false;
-}
-
-
-/* destroy the global structure */
-static void ms_global_struct_destroy()
-{
-  ms_sync_lock_destroy();
-}
-
-
-/**
- * output the version information
- *
- * @param command_name, the string of this process
- */
-static void ms_version_command(const char *command_name)
-{
-  printf("%s v%u.%u\n", command_name, 1U, 0U);
-  exit(0);
-}
-
-
-/**
- * get the description of the option
- *
- * @param option, option of command line
- *
- * @return char*, description of the command option
- */
-static const char *ms_lookup_help(ms_options_t option)
-{
-  switch (option)
-  {
-  case OPT_SERVERS:
-    return
-      "List one or more servers to connect. Servers count must be less than\n"
-      "        threads count. e.g.: --servers=localhost:1234,localhost:11211";
-
-  case OPT_VERSION:
-    return "Display the version of the application and then exit.";
-
-  case OPT_HELP:
-    return "Display this message and then exit.";
-
-  case OPT_EXECUTE_NUMBER:
-    return "Number of operations(get and set) to execute for the\n"
-           "        given test. Default 1000000.";
-
-  case OPT_THREAD_NUMBER:
-    return
-      "Number of threads to startup, better equal to CPU numbers. Default 8.";
-
-  case OPT_CONCURRENCY:
-    return "Number of concurrency to simulate with load. Default 128.";
-
-  case OPT_FIXED_LTH:
-    return "Fixed length of value.";
-
-  case OPT_VERIFY:
-    return "The proportion of date verification, e.g.: --verify=0.01";
-
-  case OPT_GETS_DIVISION:
-    return "Number of keys to multi-get once. Default 1, means single get.";
-
-  case OPT_TIME:
-    return
-      "How long the test to run, suffix: s-seconds, m-minutes, h-hours,\n"
-      "        d-days e.g.: --time=2h.";
-
-  case OPT_CONFIG_CMD:
-    return
-      "Load the configure file to get command,key and value distribution list.";
-
-  case OPT_WINDOW_SIZE:
-    return
-      "Task window size of each concurrency, suffix: K, M e.g.: --win_size=10k.\n"
-      "        Default 10k.";
-
-  case OPT_UDP:
-    return
-      "UDP support, default memslap uses TCP, TCP port and UDP port of\n"
-      "        server must be same.";
-
-  case OPT_EXPIRE:
-    return
-      "The proportion of objects with expire time, e.g.: --exp_verify=0.01.\n"
-      "        Default no object with expire time";
-
-  case OPT_OVERWRITE:
-    return
-      "The proportion of objects need overwrite, e.g.: --overwrite=0.01.\n"
-      "        Default never overwrite object.";
-
-  case OPT_STAT_FREQ:
-    return
-      "Frequency of dumping statistic information. suffix: s-seconds,\n"
-      "        m-minutes, e.g.: --resp_freq=10s.";
-
-  case OPT_SOCK_PER_CONN:
-    return "Number of TCP socks per concurrency. Default 1.";
-
-  case OPT_RECONNECT:
-    return
-      "Reconnect support, when connection is closed it will be reconnected.";
-
-  case OPT_VERBOSE:
-    return
-      "Whether it outputs detailed information when verification fails.";
-
-  case OPT_FACEBOOK_TEST:
-    return
-      "Whether it enables facebook test feature, set with TCP and multi-get with UDP.";
-
-  case OPT_BINARY_PROTOCOL:
-    return
-      "Whether it enables binary protocol. Default with ASCII protocol.";
-
-  case OPT_TPS:
-    return "Expected throughput, suffix: K, e.g.: --tps=10k.";
-
-  case OPT_REP_WRITE_SRV:
-    return "The first nth servers can write data, e.g.: --rep_write=2.";
-
-  default:
-    return "Forgot to document this option :)";
-  } /* switch */
-} /* ms_lookup_help */
-
-
-/* used to parse the time string  */
-static int64_t ms_parse_time()
-{
-  int64_t ret= 0;
-  char unit= optarg[strlen(optarg) - 1];
-
-  optarg[strlen(optarg) - 1]= '\0';
-  ret= atoi(optarg);
-
-  switch (unit)
-  {
-  case 'd':
-  case 'D':
-    ret*= 24;
-    /* fall through */
-  case 'h':
-  case 'H':
-    ret*= 60;
-    /* fall through */
-  case 'm':
-  case 'M':
-    ret*= 60;
-    /* fall through */
-  case 's':
-  case 'S':
-    break;
-
-  default:
-    ret= -1;
-    break;
-  } /* switch */
-
-  return ret;
-} /* ms_parse_time */
-
-
-/* used to parse the size string */
-static int64_t ms_parse_size()
-{
-  int64_t ret= -1;
-  char unit= optarg[strlen(optarg) - 1];
-
-  optarg[strlen(optarg) - 1]= '\0';
-  errno= 0;
-  ret= strtoll(optarg, (char **)NULL, 10);
-  if (errno != 0)
-  {
-    fprintf(stderr, "strtoll(optarg,..): %s\n", strerror(errno));
-    exit(1);
-  }
-
-  switch (unit)
-  {
-  case 'k':
-  case 'K':
-    ret*= 1024;
-    break;
-
-  case 'm':
-  case 'M':
-    ret*= 1024 * 1024;
-    break;
-
-  case 'g':
-  case 'G':
-    ret*= 1024 * 1024 * 1024;
-    break;
-
-  default:
-    ret= -1;
-    break;
-  } /* switch */
-
-  return ret;
-} /* ms_parse_size */
-
-
-/* used to parse the options of command line */
-static void ms_options_parse(int argc, char *argv[])
-{
-  int option_index= 0;
-  int option_rv;
-
-  while ((option_rv= getopt_long(argc, argv, "VhURbaBs:x:T:c:X:v:d:"
-                                             "t:S:F:w:e:o:n:P:p:",
-                                 long_options, &option_index)) != -1)
-  {
-    switch (option_rv)
-    {
-    case 0:
-      break;
-
-    case OPT_VERSION:     /* --version or -V */
-      ms_version_command(PROGRAM_NAME);
-      break;
-
-    case OPT_HELP:     /* --help or -h */
-      ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION);
-      break;
-
-    case OPT_SERVERS:     /* --servers or -s */
-      ms_setting.srv_str= strdup(optarg);
-      break;
-
-    case OPT_CONCURRENCY:       /* --concurrency or -c */
-      errno= 0;
-      ms_setting.nconns= (uint32_t)strtoul(optarg, (char **) NULL, 10);
-      if (ms_setting.nconns <= 0 || errno != 0)
-      {
-        fprintf(stderr, "Concurrency must be greater than 0.:-)\n");
-        exit(1);
-      }
-      break;
-
-    case OPT_EXECUTE_NUMBER:        /* --execute_number or -x */
-      errno= 0;
-      ms_setting.exec_num= (int)strtol(optarg, (char **) NULL, 10);
-      if (ms_setting.exec_num <= 0 || errno != 0)
-      {
-        fprintf(stderr, "Execute number must be greater than 0.:-)\n");
-        exit(1);
-      }
-      break;
-
-    case OPT_THREAD_NUMBER:     /* --threads or -T */
-      errno= 0;
-      ms_setting.nthreads= (uint32_t)strtoul(optarg, (char **) NULL, 10);
-      if (ms_setting.nthreads <= 0 || errno != 0)
-      {
-        fprintf(stderr, "Threads number must be greater than 0.:-)\n");
-        exit(1);
-      }
-      break;
-
-    case OPT_FIXED_LTH:         /* --fixed_size or -X */
-      errno= 0;
-      ms_setting.fixed_value_size= (size_t)strtoull(optarg, (char **) NULL, 10);
-      if ((ms_setting.fixed_value_size <= 0 || errno != 0)
-          || (ms_setting.fixed_value_size > MAX_VALUE_SIZE))
-      {
-        fprintf(stderr, "Value size must be between 0 and 1M.:-)\n");
-        exit(1);
-      }
-      break;
-
-    case OPT_VERIFY:        /* --verify or -v */
-      ms_setting.verify_percent= atof(optarg);
-      if ((ms_setting.verify_percent <= 0)
-          || (ms_setting.verify_percent > 1.0))
-      {
-        fprintf(stderr, "Data verification rate must be "
-                        "greater than 0 and less than 1.0. :-)\n");
-        exit(1);
-      }
-      break;
-
-    case OPT_GETS_DIVISION:         /* --division or -d */
-      errno= 0;
-      ms_setting.mult_key_num= (int)strtol(optarg, (char **) NULL, 10);
-      if (ms_setting.mult_key_num <= 0 || errno != 0)
-      {
-        fprintf(stderr, "Multi-get key number must be greater than 0.:-)\n");
-        exit(1);
-      }
-      break;
-
-    case OPT_TIME:      /* --time or -t */
-      ms_setting.run_time= (int)ms_parse_time();
-      if (ms_setting.run_time == -1)
-      {
-        fprintf(stderr, "Please specify the run time. :-)\n"
-                        "'s' for second, 'm' for minute, 'h' for hour, "
-                        "'d' for day. e.g.: --time=24h (means 24 hours).\n");
-        exit(1);
-      }
-
-      if (ms_setting.run_time == 0)
-      {
-        fprintf(stderr, "Running time can not be 0. :-)\n");
-        exit(1);
-      }
-      break;
-
-    case OPT_CONFIG_CMD:        /* --cfg_cmd or -F */
-      ms_setting.cfg_file= strdup(optarg);
-      break;
-
-    case OPT_WINDOW_SIZE:       /* --win_size or -w */
-      ms_setting.win_size= (size_t)ms_parse_size();
-      if (ms_setting.win_size == (size_t)-1)
-      {
-        fprintf(
-          stderr,
-          "Please specify the item window size. :-)\n"
-          "e.g.: --win_size=10k (means 10k task window size).\n");
-        exit(1);
-      }
-      break;
-
-    case OPT_UDP:       /* --udp or -U*/
-      ms_setting.udp= true;
-      break;
-
-    case OPT_EXPIRE:        /* --exp_verify or -e */
-      ms_setting.exp_ver_per= atof(optarg);
-      if ((ms_setting.exp_ver_per <= 0) || (ms_setting.exp_ver_per > 1.0))
-      {
-        fprintf(stderr, "Expire time verification rate must be "
-                        "greater than 0 and less than 1.0. :-)\n");
-        exit(1);
-      }
-      break;
-
-    case OPT_OVERWRITE:         /* --overwrite or -o */
-      ms_setting.overwrite_percent= atof(optarg);
-      if ((ms_setting.overwrite_percent <= 0)
-          || (ms_setting.overwrite_percent > 1.0))
-      {
-        fprintf(stderr, "Objects overwrite rate must be "
-                        "greater than 0 and less than 1.0. :-)\n");
-        exit(1);
-      }
-      break;
-
-    case OPT_STAT_FREQ:         /* --stat_freq or -S */
-      ms_setting.stat_freq= (int)ms_parse_time();
-      if (ms_setting.stat_freq == -1)
-      {
-        fprintf(stderr, "Please specify the frequency of dumping "
-                        "statistic information. :-)\n"
-                        "'s' for second, 'm' for minute, 'h' for hour, "
-                        "'d' for day. e.g.: --time=24h (means 24 hours).\n");
-        exit(1);
-      }
-
-      if (ms_setting.stat_freq == 0)
-      {
-        fprintf(stderr, "The frequency of dumping statistic information "
-                        "can not be 0. :-)\n");
-        exit(1);
-      }
-      break;
-
-    case OPT_SOCK_PER_CONN:         /* --conn_sock or -n */
-      errno= 0;
-      ms_setting.sock_per_conn= (uint32_t)strtoul(optarg, (char **) NULL, 10);
-      if (ms_setting.sock_per_conn <= 0 || errno != 0)
-      {
-        fprintf(stderr, "Number of socks of each concurrency "
-                        "must be greater than 0.:-)\n");
-        exit(1);
-      }
-      break;
-
-    case OPT_RECONNECT:     /* --reconnect or -R */
-      ms_setting.reconnect= true;
-      break;
-
-    case OPT_VERBOSE:       /* --verbose or -b */
-      ms_setting.verbose= true;
-      break;
-
-    case OPT_FACEBOOK_TEST:         /* --facebook or -a */
-      ms_setting.facebook_test= true;
-      break;
-
-    case OPT_BINARY_PROTOCOL:       /* --binary or -B */
-      ms_setting.binary_prot_= true;
-      break;
-
-    case OPT_TPS:       /* --tps or -P */
-      ms_setting.expected_tps= (int)ms_parse_size();
-      if (ms_setting.expected_tps == -1)
-      {
-        fprintf(stderr,
-                "Please specify the item expected throughput. :-)\n"
-                "e.g.: --tps=10k (means 10k throughput).\n");
-        exit(1);
-      }
-      break;
-
-    case OPT_REP_WRITE_SRV:         /* --rep_write or -p */
-      errno= 0;
-      ms_setting.rep_write_srv= (uint32_t)strtoul(optarg, (char **) NULL, 10);
-      if (ms_setting.rep_write_srv <= 0 || errno != 0)
-      {
-        fprintf(stderr,
-                "Number of replication writing server must be greater "
-                "than 0.:-)\n");
-        exit(1);
-      }
-      break;
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(1);
-
-    default:
-      abort();
-    } /* switch */
-  }
-} /* ms_options_parse */
-
-
-static int ms_check_para()
-{
-  if (ms_setting.srv_str == NULL)
-  {
-    char *temp;
-
-    if ((temp= getenv("MEMCACHED_SERVERS")))
-    {
-      ms_setting.srv_str= strdup(temp);
-    }
-    else
-    {
-      fprintf(stderr, "No Servers provided\n\n");
-      return -1;
-    }
-  }
-
-  if (ms_setting.nconns % (uint32_t)ms_setting.nthreads != 0)
-  {
-    fprintf(stderr, "Concurrency must be the multiples of threads count.\n");
-    return -1;
-  }
-
-  if (ms_setting.win_size % UNIT_ITEMS_COUNT != 0)
-  {
-    fprintf(stderr, "Window size must be the multiples of 1024.\n\n");
-    return -1;
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_check_para */
-
-
-/* initialize the statistic structure */
-static void ms_statistic_init()
-{
-  pthread_mutex_init(&ms_statistic.stat_mutex, NULL);
-  ms_init_stats(&ms_statistic.get_stat, "Get");
-  ms_init_stats(&ms_statistic.set_stat, "Set");
-  ms_init_stats(&ms_statistic.total_stat, "Total");
-} /* ms_statistic_init */
-
-
-/* initialize the global state structure */
-static void ms_stats_init()
-{
-  memset(&ms_stats, 0, sizeof(ms_stats_t));
-  if (ms_setting.stat_freq > 0)
-  {
-    ms_statistic_init();
-  }
-} /* ms_stats_init */
-
-
-/* use to output the statistic */
-static void ms_print_statistics(int in_time)
-{
-  int obj_size= (int)(ms_setting.avg_key_size + ms_setting.avg_val_size);
-
-  printf("\033[1;1H\033[2J\n");
-  ms_dump_format_stats(&ms_statistic.get_stat, in_time,
-                       ms_setting.stat_freq, obj_size);
-  ms_dump_format_stats(&ms_statistic.set_stat, in_time,
-                       ms_setting.stat_freq, obj_size);
-  ms_dump_format_stats(&ms_statistic.total_stat, in_time,
-                       ms_setting.stat_freq, obj_size);
-} /* ms_print_statistics */
-
-
-/* used to print the states of memslap */
-static void ms_print_memslap_stats(struct timeval *start_time,
-                                   struct timeval *end_time)
-{
-  char buf[1024];
-  char *pos= buf;
-
-  pos+= snprintf(pos,
-                 sizeof(buf), "cmd_get: %lu\n",
-                 (unsigned long) ms_stats.cmd_get);
-  pos+= snprintf(pos,
-                 sizeof(buf) - (size_t)(pos -buf),
-                 "cmd_set: %lu\n",
-                 (unsigned long) ms_stats.cmd_set);
-  pos+= snprintf(pos,
-                 sizeof(buf) - (size_t)(pos -buf),
-                 "get_misses: %lu\n",
-                 (unsigned long) ms_stats.get_misses);
-
-  if (ms_setting.verify_percent > 0)
-  {
-    pos+= snprintf(pos,
-                   sizeof(buf) - (size_t)(pos -buf),
-                   "verify_misses: %lu\n",
-                   (unsigned long) ms_stats.vef_miss);
-    pos+= snprintf(pos,
-                   sizeof(buf) - (size_t)(pos -buf),
-                   "verify_failed: %lu\n",
-                   (unsigned long) ms_stats.vef_failed);
-  }
-
-  if (ms_setting.exp_ver_per > 0)
-  {
-    pos+= snprintf(pos,
-                   sizeof(buf) - (size_t)(pos -buf),
-                   "expired_get: %lu\n",
-                   (unsigned long) ms_stats.exp_get);
-    pos+= snprintf(pos,
-                   sizeof(buf) - (size_t)(pos -buf),
-                   "unexpired_unget: %lu\n",
-                   (unsigned long) ms_stats.unexp_unget);
-  }
-
-  pos+= snprintf(pos,
-                 sizeof(buf) - (size_t)(pos -buf),
-                 "written_bytes: %lu\n",
-                 (unsigned long) ms_stats.bytes_written);
-  pos+= snprintf(pos,
-                 sizeof(buf) - (size_t)(pos -buf),
-                 "read_bytes: %lu\n",
-                 (unsigned long) ms_stats.bytes_read);
-  pos+= snprintf(pos,
-                 sizeof(buf) - (size_t)(pos -buf),
-                 "object_bytes: %lu\n",
-                 (unsigned long) ms_stats.obj_bytes);
-
-  if (ms_setting.udp || ms_setting.facebook_test)
-  {
-    pos+= snprintf(pos,
-                   sizeof(buf) - (size_t)(pos -buf),
-                   "packet_disorder: %lu\n",
-                   (unsigned long) ms_stats.pkt_disorder);
-    pos+= snprintf(pos,
-                   sizeof(buf) - (size_t)(pos -buf),
-                   "packet_drop: %lu\n",
-                   (unsigned long)ms_stats.pkt_drop);
-    pos+= snprintf(pos,
-                   sizeof(buf) - (size_t)(pos -buf),
-                   "udp_timeout: %lu\n",
-                   (unsigned long)ms_stats.udp_timeout);
-  }
-
-  if (ms_setting.stat_freq > 0)
-  {
-    ms_dump_stats(&ms_statistic.get_stat);
-    ms_dump_stats(&ms_statistic.set_stat);
-    ms_dump_stats(&ms_statistic.total_stat);
-  }
-
-  int64_t time_diff= ms_time_diff(start_time, end_time);
-  pos+= snprintf(pos,
-                 sizeof(buf) - (size_t)(pos -buf),
-                 "\nRun time: %.1fs Ops: %llu TPS: %.0Lf Net_rate: %.1fM/s\n",
-                 (double)time_diff / 1000000,
-                 (unsigned long long)(ms_stats.cmd_get + ms_stats.cmd_set),
-                 (ms_stats.cmd_get
-                  + ms_stats.cmd_set) / ((long double)time_diff / 1000000),
-                 (double)(
-                          ms_stats.bytes_written
-                          + ms_stats.bytes_read) / 1024 / 1024
-                 / ((double)time_diff / 1000000));
-  assert(pos <= buf);
-
-  fprintf(stdout, "%s", buf);
-  fflush(stdout);
-} /* ms_print_memslap_stats */
-
-
-/* the loop of the main thread, wait the work threads to complete */
-static void ms_monitor_slap_mode()
-{
-  struct timeval start_time, end_time;
-
-  /* Wait all the threads complete initialization. */
-  pthread_mutex_lock(&ms_global.init_lock.lock);
-  while (ms_global.init_lock.count < ms_setting.nthreads)
-  {
-    pthread_cond_wait(&ms_global.init_lock.cond,
-                      &ms_global.init_lock.lock);
-  }
-  pthread_mutex_unlock(&ms_global.init_lock.lock);
-
-  /* only when there is no set operation it need warm up */
-  if (ms_setting.cmd_distr[CMD_SET].cmd_prop < PROP_ERROR)
-  {
-    /* Wait all the connects complete warm up. */
-    pthread_mutex_lock(&ms_global.warmup_lock.lock);
-    while (ms_global.warmup_lock.count < ms_setting.nconns)
-    {
-      pthread_cond_wait(&ms_global.warmup_lock.cond, &ms_global.warmup_lock.lock);
-    }
-    pthread_mutex_unlock(&ms_global.warmup_lock.lock);
-  }
-  ms_global.finish_warmup= true;
-
-  /* running in "run time" mode, user specify run time */
-  if (ms_setting.run_time > 0)
-  {
-    int second= 0;
-    gettimeofday(&start_time, NULL);
-    while (1)
-    {
-      sleep(1);
-      second++;
-
-      if ((ms_setting.stat_freq > 0) && (second % ms_setting.stat_freq == 0)
-          && (ms_stats.active_conns >= ms_setting.nconns)
-          && (ms_stats.active_conns <= INT_MAX))
-      {
-        ms_print_statistics(second);
-      }
-
-      if (ms_setting.run_time <= second)
-      {
-        ms_global.time_out= true;
-        break;
-      }
-
-      /* all connections disconnect */
-      if ((second > 5) && (ms_stats.active_conns == 0))
-      {
-        break;
-      }
-    }
-    gettimeofday(&end_time, NULL);
-    sleep(1);       /* wait all threads clean up */
-  }
-  else
-  {
-    /* running in "execute number" mode, user specify execute number */
-    gettimeofday(&start_time, NULL);
-
-    /*
-     * We loop until we know that all connects have cleaned up.
-     */
-    pthread_mutex_lock(&ms_global.run_lock.lock);
-    while (ms_global.run_lock.count < ms_setting.nconns)
-    {
-      pthread_cond_wait(&ms_global.run_lock.cond, &ms_global.run_lock.lock);
-    }
-    pthread_mutex_unlock(&ms_global.run_lock.lock);
-
-    gettimeofday(&end_time, NULL);
-  }
-
-  ms_print_memslap_stats(&start_time, &end_time);
-} /* ms_monitor_slap_mode */
-
-
-/* the main function */
-int main(int argc, char *argv[])
-{
-  srandom((unsigned int)time(NULL));
-  ms_global_struct_init();
-
-  /* initialization */
-  ms_setting_init_pre();
-  ms_options_parse(argc, argv);
-  if (ms_check_para())
-  {
-    ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION);
-    exit(1);
-  }
-  ms_setting_init_post();
-  ms_stats_init();
-  ms_thread_init();
-
-  /* waiting work thread complete its task */
-  ms_monitor_slap_mode();
-
-  /* clean up */
-  ms_thread_cleanup();
-  ms_global_struct_destroy();
-  ms_setting_cleanup();
-
-  return EXIT_SUCCESS;
-} /* main */
diff --git a/clients/memcapable.cc b/clients/memcapable.cc
deleted file mode 100644 (file)
index c52b3c4..0000000
+++ /dev/null
@@ -1,2253 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-#undef NDEBUG
-
-#include <mem_config.h>
-
-#ifdef HAVE_POLL_H
-#include <poll.h>
-#else
-#include "poll/poll.h"
-#endif
-
-#include <cassert>
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <ctype.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <pthread.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <libmemcached-1.0/memcached.h>
-
-#include "libmemcached/socket.hpp"
-#include "libmemcachedprotocol-0.0/binary.h"
-#include "libmemcached/byteorder.h"
-#include "clients/utilities.h"
-
-#include <vector>
-
-#ifdef linux
-/* /usr/include/netinet/in.h defines macros from ntohs() to _bswap_nn to
- * optimize the conversion functions, but the prototypes generate warnings
- * from gcc. The conversion methods isn't the bottleneck for my app, so
- * just remove the warnings by undef'ing the optimization ..
- */
-#undef ntohs
-#undef ntohl
-#endif
-
-/* Should we generate coredumps when we enounter an error (-c) */
-static bool do_core= false;
-/* connection to the server */
-static memcached_socket_t sock;
-/* Should the output from test failures be verbose or quiet? */
-static bool verbose= false;
-
-/* The number of seconds to wait for an IO-operation */
-static int timeout= 2;
-
-/*
- * Instead of having to cast between the different datatypes we create
- * a union of all of the different types of pacages we want to send.
- * A lot of the different commands use the same packet layout, so I'll
- * just define the different types I need. The typedefs only contain
- * the header of the message, so we need some space for keys and body
- * To avoid to have to do multiple writes, lets add a chunk of memory
- * to use. 1k should be more than enough for header, key and body.
- */
-typedef union
-{
-  protocol_binary_request_no_extras plain;
-  protocol_binary_request_flush flush;
-  protocol_binary_request_incr incr;
-  protocol_binary_request_set set;
-  char bytes[1024];
-} command;
-
-typedef union
-{
-  protocol_binary_response_no_extras plain;
-  protocol_binary_response_incr incr;
-  protocol_binary_response_decr decr;
-  char bytes[1024];
-} response;
-
-enum test_return
-{
-  TEST_SKIP, TEST_PASS, TEST_PASS_RECONNECT, TEST_FAIL
-};
-
-/**
- * Try to get an addrinfo struct for a given port on a given host
- */
-static struct addrinfo *lookuphost(const char *hostname, const char *port)
-{
-  struct addrinfo *ai= 0;
-  struct addrinfo hints;
-  memset(&hints, 0, sizeof(struct addrinfo));
-  hints.ai_family=AF_UNSPEC;
-  hints.ai_protocol=IPPROTO_TCP;
-  hints.ai_socktype=SOCK_STREAM;
-
-  int error= getaddrinfo(hostname, port, &hints, &ai);
-  if (error != 0)
-  {
-    if (error != EAI_SYSTEM)
-    {
-      fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(error));
-    }
-    else
-    {
-      perror("getaddrinfo()");
-    }
-  }
-
-  return ai;
-}
-
-/**
- * Set the socket in nonblocking mode
- * @return -1 if failure, the socket otherwise
- */
-static memcached_socket_t set_noblock(void)
-{
-#if defined(_WIN32)
-  u_long arg = 1;
-  if (ioctlsocket(sock, FIONBIO, &arg) == SOCKET_ERROR)
-  {
-    perror("Failed to set nonblocking io");
-    closesocket(sock);
-    return INVALID_SOCKET;
-  }
-#else
-  int flags= fcntl(sock, F_GETFL, 0);
-  if (flags == -1)
-  {
-    perror("Failed to get socket flags");
-    memcached_close_socket(sock);
-    return INVALID_SOCKET;
-  }
-
-  if ((flags & O_NONBLOCK) != O_NONBLOCK)
-  {
-    if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)
-    {
-      perror("Failed to set socket to nonblocking mode");
-      memcached_close_socket(sock);
-      return INVALID_SOCKET;
-    }
-  }
-#endif
-  return sock;
-}
-
-/**
- * Try to open a connection to the server
- * @param hostname the name of the server to connect to
- * @param port the port number (or service) to connect to
- * @return positive integer if success, -1 otherwise
- */
-static memcached_socket_t connect_server(const char *hostname, const char *port)
-{
-  struct addrinfo *ai= lookuphost(hostname, port);
-  sock= INVALID_SOCKET;
-  if (ai != NULL)
-  {
-    if ((sock= socket(ai->ai_family, ai->ai_socktype,
-                      ai->ai_protocol)) != INVALID_SOCKET)
-    {
-      if (connect(sock, ai->ai_addr, ai->ai_addrlen) == SOCKET_ERROR)
-      {
-        fprintf(stderr, "Failed to connect socket: %s\n",
-                strerror(get_socket_errno()));
-        closesocket(sock);
-        sock= INVALID_SOCKET;
-      }
-      else
-      {
-        sock= set_noblock();
-      }
-    }
-    else
-    {
-      fprintf(stderr, "Failed to create socket: %s\n", strerror(get_socket_errno()));
-    }
-
-    freeaddrinfo(ai);
-  }
-
-  return sock;
-}
-
-static ssize_t timeout_io_op(memcached_socket_t fd, short direction, void *buf, size_t len)
-{
-  ssize_t ret;
-
-  if (direction == POLLOUT)
-  {
-    ret= send(fd, buf, len, 0);
-  }
-  else
-  {
-    ret= recv(fd, buf, len, 0);
-  }
-
-  if (ret == SOCKET_ERROR && get_socket_errno() == EWOULDBLOCK) 
-  {
-    struct pollfd fds;
-    memset(&fds, 0, sizeof(struct pollfd));
-    fds.events= direction;
-    fds.fd= fd;
-
-    int err= poll(&fds, 1, timeout * 1000);
-    if (err == 1)
-    {
-      if (direction == POLLOUT)
-      {
-        ret= send(fd, buf, len, 0);
-      }
-      else
-      {
-        ret= recv(fd, buf, len, 0);
-      }
-    }
-    else if (err == 0)
-    {
-      errno= ETIMEDOUT;
-    }
-    else
-    {
-      perror("Failed to poll");
-      return -1;
-    }
-  }
-
-  return ret;
-}
-
-/**
- * Ensure that an expression is true. If it isn't print out a message similar
- * to assert() and create a coredump if the user wants that. If not an error
- * message is returned.
- *
- */
-static enum test_return ensure(bool val, const char *expression, const char *file, int line)
-{
-  if (!val)
-  {
-    if (verbose)
-    {
-      fprintf(stdout, "\n%s:%d: %s", file, line, expression);
-    }
-
-    if (do_core)
-    {
-      abort();
-    }
-
-    return TEST_FAIL;
-  }
-
-  return TEST_PASS;
-}
-
-#define verify(expression) do { if (ensure(expression, #expression, __FILE__, __LINE__) == TEST_FAIL) return TEST_FAIL; } while (0)
-#define execute(expression) do { if (ensure(expression == TEST_PASS, #expression, __FILE__, __LINE__) == TEST_FAIL) return TEST_FAIL; } while (0)
-
-/**
- * Send a chunk of memory over the socket (retry if the call is iterrupted
- */
-static enum test_return retry_write(const void* buf, size_t len)
-{
-  size_t offset= 0;
-  const char* ptr= static_cast<const char *>(buf);
-
-  do
-  {
-    size_t num_bytes= len - offset;
-    ssize_t nw= timeout_io_op(sock, POLLOUT, (void*)(ptr + offset), num_bytes);
-    if (nw == -1)
-    {
-      verify(get_socket_errno() == EINTR || get_socket_errno() == EAGAIN);
-    }
-    else
-    {
-      offset+= (size_t)nw;
-    }
-
-  } while (offset < len);
-
-  return TEST_PASS;
-}
-
-/**
- * Resend a packet to the server (All fields in the command header should
- * be in network byte order)
- */
-static enum test_return resend_packet(command *cmd)
-{
-  size_t length= sizeof (protocol_binary_request_no_extras) +
-    ntohl(cmd->plain.message.header.request.bodylen);
-
-  execute(retry_write(cmd, length));
-  return TEST_PASS;
-}
-
-/**
- * Send a command to the server. The command header needs to be updated
- * to network byte order
- */
-static enum test_return send_packet(command *cmd)
-{
-  /* Fix the byteorder of the header */
-  cmd->plain.message.header.request.keylen=
-          ntohs(cmd->plain.message.header.request.keylen);
-  cmd->plain.message.header.request.bodylen=
-          ntohl(cmd->plain.message.header.request.bodylen);
-  cmd->plain.message.header.request.cas=
-          memcached_ntohll(cmd->plain.message.header.request.cas);
-
-  execute(resend_packet(cmd));
-  return TEST_PASS;
-}
-
-/**
- * Read a fixed length chunk of data from the server
- */
-static enum test_return retry_read(void *buf, size_t len)
-{
-  size_t offset= 0;
-  do
-  {
-    ssize_t nr= timeout_io_op(sock, POLLIN, ((char*) buf) + offset, len - offset);
-    switch (nr) {
-    case -1 :
-      fprintf(stderr, "Errno: %d %s\n", get_socket_errno(), strerror(errno));
-      verify(get_socket_errno() == EINTR || get_socket_errno() == EAGAIN);
-      break;
-
-    case 0:
-      return TEST_FAIL;
-
-    default:
-      offset+= (size_t)nr;
-    }
-  } while (offset < len);
-
-  return TEST_PASS;
-}
-
-/**
- * Receive a response from the server and conver the fields in the header
- * to local byte order
- */
-static enum test_return recv_packet(response *rsp)
-{
-  execute(retry_read(rsp, sizeof(protocol_binary_response_no_extras)));
-
-  /* Fix the byte order in the packet header */
-  rsp->plain.message.header.response.keylen=
-          ntohs(rsp->plain.message.header.response.keylen);
-  rsp->plain.message.header.response.status=
-          ntohs(rsp->plain.message.header.response.status);
-  rsp->plain.message.header.response.bodylen=
-          ntohl(rsp->plain.message.header.response.bodylen);
-  rsp->plain.message.header.response.cas=
-          memcached_ntohll(rsp->plain.message.header.response.cas);
-
-  size_t bodysz= rsp->plain.message.header.response.bodylen;
-  if (bodysz > 0)
-    execute(retry_read(rsp->bytes + sizeof (protocol_binary_response_no_extras), bodysz));
-
-  return TEST_PASS;
-}
-
-/**
- * Create a storage command (add, set, replace etc)
- *
- * @param cmd destination buffer
- * @param cc the storage command to create
- * @param key the key to store
- * @param keylen the length of the key
- * @param dta the data to store with the key
- * @param dtalen the length of the data to store with the key
- * @param flags the flags to store along with the key
- * @param exptime the expiry time for the key
- */
-static void storage_command(command *cmd,
-                            uint8_t cc,
-                            const void* key,
-                            size_t keylen,
-                            const void* dta,
-                            size_t dtalen,
-                            uint32_t flags,
-                            uint32_t exptime)
-{
-  /* all of the storage commands use the same command layout */
-  protocol_binary_request_set *request= &cmd->set;
-
-  memset(request, 0, sizeof (*request));
-  request->message.header.request.magic= PROTOCOL_BINARY_REQ;
-  request->message.header.request.opcode= cc;
-  request->message.header.request.keylen= (uint16_t)keylen;
-  request->message.header.request.extlen= 8;
-  request->message.header.request.bodylen= (uint32_t)(keylen + 8 + dtalen);
-  request->message.header.request.opaque= 0xdeadbeef;
-  request->message.body.flags= flags;
-  request->message.body.expiration= exptime;
-
-  off_t key_offset= sizeof (protocol_binary_request_no_extras) + 8;
-  memcpy(cmd->bytes + key_offset, key, keylen);
-  if (dta != NULL)
-    memcpy(cmd->bytes + key_offset + keylen, dta, dtalen);
-}
-
-/**
- * Create a basic command to send to the server
- * @param cmd destination buffer
- * @param cc the command to create
- * @param key the key to store
- * @param keylen the length of the key
- * @param dta the data to store with the key
- * @param dtalen the length of the data to store with the key
- */
-static void raw_command(command *cmd,
-                        uint8_t cc,
-                        const void* key,
-                        size_t keylen,
-                        const void* dta,
-                        size_t dtalen)
-{
-  /* all of the storage commands use the same command layout */
-  memset(cmd, 0, sizeof (*cmd));
-  cmd->plain.message.header.request.magic= PROTOCOL_BINARY_REQ;
-  cmd->plain.message.header.request.opcode= cc;
-  cmd->plain.message.header.request.keylen= (uint16_t)keylen;
-  cmd->plain.message.header.request.bodylen= (uint32_t)(keylen + dtalen);
-  cmd->plain.message.header.request.opaque= 0xdeadbeef;
-
-  off_t key_offset= sizeof (protocol_binary_request_no_extras);
-
-  if (key != NULL)
-    memcpy(cmd->bytes + key_offset, key, keylen);
-
-  if (dta != NULL)
-    memcpy(cmd->bytes + key_offset + keylen, dta, dtalen);
-}
-
-/**
- * Create the flush command
- * @param cmd destination buffer
- * @param cc the command to create (FLUSH/FLUSHQ)
- * @param exptime when to flush
- * @param use_extra to force using of the extra field?
- */
-static void flush_command(command *cmd,
-                          uint8_t cc, uint32_t exptime, bool use_extra)
-{
-  memset(cmd, 0, sizeof (cmd->flush));
-  cmd->flush.message.header.request.magic= PROTOCOL_BINARY_REQ;
-  cmd->flush.message.header.request.opcode= cc;
-  cmd->flush.message.header.request.opaque= 0xdeadbeef;
-
-  if (exptime != 0 || use_extra)
-  {
-    cmd->flush.message.header.request.extlen= 4;
-    cmd->flush.message.body.expiration= htonl(exptime);
-    cmd->flush.message.header.request.bodylen= 4;
-  }
-}
-
-/**
- * Create a incr/decr command
- * @param cc the cmd to create (FLUSH/FLUSHQ)
- * @param key the key to operate on
- * @param keylen the number of bytes in the key
- * @param delta the number to add/subtract
- * @param initial the initial value if the key doesn't exist
- * @param exptime when the key should expire if it isn't set
- */
-static void arithmetic_command(command *cmd,
-                               uint8_t cc,
-                               const void* key,
-                               size_t keylen,
-                               uint64_t delta,
-                               uint64_t initial,
-                               uint32_t exptime)
-{
-  memset(cmd, 0, sizeof (cmd->incr));
-  cmd->incr.message.header.request.magic= PROTOCOL_BINARY_REQ;
-  cmd->incr.message.header.request.opcode= cc;
-  cmd->incr.message.header.request.keylen= (uint16_t)keylen;
-  cmd->incr.message.header.request.extlen= 20;
-  cmd->incr.message.header.request.bodylen= (uint32_t)(keylen + 20);
-  cmd->incr.message.header.request.opaque= 0xdeadbeef;
-  cmd->incr.message.body.delta= memcached_htonll(delta);
-  cmd->incr.message.body.initial= memcached_htonll(initial);
-  cmd->incr.message.body.expiration= htonl(exptime);
-
-  off_t key_offset= sizeof (protocol_binary_request_no_extras) + 20;
-  memcpy(cmd->bytes + key_offset, key, keylen);
-}
-
-/**
- * Validate the response header from the server
- * @param rsp the response to check
- * @param cc the expected command
- * @param status the expected status
- */
-static enum test_return do_validate_response_header(response *rsp,
-                                                    uint8_t cc, uint16_t status)
-{
-  verify(rsp->plain.message.header.response.magic == PROTOCOL_BINARY_RES);
-  verify(rsp->plain.message.header.response.opcode == cc);
-  verify(rsp->plain.message.header.response.datatype == PROTOCOL_BINARY_RAW_BYTES);
-  verify(rsp->plain.message.header.response.status == status);
-  verify(rsp->plain.message.header.response.opaque == 0xdeadbeef);
-
-  if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS)
-  {
-    switch (cc) {
-    case PROTOCOL_BINARY_CMD_ADDQ:
-    case PROTOCOL_BINARY_CMD_APPENDQ:
-    case PROTOCOL_BINARY_CMD_DECREMENTQ:
-    case PROTOCOL_BINARY_CMD_DELETEQ:
-    case PROTOCOL_BINARY_CMD_FLUSHQ:
-    case PROTOCOL_BINARY_CMD_INCREMENTQ:
-    case PROTOCOL_BINARY_CMD_PREPENDQ:
-    case PROTOCOL_BINARY_CMD_QUITQ:
-    case PROTOCOL_BINARY_CMD_REPLACEQ:
-    case PROTOCOL_BINARY_CMD_SETQ:
-      verify("Quiet command shouldn't return on success" == NULL);
-      /* fall through */
-    default:
-      break;
-    }
-
-    switch (cc) {
-    case PROTOCOL_BINARY_CMD_ADD:
-    case PROTOCOL_BINARY_CMD_REPLACE:
-    case PROTOCOL_BINARY_CMD_SET:
-    case PROTOCOL_BINARY_CMD_APPEND:
-    case PROTOCOL_BINARY_CMD_PREPEND:
-      verify(rsp->plain.message.header.response.keylen == 0);
-      verify(rsp->plain.message.header.response.extlen == 0);
-      verify(rsp->plain.message.header.response.bodylen == 0);
-      verify(rsp->plain.message.header.response.cas != 0);
-      break;
-    case PROTOCOL_BINARY_CMD_FLUSH:
-    case PROTOCOL_BINARY_CMD_NOOP:
-    case PROTOCOL_BINARY_CMD_QUIT:
-    case PROTOCOL_BINARY_CMD_DELETE:
-      verify(rsp->plain.message.header.response.keylen == 0);
-      verify(rsp->plain.message.header.response.extlen == 0);
-      verify(rsp->plain.message.header.response.bodylen == 0);
-      verify(rsp->plain.message.header.response.cas == 0);
-      break;
-
-    case PROTOCOL_BINARY_CMD_DECREMENT:
-    case PROTOCOL_BINARY_CMD_INCREMENT:
-      verify(rsp->plain.message.header.response.keylen == 0);
-      verify(rsp->plain.message.header.response.extlen == 0);
-      verify(rsp->plain.message.header.response.bodylen == 8);
-      verify(rsp->plain.message.header.response.cas != 0);
-      break;
-
-    case PROTOCOL_BINARY_CMD_STAT:
-      verify(rsp->plain.message.header.response.extlen == 0);
-      /* key and value exists in all packets except in the terminating */
-      verify(rsp->plain.message.header.response.cas == 0);
-      break;
-
-    case PROTOCOL_BINARY_CMD_VERSION:
-      verify(rsp->plain.message.header.response.keylen == 0);
-      verify(rsp->plain.message.header.response.extlen == 0);
-      verify(rsp->plain.message.header.response.bodylen != 0);
-      verify(rsp->plain.message.header.response.cas == 0);
-      break;
-
-    case PROTOCOL_BINARY_CMD_GET:
-    case PROTOCOL_BINARY_CMD_GETQ:
-      verify(rsp->plain.message.header.response.keylen == 0);
-      verify(rsp->plain.message.header.response.extlen == 4);
-      verify(rsp->plain.message.header.response.cas != 0);
-      break;
-
-    case PROTOCOL_BINARY_CMD_GETK:
-    case PROTOCOL_BINARY_CMD_GETKQ:
-      verify(rsp->plain.message.header.response.keylen != 0);
-      verify(rsp->plain.message.header.response.extlen == 4);
-      verify(rsp->plain.message.header.response.cas != 0);
-      break;
-
-    default:
-      /* Undefined command code */
-      break;
-    }
-  }
-  else
-  {
-    verify(rsp->plain.message.header.response.cas == 0);
-    verify(rsp->plain.message.header.response.extlen == 0);
-    if (cc != PROTOCOL_BINARY_CMD_GETK)
-    {
-      verify(rsp->plain.message.header.response.keylen == 0);
-    }
-  }
-
-  return TEST_PASS;
-}
-
-/* We call verify(validate_response_header), but that macro
- * expects a boolean expression, and the function returns
- * an enum.... Let's just create a macro to avoid cluttering
- * the code with all of the == TEST_PASS ;-)
- */
-#define validate_response_header(a,b,c) \
-        do_validate_response_header(a,b,c) == TEST_PASS
-
-
-static enum test_return send_binary_noop(void)
-{
-  command cmd;
-  raw_command(&cmd, PROTOCOL_BINARY_CMD_NOOP, NULL, 0, NULL, 0);
-  execute(send_packet(&cmd));
-  return TEST_PASS;
-}
-
-static enum test_return receive_binary_noop(void)
-{
-  response rsp;
-  execute(recv_packet(&rsp));
-  verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_NOOP,
-                                  PROTOCOL_BINARY_RESPONSE_SUCCESS));
-  return TEST_PASS;
-}
-
-static enum test_return test_binary_noop(void)
-{
-  execute(send_binary_noop());
-  execute(receive_binary_noop());
-  return TEST_PASS;
-}
-
-static enum test_return test_binary_quit_impl(uint8_t cc)
-{
-  command cmd;
-  response rsp;
-  raw_command(&cmd, cc, NULL, 0, NULL, 0);
-
-  execute(send_packet(&cmd));
-  if (cc == PROTOCOL_BINARY_CMD_QUIT)
-  {
-    execute(recv_packet(&rsp));
-    verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_QUIT,
-                                    PROTOCOL_BINARY_RESPONSE_SUCCESS));
-  }
-
-  /* Socket should be closed now, read should return EXIT_SUCCESS */
-  verify(timeout_io_op(sock, POLLIN, rsp.bytes, sizeof(rsp.bytes)) == 0);
-
-  return TEST_PASS_RECONNECT;
-}
-
-static enum test_return test_binary_quit(void)
-{
-  return test_binary_quit_impl(PROTOCOL_BINARY_CMD_QUIT);
-}
-
-static enum test_return test_binary_quitq(void)
-{
-  return test_binary_quit_impl(PROTOCOL_BINARY_CMD_QUITQ);
-}
-
-static enum test_return test_binary_set_impl(const char* key, uint8_t cc)
-{
-  command cmd;
-  response rsp;
-
-  uint64_t value= 0xdeadbeefdeadcafeULL;
-  storage_command(&cmd, cc, key, strlen(key), &value, sizeof (value), 0, 0);
-
-  /* set should always work */
-  for (int ii= 0; ii < 10; ii++)
-  {
-    if (ii == 0)
-    {
-      execute(send_packet(&cmd));
-    }
-    else
-    {
-      execute(resend_packet(&cmd));
-    }
-
-    if (cc == PROTOCOL_BINARY_CMD_SET)
-    {
-      execute(recv_packet(&rsp));
-      verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
-    }
-    else
-      execute(test_binary_noop());
-  }
-
-  /*
-   * We need to get the current CAS id, and at this time we haven't
-   * verified that we have a working get
-   */
-  if (cc == PROTOCOL_BINARY_CMD_SETQ)
-  {
-    cmd.set.message.header.request.opcode= PROTOCOL_BINARY_CMD_SET;
-    execute(resend_packet(&cmd));
-    execute(recv_packet(&rsp));
-    verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_SET,
-                                    PROTOCOL_BINARY_RESPONSE_SUCCESS));
-    cmd.set.message.header.request.opcode= PROTOCOL_BINARY_CMD_SETQ;
-  }
-
-  /* try to set with the correct CAS value */
-  cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas);
-  execute(resend_packet(&cmd));
-  if (cc == PROTOCOL_BINARY_CMD_SET)
-  {
-    execute(recv_packet(&rsp));
-    verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
-  }
-  else
-    execute(test_binary_noop());
-
-  /* try to set with an incorrect CAS value */
-  cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas - 1);
-  execute(resend_packet(&cmd));
-  execute(send_binary_noop());
-  execute(recv_packet(&rsp));
-  verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS));
-  execute(receive_binary_noop());
-
-  return TEST_PASS;
-}
-
-static enum test_return test_binary_set(void)
-{
-  return test_binary_set_impl("test_binary_set", PROTOCOL_BINARY_CMD_SET);
-}
-
-static enum test_return test_binary_setq(void)
-{
-  return test_binary_set_impl("test_binary_setq", PROTOCOL_BINARY_CMD_SETQ);
-}
-
-static enum test_return test_binary_add_impl(const char* key, uint8_t cc)
-{
-  command cmd;
-  response rsp;
-  uint64_t value= 0xdeadbeefdeadcafeULL;
-  storage_command(&cmd, cc, key, strlen(key), &value, sizeof (value), 0, 0);
-
-  /* first add should work, rest of them should fail (even with cas
-     as wildcard */
-  for (int ii=0; ii < 10; ii++)
-  {
-    if (ii == 0)
-      execute(send_packet(&cmd));
-    else
-      execute(resend_packet(&cmd));
-
-    if (cc == PROTOCOL_BINARY_CMD_ADD || ii > 0)
-    {
-      uint16_t expected_result;
-      if (ii == 0)
-        expected_result= PROTOCOL_BINARY_RESPONSE_SUCCESS;
-      else
-        expected_result= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS;
-
-      execute(send_binary_noop());
-      execute(recv_packet(&rsp));
-      execute(receive_binary_noop());
-      verify(validate_response_header(&rsp, cc, expected_result));
-    }
-    else
-      execute(test_binary_noop());
-  }
-
-  return TEST_PASS;
-}
-
-static enum test_return test_binary_add(void)
-{
-  return test_binary_add_impl("test_binary_add", PROTOCOL_BINARY_CMD_ADD);
-}
-
-static enum test_return test_binary_addq(void)
-{
-  return test_binary_add_impl("test_binary_addq", PROTOCOL_BINARY_CMD_ADDQ);
-}
-
-static enum test_return binary_set_item(const char *key, const char *value)
-{
-  command cmd;
-  response rsp;
-  storage_command(&cmd, PROTOCOL_BINARY_CMD_SET, key, strlen(key),
-                  value, strlen(value), 0, 0);
-  execute(send_packet(&cmd));
-  execute(recv_packet(&rsp));
-  verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_SET,
-                                  PROTOCOL_BINARY_RESPONSE_SUCCESS));
-  return TEST_PASS;
-}
-
-static enum test_return test_binary_replace_impl(const char* key, uint8_t cc)
-{
-  command cmd;
-  response rsp;
-  uint64_t value= 0xdeadbeefdeadcafeULL;
-  storage_command(&cmd, cc, key, strlen(key), &value, sizeof (value), 0, 0);
-
-  /* first replace should fail, successive should succeed (when the
-     item is added! */
-  for (int ii= 0; ii < 10; ii++)
-  {
-    if (ii == 0)
-    {
-      execute(send_packet(&cmd));
-    }
-    else
-    {
-      execute(resend_packet(&cmd));
-    }
-
-    if (cc == PROTOCOL_BINARY_CMD_REPLACE || ii == 0)
-    {
-      uint16_t expected_result;
-      if (ii == 0)
-      {
-        expected_result=PROTOCOL_BINARY_RESPONSE_KEY_ENOENT;
-      }
-      else
-      {
-        expected_result=PROTOCOL_BINARY_RESPONSE_SUCCESS;
-      }
-
-      execute(send_binary_noop());
-      execute(recv_packet(&rsp));
-      execute(receive_binary_noop());
-      verify(validate_response_header(&rsp, cc, expected_result));
-
-      if (ii == 0)
-        execute(binary_set_item(key, key));
-    }
-    else
-    {
-      execute(test_binary_noop());
-    }
-  }
-
-  /* verify that replace with CAS value works! */
-  cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas);
-  execute(resend_packet(&cmd));
-
-  if (cc == PROTOCOL_BINARY_CMD_REPLACE)
-  {
-    execute(recv_packet(&rsp));
-    verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
-  }
-  else
-    execute(test_binary_noop());
-
-  /* try to set with an incorrect CAS value */
-  cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas - 1);
-  execute(resend_packet(&cmd));
-  execute(send_binary_noop());
-  execute(recv_packet(&rsp));
-  execute(receive_binary_noop());
-  verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS));
-
-  return TEST_PASS;
-}
-
-static enum test_return test_binary_replace(void)
-{
-  return test_binary_replace_impl("test_binary_replace", PROTOCOL_BINARY_CMD_REPLACE);
-}
-
-static enum test_return test_binary_replaceq(void)
-{
-  return test_binary_replace_impl("test_binary_replaceq", PROTOCOL_BINARY_CMD_REPLACEQ);
-}
-
-static enum test_return test_binary_delete_impl(const char *key, uint8_t cc)
-{
-  command cmd;
-  response rsp;
-  raw_command(&cmd, cc, key, strlen(key), NULL, 0);
-
-  /* The delete shouldn't work the first time, because the item isn't there */
-  execute(send_packet(&cmd));
-  execute(send_binary_noop());
-  execute(recv_packet(&rsp));
-  verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT));
-  execute(receive_binary_noop());
-  execute(binary_set_item(key, key));
-
-  /* The item should be present now, resend*/
-  execute(resend_packet(&cmd));
-  if (cc == PROTOCOL_BINARY_CMD_DELETE)
-  {
-    execute(recv_packet(&rsp));
-    verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
-  }
-
-  execute(test_binary_noop());
-
-  return TEST_PASS;
-}
-
-static enum test_return test_binary_delete(void)
-{
-  return test_binary_delete_impl("test_binary_delete", PROTOCOL_BINARY_CMD_DELETE);
-}
-
-static enum test_return test_binary_deleteq(void)
-{
-  return test_binary_delete_impl("test_binary_deleteq", PROTOCOL_BINARY_CMD_DELETEQ);
-}
-
-static enum test_return test_binary_get_impl(const char *key, uint8_t cc)
-{
-  command cmd;
-  response rsp;
-
-  raw_command(&cmd, cc, key, strlen(key), NULL, 0);
-  execute(send_packet(&cmd));
-  execute(send_binary_noop());
-
-  if (cc == PROTOCOL_BINARY_CMD_GET || cc == PROTOCOL_BINARY_CMD_GETK)
-  {
-    execute(recv_packet(&rsp));
-    verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT));
-  }
-
-  execute(receive_binary_noop());
-
-  execute(binary_set_item(key, key));
-  execute(resend_packet(&cmd));
-  execute(send_binary_noop());
-
-  execute(recv_packet(&rsp));
-  verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
-  execute(receive_binary_noop());
-
-  return TEST_PASS;
-}
-
-static enum test_return test_binary_get(void)
-{
-  return test_binary_get_impl("test_binary_get", PROTOCOL_BINARY_CMD_GET);
-}
-
-static enum test_return test_binary_getk(void)
-{
-  return test_binary_get_impl("test_binary_getk", PROTOCOL_BINARY_CMD_GETK);
-}
-
-static enum test_return test_binary_getq(void)
-{
-  return test_binary_get_impl("test_binary_getq", PROTOCOL_BINARY_CMD_GETQ);
-}
-
-static enum test_return test_binary_getkq(void)
-{
-  return test_binary_get_impl("test_binary_getkq", PROTOCOL_BINARY_CMD_GETKQ);
-}
-
-static enum test_return test_binary_incr_impl(const char* key, uint8_t cc)
-{
-  command cmd;
-  response rsp;
-  arithmetic_command(&cmd, cc, key, strlen(key), 1, 0, 0);
-
-  uint64_t ii;
-  for (ii= 0; ii < 10; ++ii)
-  {
-    if (ii == 0)
-      execute(send_packet(&cmd));
-    else
-      execute(resend_packet(&cmd));
-
-    if (cc == PROTOCOL_BINARY_CMD_INCREMENT)
-    {
-      execute(recv_packet(&rsp));
-      verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
-      verify(memcached_ntohll(rsp.incr.message.body.value) == ii);
-    }
-    else
-      execute(test_binary_noop());
-  }
-
-  /* @todo add incorrect CAS */
-  return TEST_PASS;
-}
-
-static enum test_return test_binary_incr(void)
-{
-  return test_binary_incr_impl("test_binary_incr", PROTOCOL_BINARY_CMD_INCREMENT);
-}
-
-static enum test_return test_binary_incrq(void)
-{
-  return test_binary_incr_impl("test_binary_incrq", PROTOCOL_BINARY_CMD_INCREMENTQ);
-}
-
-static enum test_return test_binary_decr_impl(const char* key, uint8_t cc)
-{
-  command cmd;
-  response rsp;
-  arithmetic_command(&cmd, cc, key, strlen(key), 1, 9, 0);
-
-  int ii;
-  for (ii= 9; ii > -1; --ii)
-  {
-    if (ii == 9)
-      execute(send_packet(&cmd));
-    else
-      execute(resend_packet(&cmd));
-
-    if (cc == PROTOCOL_BINARY_CMD_DECREMENT)
-    {
-      execute(recv_packet(&rsp));
-      verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
-      verify(memcached_ntohll(rsp.decr.message.body.value) == (uint64_t)ii);
-    }
-    else
-      execute(test_binary_noop());
-  }
-
-  /* decr 0 should not wrap */
-  execute(resend_packet(&cmd));
-  if (cc == PROTOCOL_BINARY_CMD_DECREMENT)
-  {
-    execute(recv_packet(&rsp));
-    verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
-    verify(memcached_ntohll(rsp.decr.message.body.value) == 0);
-  }
-  else
-  {
-    /* @todo get the value and verify! */
-
-  }
-
-  /* @todo add incorrect cas */
-  execute(test_binary_noop());
-  return TEST_PASS;
-}
-
-static enum test_return test_binary_decr(void)
-{
-  return test_binary_decr_impl("test_binary_decr",
-                               PROTOCOL_BINARY_CMD_DECREMENT);
-}
-
-static enum test_return test_binary_decrq(void)
-{
-  return test_binary_decr_impl("test_binary_decrq",
-                               PROTOCOL_BINARY_CMD_DECREMENTQ);
-}
-
-static enum test_return test_binary_version(void)
-{
-  command cmd;
-  response rsp;
-  raw_command(&cmd, PROTOCOL_BINARY_CMD_VERSION, NULL, 0, NULL, 0);
-
-  execute(send_packet(&cmd));
-  execute(recv_packet(&rsp));
-  verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_VERSION,
-                                  PROTOCOL_BINARY_RESPONSE_SUCCESS));
-
-  return TEST_PASS;
-}
-
-static enum test_return test_binary_flush_impl(const char *key, uint8_t cc)
-{
-  command cmd;
-  response rsp;
-
-  for (int ii= 0; ii < 2; ++ii)
-  {
-    execute(binary_set_item(key, key));
-    flush_command(&cmd, cc, 0, ii == 0);
-    execute(send_packet(&cmd));
-
-    if (cc == PROTOCOL_BINARY_CMD_FLUSH)
-    {
-      execute(recv_packet(&rsp));
-      verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
-    }
-    else
-      execute(test_binary_noop());
-
-    raw_command(&cmd, PROTOCOL_BINARY_CMD_GET, key, strlen(key), NULL, 0);
-    execute(send_packet(&cmd));
-    execute(recv_packet(&rsp));
-    verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_GET,
-                                    PROTOCOL_BINARY_RESPONSE_KEY_ENOENT));
-  }
-
-  return TEST_PASS;
-}
-
-static enum test_return test_binary_flush(void)
-{
-  return test_binary_flush_impl("test_binary_flush", PROTOCOL_BINARY_CMD_FLUSH);
-}
-
-static enum test_return test_binary_flushq(void)
-{
-  return test_binary_flush_impl("test_binary_flushq", PROTOCOL_BINARY_CMD_FLUSHQ);
-}
-
-static enum test_return test_binary_concat_impl(const char *key, uint8_t cc)
-{
-  command cmd;
-  response rsp;
-  const char *value;
-
-  if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_APPENDQ)
-  {
-    value="hello";
-  }
-  else
-  {
-    value=" world";
-  }
-
-  execute(binary_set_item(key, value));
-
-  if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_APPENDQ)
-  {
-    value=" world";
-  }
-  else
-  {
-    value="hello";
-  }
-
-  raw_command(&cmd, cc, key, strlen(key), value, strlen(value));
-  execute(send_packet(&cmd));
-  if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_PREPEND)
-  {
-    execute(recv_packet(&rsp));
-    verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
-  }
-  else
-  {
-    execute(test_binary_noop());
-  }
-
-  raw_command(&cmd, PROTOCOL_BINARY_CMD_GET, key, strlen(key), NULL, 0);
-  execute(send_packet(&cmd));
-  execute(recv_packet(&rsp));
-  verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_GET,
-                                  PROTOCOL_BINARY_RESPONSE_SUCCESS));
-  verify(rsp.plain.message.header.response.bodylen - 4 == 11);
-  verify(memcmp(rsp.bytes + 28, "hello world", 11) == 0);
-
-  return TEST_PASS;
-}
-
-static enum test_return test_binary_append(void)
-{
-  return test_binary_concat_impl("test_binary_append", PROTOCOL_BINARY_CMD_APPEND);
-}
-
-static enum test_return test_binary_prepend(void)
-{
-  return test_binary_concat_impl("test_binary_prepend", PROTOCOL_BINARY_CMD_PREPEND);
-}
-
-static enum test_return test_binary_appendq(void)
-{
-  return test_binary_concat_impl("test_binary_appendq", PROTOCOL_BINARY_CMD_APPENDQ);
-}
-
-static enum test_return test_binary_prependq(void)
-{
-  return test_binary_concat_impl("test_binary_prependq", PROTOCOL_BINARY_CMD_PREPENDQ);
-}
-
-static enum test_return test_binary_stat(void)
-{
-  command cmd;
-  response rsp;
-
-  raw_command(&cmd, PROTOCOL_BINARY_CMD_STAT, NULL, 0, NULL, 0);
-  execute(send_packet(&cmd));
-
-  do
-  {
-    execute(recv_packet(&rsp));
-    verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_STAT,
-                                    PROTOCOL_BINARY_RESPONSE_SUCCESS));
-  } while (rsp.plain.message.header.response.keylen != 0);
-
-  return TEST_PASS;
-}
-
-static enum test_return send_string(const char *cmd)
-{
-  execute(retry_write(cmd, strlen(cmd)));
-  return TEST_PASS;
-}
-
-static enum test_return receive_line(char *buffer, size_t size)
-{
-  size_t offset= 0;
-  while (offset < size)
-  {
-    execute(retry_read(buffer + offset, 1));
-    if (buffer[offset] == '\n')
-    {
-      if (offset + 1 < size)
-      {
-        buffer[offset + 1]= '\0';
-        return TEST_PASS;
-      }
-      else
-        return TEST_FAIL;
-    }
-    ++offset;
-  }
-
-  return TEST_FAIL;
-}
-
-static enum test_return receive_response(const char *msg) {
-  char buffer[80];
-  execute(receive_line(buffer, sizeof(buffer)));
-  if (strcmp(msg, buffer) != 0) {
-      fprintf(stderr, "[%s]\n", buffer);
-  }
-  verify(strcmp(msg, buffer) == 0);
-  return TEST_PASS;
-}
-
-static enum test_return receive_error_response(void)
-{
-  char buffer[80];
-  execute(receive_line(buffer, sizeof(buffer)));
-  verify(strncmp(buffer, "ERROR", 5) == 0 ||
-         strncmp(buffer, "CLIENT_ERROR", 12) == 0 ||
-         strncmp(buffer, "SERVER_ERROR", 12) == 0);
-  return TEST_PASS;
-}
-
-static enum test_return test_ascii_quit(void)
-{
-  /* Verify that quit handles unknown options */
-  execute(send_string("quit foo bar\r\n"));
-  execute(receive_error_response());
-
-  /* quit doesn't support noreply */
-  execute(send_string("quit noreply\r\n"));
-  execute(receive_error_response());
-
-  /* Verify that quit works */
-  execute(send_string("quit\r\n"));
-
-  /* Socket should be closed now, read should return EXIT_SUCCESS */
-  char buffer[80];
-  verify(timeout_io_op(sock, POLLIN, buffer, sizeof(buffer)) == 0);
-  return TEST_PASS_RECONNECT;
-
-}
-
-static enum test_return test_ascii_version(void)
-{
-  /* Verify that version command handles unknown options */
-  execute(send_string("version foo bar\r\n"));
-  execute(receive_error_response());
-
-  /* version doesn't support noreply */
-  execute(send_string("version noreply\r\n"));
-  execute(receive_error_response());
-
-  /* Verify that verify works */
-  execute(send_string("version\r\n"));
-  char buffer[256];
-  execute(receive_line(buffer, sizeof(buffer)));
-  verify(strncmp(buffer, "VERSION ", 8) == 0);
-
-  return TEST_PASS;
-}
-
-static enum test_return test_ascii_verbosity(void)
-{
-  /* This command does not adhere to the spec! */
-  execute(send_string("verbosity foo bar my\r\n"));
-  execute(receive_error_response());
-
-  execute(send_string("verbosity noreply\r\n"));
-  execute(test_ascii_version());
-
-  execute(send_string("verbosity 0 noreply\r\n"));
-  execute(test_ascii_version());
-
-  execute(send_string("verbosity\r\n"));
-  execute(receive_error_response());
-
-  execute(send_string("verbosity 1\r\n"));
-  execute(receive_response("OK\r\n"));
-
-  execute(send_string("verbosity 0\r\n"));
-  execute(receive_response("OK\r\n"));
-
-  return TEST_PASS;
-}
-
-
-
-static enum test_return test_ascii_set_impl(const char* key, bool noreply)
-{
-  /* @todo add tests for bogus format! */
-  char buffer[1024];
-  snprintf(buffer, sizeof(buffer), "set %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : "");
-  execute(send_string(buffer));
-
-  if (!noreply)
-  {
-    execute(receive_response("STORED\r\n"));
-  }
-
-  return test_ascii_version();
-}
-
-static enum test_return test_ascii_set(void)
-{
-  return test_ascii_set_impl("test_ascii_set", false);
-}
-
-static enum test_return test_ascii_set_noreply(void)
-{
-  return test_ascii_set_impl("test_ascii_set_noreply", true);
-}
-
-static enum test_return test_ascii_add_impl(const char* key, bool noreply)
-{
-  /* @todo add tests for bogus format! */
-  char buffer[1024];
-  snprintf(buffer, sizeof(buffer), "add %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : "");
-  execute(send_string(buffer));
-
-  if (!noreply)
-  {
-    execute(receive_response("STORED\r\n"));
-  }
-
-  execute(send_string(buffer));
-
-  if (!noreply)
-  {
-    execute(receive_response("NOT_STORED\r\n"));
-  }
-
-  return test_ascii_version();
-}
-
-static enum test_return test_ascii_add(void)
-{
-  return test_ascii_add_impl("test_ascii_add", false);
-}
-
-static enum test_return test_ascii_add_noreply(void)
-{
-  return test_ascii_add_impl("test_ascii_add_noreply", true);
-}
-
-static enum test_return ascii_get_unknown_value(char **key, char **value, ssize_t *ndata)
-{
-  char buffer[1024];
-
-  execute(receive_line(buffer, sizeof(buffer)));
-  verify(strncmp(buffer, "VALUE ", 6) == 0);
-  char *end= strchr(buffer + 6, ' ');
-  verify(end != NULL);
-  if (end)
-  {
-    *end= '\0';
-  }
-  *key= strdup(buffer + 6);
-  verify(*key != NULL);
-  char *ptr= end + 1;
-
-  errno= 0;
-  unsigned long val= strtoul(ptr, &end, 10); /* flags */
-  verify(errno == 0);
-  verify(ptr != end);
-  verify(val == 0);
-  verify(end != NULL);
-  errno= 0;
-  *ndata = (ssize_t)strtoul(end, &end, 10); /* size */
-  verify(errno == 0);
-  verify(ptr != end);
-  verify(end != NULL);
-  while (end and *end != '\n' and isspace(*end))
-    ++end;
-  verify(end and *end == '\n');
-
-  *value= static_cast<char*>(malloc((size_t)*ndata));
-  verify(*value != NULL);
-
-  execute(retry_read(*value, (size_t)*ndata));
-
-  execute(retry_read(buffer, 2));
-  verify(memcmp(buffer, "\r\n", 2) == 0);
-
-  return TEST_PASS;
-}
-
-static enum test_return ascii_get_value(const char *key, const char *value)
-{
-
-  char buffer[1024];
-  size_t datasize= strlen(value);
-
-  verify(datasize < sizeof(buffer));
-  execute(receive_line(buffer, sizeof(buffer)));
-  verify(strncmp(buffer, "VALUE ", 6) == 0);
-  verify(strncmp(buffer + 6, key, strlen(key)) == 0);
-  char *ptr= buffer + 6 + strlen(key) + 1;
-  char *end;
-
-  errno= 0;
-  unsigned long val= strtoul(ptr, &end, 10); /* flags */
-  verify(errno == 0);
-  verify(ptr != end);
-  verify(val == 0);
-  verify(end != NULL);
-
-  errno= 0;
-  val= strtoul(end, &end, 10); /* size */
-  verify(errno == 0);
-  verify(ptr != end);
-  verify(val == datasize);
-  verify(end != NULL);
-  while (end and *end != '\n' and isspace(*end))
-  {
-    ++end;
-  }
-  verify(end and *end == '\n');
-
-  execute(retry_read(buffer, datasize));
-  verify(memcmp(buffer, value, datasize) == 0);
-
-  execute(retry_read(buffer, 2));
-  verify(memcmp(buffer, "\r\n", 2) == 0);
-
-  return TEST_PASS;
-}
-
-static enum test_return ascii_get_item(const char *key, const char *value,
-                                       bool exist)
-{
-  char buffer[1024];
-  size_t datasize= 0;
-  if (value != NULL)
-  {
-    datasize= strlen(value);
-  }
-
-  verify(datasize < sizeof(buffer));
-  snprintf(buffer, sizeof(buffer), "get %s\r\n", key);
-  execute(send_string(buffer));
-
-  if (exist)
-  {
-    execute(ascii_get_value(key, value));
-  }
-
-  execute(retry_read(buffer, 5));
-  verify(memcmp(buffer, "END\r\n", 5) == 0);
-
-  return TEST_PASS;
-}
-
-static enum test_return ascii_gets_value(const char *key, const char *value,
-                                         unsigned long *cas)
-{
-
-  char buffer[1024];
-  size_t datasize= strlen(value);
-
-  verify(datasize < sizeof(buffer));
-  execute(receive_line(buffer, sizeof(buffer)));
-  verify(strncmp(buffer, "VALUE ", 6) == 0);
-  verify(strncmp(buffer + 6, key, strlen(key)) == 0);
-  char *ptr= buffer + 6 + strlen(key) + 1;
-  char *end;
-
-  errno= 0;
-  unsigned long val= strtoul(ptr, &end, 10); /* flags */
-  verify(errno == 0);
-  verify(ptr != end);
-  verify(val == 0);
-  verify(end != NULL);
-
-  errno= 0;
-  val= strtoul(end, &end, 10); /* size */
-  verify(errno == 0);
-  verify(ptr != end);
-  verify(val == datasize);
-  verify(end != NULL);
-
-  errno= 0;
-  *cas= strtoul(end, &end, 10); /* cas */
-  verify(errno == 0);
-  verify(ptr != end);
-  verify(val == datasize);
-  verify(end != NULL);
-
-  while (end and *end != '\n' and isspace(*end))
-  {
-    ++end;
-  }
-  verify(end and *end == '\n');
-
-  execute(retry_read(buffer, datasize));
-  verify(memcmp(buffer, value, datasize) == 0);
-
-  execute(retry_read(buffer, 2));
-  verify(memcmp(buffer, "\r\n", 2) == 0);
-
-  return TEST_PASS;
-}
-
-static enum test_return ascii_gets_item(const char *key, const char *value,
-                                        bool exist, unsigned long *cas)
-{
-  char buffer[1024];
-  size_t datasize= 0;
-  if (value != NULL)
-  {
-    datasize= strlen(value);
-  }
-
-  verify(datasize < sizeof(buffer));
-  snprintf(buffer, sizeof(buffer), "gets %s\r\n", key);
-  execute(send_string(buffer));
-
-  if (exist)
-    execute(ascii_gets_value(key, value, cas));
-
-  execute(retry_read(buffer, 5));
-  verify(memcmp(buffer, "END\r\n", 5) == 0);
-
-  return TEST_PASS;
-}
-
-static enum test_return ascii_set_item(const char *key, const char *value)
-{
-  char buffer[300];
-  size_t len= strlen(value);
-  snprintf(buffer, sizeof(buffer), "set %s 0 0 %u\r\n", key, (unsigned int)len);
-  execute(send_string(buffer));
-  execute(retry_write(value, len));
-  execute(send_string("\r\n"));
-  execute(receive_response("STORED\r\n"));
-  return TEST_PASS;
-}
-
-static enum test_return test_ascii_replace_impl(const char* key, bool noreply)
-{
-  char buffer[1024];
-  snprintf(buffer, sizeof(buffer), "replace %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : "");
-  execute(send_string(buffer));
-
-  if (noreply)
-  {
-    execute(test_ascii_version());
-  }
-  else
-  {
-    execute(receive_response("NOT_STORED\r\n"));
-  }
-
-  execute(ascii_set_item(key, "value"));
-  execute(ascii_get_item(key, "value", true));
-
-
-  execute(send_string(buffer));
-
-  if (noreply)
-    execute(test_ascii_version());
-  else
-    execute(receive_response("STORED\r\n"));
-
-  return test_ascii_version();
-}
-
-static enum test_return test_ascii_replace(void)
-{
-  return test_ascii_replace_impl("test_ascii_replace", false);
-}
-
-static enum test_return test_ascii_replace_noreply(void)
-{
-  return test_ascii_replace_impl("test_ascii_replace_noreply", true);
-}
-
-static enum test_return test_ascii_cas_impl(const char* key, bool noreply)
-{
-  char buffer[1024];
-  unsigned long cas;
-
-  execute(ascii_set_item(key, "value"));
-  execute(ascii_gets_item(key, "value", true, &cas));
-
-  snprintf(buffer, sizeof(buffer), "cas %s 0 0 6 %lu%s\r\nvalue2\r\n", key, cas, noreply ? " noreply" : "");
-  execute(send_string(buffer));
-
-  if (noreply)
-  {
-    execute(test_ascii_version());
-  }
-  else
-  {
-    execute(receive_response("STORED\r\n"));
-  }
-
-  /* reexecute the same command should fail due to illegal cas */
-  execute(send_string(buffer));
-
-  if (noreply)
-  {
-    execute(test_ascii_version());
-  }
-  else
-  {
-    execute(receive_response("EXISTS\r\n"));
-  }
-
-  return test_ascii_version();
-}
-
-static enum test_return test_ascii_cas(void)
-{
-  return test_ascii_cas_impl("test_ascii_cas", false);
-}
-
-static enum test_return test_ascii_cas_noreply(void)
-{
-  return test_ascii_cas_impl("test_ascii_cas_noreply", true);
-}
-
-static enum test_return test_ascii_delete_impl(const char *key, bool noreply)
-{
-  execute(ascii_set_item(key, "value"));
-
-  execute(send_string("delete\r\n"));
-  execute(receive_error_response());
-  /* BUG: the server accepts delete a b */
-  execute(send_string("delete a b c d e\r\n"));
-  execute(receive_error_response());
-
-  char buffer[1024];
-  snprintf(buffer, sizeof(buffer), "delete %s%s\r\n", key, noreply ? " noreply" : "");
-  execute(send_string(buffer));
-
-  if (noreply)
-    execute(test_ascii_version());
-  else
-    execute(receive_response("DELETED\r\n"));
-
-  execute(ascii_get_item(key, "value", false));
-  execute(send_string(buffer));
-  if (noreply)
-    execute(test_ascii_version());
-  else
-    execute(receive_response("NOT_FOUND\r\n"));
-
-  return TEST_PASS;
-}
-
-static enum test_return test_ascii_delete(void)
-{
-  return test_ascii_delete_impl("test_ascii_delete", false);
-}
-
-static enum test_return test_ascii_delete_noreply(void)
-{
-  return test_ascii_delete_impl("test_ascii_delete_noreply", true);
-}
-
-static enum test_return test_ascii_get(void)
-{
-  execute(ascii_set_item("test_ascii_get", "value"));
-
-  execute(send_string("get\r\n"));
-  execute(receive_error_response());
-  execute(ascii_get_item("test_ascii_get", "value", true));
-  execute(ascii_get_item("test_ascii_get_notfound", "value", false));
-
-  return TEST_PASS;
-}
-
-static enum test_return test_ascii_gets(void)
-{
-  execute(ascii_set_item("test_ascii_gets", "value"));
-
-  execute(send_string("gets\r\n"));
-  execute(receive_error_response());
-  unsigned long cas;
-  execute(ascii_gets_item("test_ascii_gets", "value", true, &cas));
-  execute(ascii_gets_item("test_ascii_gets_notfound", "value", false, &cas));
-
-  return TEST_PASS;
-}
-
-static enum test_return test_ascii_mget(void)
-{
-  const uint32_t nkeys= 5;
-  const char * const keys[]= {
-    "test_ascii_mget1",
-    "test_ascii_mget2",
-    /* test_ascii_mget_3 does not exist :) */
-    "test_ascii_mget4",
-    "test_ascii_mget5",
-    "test_ascii_mget6"
-  };
-
-  for (uint32_t x= 0; x < nkeys; ++x)
-  {
-    execute(ascii_set_item(keys[x], "value"));
-  }
-
-  /* Ask for a key that doesn't exist as well */
-  execute(send_string("get test_ascii_mget1 test_ascii_mget2 test_ascii_mget3 "
-                      "test_ascii_mget4 test_ascii_mget5 "
-                      "test_ascii_mget6\r\n"));
-
-  std::vector<char *> returned;
-  returned.resize(nkeys);
-
-  for (uint32_t x= 0; x < nkeys; ++x)
-  {
-    ssize_t nbytes = 0;
-    char *v= NULL;
-    execute(ascii_get_unknown_value(&returned[x], &v, &nbytes));
-    verify(nbytes == 5);
-    verify(memcmp(v, "value", 5) == 0);
-    free(v);
-  }
-
-  char buffer[5];
-  execute(retry_read(buffer, 5));
-  verify(memcmp(buffer, "END\r\n", 5) == 0);
-
-  /* verify that we got all the keys we expected */
-  for (uint32_t x= 0; x < nkeys; ++x)
-  {
-    bool found= false;
-    for (uint32_t y= 0; y < nkeys; ++y)
-    {
-      if (strcmp(keys[x], returned[y]) == 0)
-      {
-        found = true;
-        break;
-      }
-    }
-    verify(found);
-  }
-
-  for (uint32_t x= 0; x < nkeys; ++x)
-  {
-    free(returned[x]);
-  }
-
-  return TEST_PASS;
-}
-
-static enum test_return test_ascii_incr_impl(const char* key, bool noreply)
-{
-  char cmd[300];
-  snprintf(cmd, sizeof(cmd), "incr %s 1%s\r\n", key, noreply ? " noreply" : "");
-
-  execute(ascii_set_item(key, "0"));
-  for (int x= 1; x < 11; ++x)
-  {
-    execute(send_string(cmd));
-
-    if (noreply)
-      execute(test_ascii_version());
-    else
-    {
-      char buffer[80];
-      execute(receive_line(buffer, sizeof(buffer)));
-      int val= atoi(buffer);
-      verify(val == x);
-    }
-  }
-
-  execute(ascii_get_item(key, "10", true));
-
-  return TEST_PASS;
-}
-
-static enum test_return test_ascii_incr(void)
-{
-  return test_ascii_incr_impl("test_ascii_incr", false);
-}
-
-static enum test_return test_ascii_incr_noreply(void)
-{
-  return test_ascii_incr_impl("test_ascii_incr_noreply", true);
-}
-
-static enum test_return test_ascii_decr_impl(const char* key, bool noreply)
-{
-  char cmd[300];
-  snprintf(cmd, sizeof(cmd), "decr %s 1%s\r\n", key, noreply ? " noreply" : "");
-
-  execute(ascii_set_item(key, "9"));
-  for (int x= 8; x > -1; --x)
-  {
-    execute(send_string(cmd));
-
-    if (noreply)
-    {
-      execute(test_ascii_version());
-    }
-    else
-    {
-      char buffer[80];
-      execute(receive_line(buffer, sizeof(buffer)));
-      int val= atoi(buffer);
-      verify(val == x);
-    }
-  }
-
-  execute(ascii_get_item(key, "0", true));
-
-  /* verify that it doesn't wrap */
-  execute(send_string(cmd));
-  if (noreply)
-  {
-    execute(test_ascii_version());
-  }
-  else
-  {
-    char buffer[80];
-    execute(receive_line(buffer, sizeof(buffer)));
-  }
-  execute(ascii_get_item(key, "0", true));
-
-  return TEST_PASS;
-}
-
-static enum test_return test_ascii_decr(void)
-{
-  return test_ascii_decr_impl("test_ascii_decr", false);
-}
-
-static enum test_return test_ascii_decr_noreply(void)
-{
-  return test_ascii_decr_impl("test_ascii_decr_noreply", true);
-}
-
-
-static enum test_return test_ascii_flush_impl(const char *key, bool noreply)
-{
-#if 0
-  /* Verify that the flush_all command handles unknown options */
-  /* Bug in the current memcached server! */
-  execute(send_string("flush_all foo bar\r\n"));
-  execute(receive_error_response());
-#endif
-
-  execute(ascii_set_item(key, key));
-  execute(ascii_get_item(key, key, true));
-
-  if (noreply)
-  {
-    execute(send_string("flush_all noreply\r\n"));
-    execute(test_ascii_version());
-  }
-  else
-  {
-    execute(send_string("flush_all\r\n"));
-    execute(receive_response("OK\r\n"));
-  }
-
-  execute(ascii_get_item(key, key, false));
-
-  return TEST_PASS;
-}
-
-static enum test_return test_ascii_flush(void)
-{
-  return test_ascii_flush_impl("test_ascii_flush", false);
-}
-
-static enum test_return test_ascii_flush_noreply(void)
-{
-  return test_ascii_flush_impl("test_ascii_flush_noreply", true);
-}
-
-static enum test_return test_ascii_concat_impl(const char *key,
-                                               bool append,
-                                               bool noreply)
-{
-  const char *value;
-
-  if (append)
-    value="hello";
-  else
-    value=" world";
-
-  execute(ascii_set_item(key, value));
-
-  if (append)
-  {
-    value=" world";
-  }
-  else
-  {
-    value="hello";
-  }
-
-  char cmd[400];
-  snprintf(cmd, sizeof(cmd), "%s %s 0 0 %u%s\r\n%s\r\n",
-           append ? "append" : "prepend",
-           key, (unsigned int)strlen(value), noreply ? " noreply" : "",
-           value);
-  execute(send_string(cmd));
-
-  if (noreply)
-  {
-    execute(test_ascii_version());
-  }
-  else
-  {
-    execute(receive_response("STORED\r\n"));
-  }
-
-  execute(ascii_get_item(key, "hello world", true));
-
-  snprintf(cmd, sizeof(cmd), "%s %s_notfound 0 0 %u%s\r\n%s\r\n",
-           append ? "append" : "prepend",
-           key, (unsigned int)strlen(value), noreply ? " noreply" : "",
-           value);
-  execute(send_string(cmd));
-
-  if (noreply)
-  {
-    execute(test_ascii_version());
-  }
-  else
-  {
-    execute(receive_response("NOT_STORED\r\n"));
-  }
-
-  return TEST_PASS;
-}
-
-static enum test_return test_ascii_append(void)
-{
-  return test_ascii_concat_impl("test_ascii_append", true, false);
-}
-
-static enum test_return test_ascii_prepend(void)
-{
-  return test_ascii_concat_impl("test_ascii_prepend", false, false);
-}
-
-static enum test_return test_ascii_append_noreply(void)
-{
-  return test_ascii_concat_impl("test_ascii_append_noreply", true, true);
-}
-
-static enum test_return test_ascii_prepend_noreply(void)
-{
-  return test_ascii_concat_impl("test_ascii_prepend_noreply", false, true);
-}
-
-static enum test_return test_ascii_stat(void)
-{
-  execute(send_string("stats noreply\r\n"));
-  execute(receive_error_response());
-  execute(send_string("stats\r\n"));
-  char buffer[1024];
-  do {
-    execute(receive_line(buffer, sizeof(buffer)));
-  } while (strcmp(buffer, "END\r\n") != 0);
-
-  return TEST_PASS_RECONNECT;
-}
-
-typedef enum test_return(*TEST_FUNC)(void);
-
-struct testcase
-{
-  const char *description;
-  TEST_FUNC function;
-};
-
-struct testcase testcases[]= {
-  { "ascii quit", test_ascii_quit },
-  { "ascii version", test_ascii_version },
-  { "ascii verbosity", test_ascii_verbosity },
-  { "ascii set", test_ascii_set },
-  { "ascii set noreply", test_ascii_set_noreply },
-  { "ascii get", test_ascii_get },
-  { "ascii gets", test_ascii_gets },
-  { "ascii mget", test_ascii_mget },
-  { "ascii flush", test_ascii_flush },
-  { "ascii flush noreply", test_ascii_flush_noreply },
-  { "ascii add", test_ascii_add },
-  { "ascii add noreply", test_ascii_add_noreply },
-  { "ascii replace", test_ascii_replace },
-  { "ascii replace noreply", test_ascii_replace_noreply },
-  { "ascii cas", test_ascii_cas },
-  { "ascii cas noreply", test_ascii_cas_noreply },
-  { "ascii delete", test_ascii_delete },
-  { "ascii delete noreply", test_ascii_delete_noreply },
-  { "ascii incr", test_ascii_incr },
-  { "ascii incr noreply", test_ascii_incr_noreply },
-  { "ascii decr", test_ascii_decr },
-  { "ascii decr noreply", test_ascii_decr_noreply },
-  { "ascii append", test_ascii_append },
-  { "ascii append noreply", test_ascii_append_noreply },
-  { "ascii prepend", test_ascii_prepend },
-  { "ascii prepend noreply", test_ascii_prepend_noreply },
-  { "ascii stat", test_ascii_stat },
-  { "binary noop", test_binary_noop },
-  { "binary quit", test_binary_quit },
-  { "binary quitq", test_binary_quitq },
-  { "binary set", test_binary_set },
-  { "binary setq", test_binary_setq },
-  { "binary flush", test_binary_flush },
-  { "binary flushq", test_binary_flushq },
-  { "binary add", test_binary_add },
-  { "binary addq", test_binary_addq },
-  { "binary replace", test_binary_replace },
-  { "binary replaceq", test_binary_replaceq },
-  { "binary delete", test_binary_delete },
-  { "binary deleteq", test_binary_deleteq },
-  { "binary get", test_binary_get },
-  { "binary getq", test_binary_getq },
-  { "binary getk", test_binary_getk },
-  { "binary getkq", test_binary_getkq },
-  { "binary incr", test_binary_incr },
-  { "binary incrq", test_binary_incrq },
-  { "binary decr", test_binary_decr },
-  { "binary decrq", test_binary_decrq },
-  { "binary version", test_binary_version },
-  { "binary append", test_binary_append },
-  { "binary appendq", test_binary_appendq },
-  { "binary prepend", test_binary_prepend },
-  { "binary prependq", test_binary_prependq },
-  { "binary stat", test_binary_stat },
-  { NULL, NULL}
-};
-
-const int ascii_tests = 1;
-const int binary_tests = 2;
-
-struct test_type_st
-{
-  bool ascii;
-  bool binary;
-};
-
-int main(int argc, char **argv)
-{
-  static const char * const status_msg[]= {"[skip]", "[pass]", "[pass]", "[FAIL]"};
-  struct test_type_st tests= { true, true };
-  int total= 0;
-  int failed= 0;
-  const char *hostname= NULL;
-  const char *port= MEMCACHED_DEFAULT_PORT_STRING;
-  int cmd;
-  bool prompt= false;
-  const char *testname= NULL;
-
-
-
-  while ((cmd= getopt(argc, argv, "qt:vch:p:PT:?ab")) != EOF)
-  {
-    switch (cmd) {
-    case 'a':
-      tests.ascii= true;
-      tests.binary= false;
-      break;
-
-    case 'b':
-      tests.ascii= false;
-      tests.binary= true;
-      break;
-
-    case 't':
-      timeout= atoi(optarg);
-      if (timeout == 0)
-      {
-        fprintf(stderr, "Invalid timeout. Please specify a number for -t\n");
-        return EXIT_FAILURE;
-      }
-      break;
-
-    case 'v': verbose= true;
-      break;
-
-    case 'c': do_core= true;
-      break;
-
-    case 'h': hostname= optarg;
-      break;
-
-    case 'p': port= optarg;
-      break;
-
-    case 'q':
-      close_stdio();
-      break;
-
-    case 'P': prompt= true;
-      break;
-
-    case 'T': testname= optarg;
-       break;
-
-    default:
-      fprintf(stderr, "Usage: %s [-h hostname] [-p port] [-c] [-v] [-t n] [-P] [-T testname]'\n"
-              "\t-c\tGenerate coredump if a test fails\n"
-              "\t-v\tVerbose test output (print out the assertion)\n"
-              "\t-t n\tSet the timeout for io-operations to n seconds\n"
-              "\t-P\tPrompt the user before starting a test.\n"
-              "\t\t\t\"skip\" will skip the test\n"
-              "\t\t\t\"quit\" will terminate memcapable\n"
-              "\t\t\tEverything else will start the test\n"
-              "\t-T n\tJust run the test named n\n"
-              "\t-a\tOnly test the ascii protocol\n"
-              "\t-b\tOnly test the binary protocol\n",
-              argv[0]);
-      return EXIT_SUCCESS;
-    }
-  }
-
-  if (!hostname)
-  {
-    fprintf(stderr, "No hostname was provided.\n");
-    return EXIT_FAILURE;
-  }
-
-  initialize_sockets();
-  sock= connect_server(hostname, port);
-  if (sock == INVALID_SOCKET)
-  {
-    fprintf(stderr, "Failed to connect to <%s:%s>: %s\n",
-            hostname?:"(null)", port?:"(null)", strerror(get_socket_errno()));
-    return EXIT_FAILURE;
-  }
-
-  for (int ii= 0; testcases[ii].description != NULL; ++ii)
-  {
-    if (testname != NULL && strcmp(testcases[ii].description, testname) != 0)
-    {
-      continue;
-    }
-
-    if ((testcases[ii].description[0] == 'a' && (tests.ascii) == 0) ||
-        (testcases[ii].description[0] == 'b' && (tests.binary) == 0))
-    {
-      continue;
-    }
-    ++total;
-    fprintf(stdout, "%-40s", testcases[ii].description);
-    fflush(stdout);
-
-    if (prompt)
-    {
-      fprintf(stdout, "\nPress <return> when you are ready? ");
-      char buffer[80] = {0};
-      if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
-        if (strncmp(buffer, "skip", 4) == 0)
-        {
-          fprintf(stdout, "%-40s%s\n", testcases[ii].description,
-                  status_msg[TEST_SKIP]);
-          fflush(stdout);
-          continue;
-        }
-        if (strncmp(buffer, "quit", 4) == 0)
-        {
-          exit(EXIT_SUCCESS);
-        }
-      }
-
-      fprintf(stdout, "%-40s", testcases[ii].description);
-      fflush(stdout);
-    }
-
-    bool reconnect= false;
-    enum test_return ret= testcases[ii].function();
-    if (ret == TEST_FAIL)
-    {
-      reconnect= true;
-      ++failed;
-      if (verbose)
-      {
-        fprintf(stderr, "\n");
-      }
-    }
-    else if (ret == TEST_PASS_RECONNECT)
-    {
-      reconnect= true;
-    }
-
-    if (ret == TEST_FAIL)
-    {
-      fprintf(stderr, "%s\n", status_msg[ret]);
-    }
-    else
-    {
-      fprintf(stdout, "%s\n", status_msg[ret]);
-    }
-
-    if (reconnect)
-    {
-      closesocket(sock);
-      if ((sock= connect_server(hostname, port)) == INVALID_SOCKET)
-      {
-        fprintf(stderr, "Failed to connect to <%s:%s>: %s\n", hostname?:"(null)", port?:"(null)", strerror(get_socket_errno()));
-        fprintf(stderr, "%d of %d tests failed\n", failed, total);
-        return EXIT_FAILURE;
-      }
-    }
-  }
-
-  closesocket(sock);
-  if (failed == 0)
-  {
-    fprintf(stdout, "All tests passed\n");
-  }
-  else
-  {
-    fprintf(stderr, "%d of %d tests failed\n", failed, total);
-  }
-
-  return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
-}
diff --git a/clients/memcapable.sh b/clients/memcapable.sh
deleted file mode 100755 (executable)
index cc4f89a..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-clients/memcapable -vh localhost
diff --git a/clients/memcat.cc b/clients/memcat.cc
deleted file mode 100644 (file)
index 8653512..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-#include <mem_config.h>
-
-#include <cstdio>
-#include <cstring>
-#include <getopt.h>
-#include <iostream>
-#include <unistd.h>
-#include <libmemcached-1.0/memcached.h>
-
-#include "utilities.h"
-
-#define PROGRAM_NAME "memcat"
-#define PROGRAM_DESCRIPTION "Cat a set of key values to stdout."
-
-
-/* Prototypes */
-void options_parse(int argc, char *argv[]);
-
-static int opt_binary= 0;
-static int opt_verbose= 0;
-static int opt_displayflag= 0;
-static char *opt_servers= NULL;
-static char *opt_hash= NULL;
-static char *opt_username;
-static char *opt_passwd;
-static char *opt_file;
-
-int main(int argc, char *argv[])
-{
-  char *string;
-  size_t string_length;
-  uint32_t flags;
-  memcached_return_t rc;
-
-  int return_code= EXIT_SUCCESS;
-
-  options_parse(argc, argv);
-  initialize_sockets();
-
-  if (opt_servers == NULL)
-  {
-    char *temp;
-
-    if ((temp= getenv("MEMCACHED_SERVERS")))
-    {
-      opt_servers= strdup(temp);
-    }
-
-    if (opt_servers == NULL)
-    {
-      std::cerr << "No servers provided" << std::endl;
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  memcached_server_st* servers= memcached_servers_parse(opt_servers);
-  if (servers == NULL or memcached_server_list_count(servers) == 0)
-  {
-    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  memcached_st* memc= memcached_create(NULL);
-  process_hash_option(memc, opt_hash);
-
-  memcached_server_push(memc, servers);
-  memcached_server_list_free(servers);
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
-                         (uint64_t)opt_binary);
-
-  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    memcached_free(memc);
-    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  if (opt_username)
-  {
-    memcached_return_t ret;
-    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
-    {
-      std::cerr << memcached_last_error_message(memc) << std::endl;
-      memcached_free(memc);
-      return EXIT_FAILURE;
-    }
-  }
-
-  while (optind < argc)
-  {
-    string= memcached_get(memc, argv[optind], strlen(argv[optind]),
-                          &string_length, &flags, &rc);
-    if (rc == MEMCACHED_SUCCESS)
-    {
-      if (opt_displayflag)
-      {
-        if (opt_verbose)
-        {
-          std::cout << "key: " << argv[optind] << std::endl << "flags: " << flags << std::endl;
-        }
-      }
-      else
-      {
-        if (opt_verbose)
-        {
-          std::cout << "key: " << argv[optind] << std::endl << "flags: " << flags << std::endl << "length: " << string_length << std::endl << "value: ";
-        }
-
-        if (opt_file)
-        {
-          FILE *fp= fopen(opt_file, "w");
-          if (fp == NULL)
-          {
-            perror("fopen");
-            return_code= EXIT_FAILURE;
-            break;
-          }
-
-          size_t written= fwrite(string, 1, string_length, fp);
-          if (written != string_length) 
-          {
-            std::cerr << "error writing file to file " << opt_file << " wrote " << written << ", should have written" << string_length << std::endl;
-            return_code= EXIT_FAILURE;
-            break;
-          }
-
-          if (fclose(fp))
-          {
-            std::cerr << "error closing " << opt_file << std::endl;
-            return_code= EXIT_FAILURE;
-            break;
-          }
-        }
-        else
-        {
-          std::cout.write(string, string_length);
-          std::cout << std::endl;
-        }
-        free(string);
-      }
-    }
-    else if (rc != MEMCACHED_NOTFOUND)
-    {
-      std::cerr << "error on " << argv[optind] << "(" <<  memcached_strerror(memc, rc) << ")";
-      if (memcached_last_error_errno(memc))
-      {
-        std::cerr << " system error (" << strerror(memcached_last_error_errno(memc)) << ")" << std::endl;
-      }
-      std::cerr << std::endl;
-
-      return_code= EXIT_FAILURE;
-      break;
-    }
-    else // Unknown Issue
-    {
-      std::cerr << "error on " << argv[optind] << "("<< memcached_strerror(NULL, rc) << ")" << std::endl;
-      return_code= EXIT_FAILURE;
-    }
-    optind++;
-  }
-
-  memcached_free(memc);
-
-  if (opt_servers)
-  {
-    free(opt_servers);
-  }
-  if (opt_hash)
-  {
-    free(opt_hash);
-  }
-
-  return return_code;
-}
-
-
-void options_parse(int argc, char *argv[])
-{
-  int option_index= 0;
-
-  memcached_programs_help_st help_options[]=
-  {
-    {0},
-  };
-
-  static struct option long_options[]=
-    {
-      {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
-      {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
-      {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
-      {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
-      {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
-      {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
-      {(OPTIONSTRING)"flag", no_argument, &opt_displayflag, OPT_FLAG},
-      {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
-      {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
-      {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
-      {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
-      {(OPTIONSTRING)"file", required_argument, NULL, OPT_FILE},
-      {0, 0, 0, 0},
-    };
-
-  while (1)
-  {
-    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
-    if (option_rv == -1) break;
-    switch (option_rv)
-    {
-    case 0:
-      break;
-    case OPT_BINARY:
-      opt_binary = 1;
-      break;
-    case OPT_VERBOSE: /* --verbose or -v */
-      opt_verbose = OPT_VERBOSE;
-      break;
-    case OPT_DEBUG: /* --debug or -d */
-      opt_verbose = OPT_DEBUG;
-      break;
-    case OPT_VERSION: /* --version or -V */
-      version_command(PROGRAM_NAME);
-      break;
-    case OPT_HELP: /* --help or -h */
-      help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
-      break;
-    case OPT_SERVERS: /* --servers or -s */
-      opt_servers= strdup(optarg);
-      break;
-    case OPT_HASH:
-      opt_hash= strdup(optarg);
-      break;
-    case OPT_USERNAME:
-      opt_username= optarg;
-      break;
-    case OPT_PASSWD:
-      opt_passwd= optarg;
-      break;
-    case OPT_FILE:
-      opt_file= optarg;
-      break;
-
-    case OPT_QUIET:
-      close_stdio();
-      break;
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(EXIT_FAILURE);
-    default:
-      abort();
-    }
-  }
-}
diff --git a/clients/memcat.sh b/clients/memcat.sh
deleted file mode 100755 (executable)
index e7497de..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-clients/memcp.sh
-clients/memcat --servers=localhost -v mem.testdata
diff --git a/clients/memcp.cc b/clients/memcp.cc
deleted file mode 100644 (file)
index d87e0ca..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-#include "mem_config.h"
-
-#include <cerrno>
-#include <climits>
-#include <cstdio>
-#include <cstdlib>
-#include <cstdlib>
-#include <cstring>
-#include <fcntl.h>
-#include <getopt.h>
-#include <iostream>
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/types.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-
-#include <libmemcached-1.0/memcached.h>
-
-#include "client_options.h"
-#include "utilities.h"
-
-#define PROGRAM_NAME "memcp"
-#define PROGRAM_DESCRIPTION "Copy a set of files to a memcached cluster."
-
-/* Prototypes */
-static void options_parse(int argc, char *argv[]);
-
-static bool opt_binary= false;
-static bool opt_udp= false;
-static bool opt_buffer= false;
-static int opt_verbose= 0;
-static char *opt_servers= NULL;
-static char *opt_hash= NULL;
-static int opt_method= OPT_SET;
-static uint32_t opt_flags= 0;
-static time_t opt_expires= 0;
-static char *opt_username;
-static char *opt_passwd;
-
-static long strtol_wrapper(const char *nptr, int base, bool *error)
-{
-  long val;
-  char *endptr;
-
-  errno= 0;    /* To distinguish success/failure after call */
-  val= strtol(nptr, &endptr, base);
-
-  /* Check for various possible errors */
-
-  if ((errno == ERANGE and (val == LONG_MAX or val == LONG_MIN))
-      or (errno != 0 && val == 0))
-  {
-    *error= true;
-    return 0;
-  }
-
-  if (endptr == nptr)
-  {
-    *error= true;
-    return 0;
-  }
-
-  *error= false;
-  return val;
-}
-
-int main(int argc, char *argv[])
-{
-
-  options_parse(argc, argv);
-
-  if (optind >= argc)
-  {
-    fprintf(stderr, "Expected argument after options\n");
-    exit(EXIT_FAILURE);
-  }
-
-  initialize_sockets();
-
-  memcached_st *memc= memcached_create(NULL);
-
-  if (opt_udp)
-  {
-    if (opt_verbose)
-    {
-      std::cout << "Enabling UDP" << std::endl;
-    }
-
-    if (memcached_failed(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, opt_udp)))
-    {
-      memcached_free(memc);
-      std::cerr << "Could not enable UDP protocol." << std::endl;
-      return EXIT_FAILURE;
-    }
-  }
-
-  if (opt_buffer)
-  {
-    if (opt_verbose)
-    {
-      std::cout << "Enabling MEMCACHED_BEHAVIOR_BUFFER_REQUESTS" << std::endl;
-    }
-
-    if (memcached_failed(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, opt_buffer)))
-    {
-      memcached_free(memc);
-      std::cerr << "Could not enable MEMCACHED_BEHAVIOR_BUFFER_REQUESTS." << std::endl;
-      return EXIT_FAILURE;
-    }
-  }
-
-  process_hash_option(memc, opt_hash);
-
-  if (opt_servers == NULL)
-  {
-    char *temp;
-
-    if ((temp= getenv("MEMCACHED_SERVERS")))
-    {
-      opt_servers= strdup(temp);
-    }
-#if 0
-    else if (argc >= 1 and argv[--argc])
-    {
-      opt_servers= strdup(argv[argc]);
-    }
-#endif
-
-    if (opt_servers == NULL)
-    {
-      std::cerr << "No Servers provided" << std::endl;
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  memcached_server_st* servers= memcached_servers_parse(opt_servers);
-  if (servers == NULL or memcached_server_list_count(servers) == 0)
-  {
-    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  memcached_server_push(memc, servers);
-  memcached_server_list_free(servers);
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, opt_binary);
-  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    memcached_free(memc);
-    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  if (opt_username)
-  {
-    memcached_return_t ret;
-    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
-    {
-      std::cerr << memcached_last_error_message(memc) << std::endl;
-      memcached_free(memc);
-      return EXIT_FAILURE;
-    }
-  }
-
-  int exit_code= EXIT_SUCCESS;
-  while (optind < argc)
-  {
-    int fd= open(argv[optind], O_RDONLY);
-    if (fd < 0)
-    {
-      std::cerr << "memcp " << argv[optind] << " " << strerror(errno) << std::endl;
-      optind++;
-      exit_code= EXIT_FAILURE;
-      continue;
-    }
-
-    struct stat sbuf;
-    if (fstat(fd, &sbuf) == -1)
-    {
-      std::cerr << "memcp " << argv[optind] << " " << strerror(errno) << std::endl;
-      optind++;
-      exit_code= EXIT_FAILURE;
-      continue;
-    }
-
-    char *ptr= rindex(argv[optind], '/');
-    if (ptr)
-    {
-      ptr++;
-    }
-    else
-    {
-      ptr= argv[optind];
-    }
-
-    if (opt_verbose)
-    {
-      static const char *opstr[] = { "set", "add", "replace" };
-      printf("op: %s\nsource file: %s\nlength: %lu\n"
-            "key: %s\nflags: %x\nexpires: %lu\n",
-            opstr[opt_method - OPT_SET], argv[optind], (unsigned long)sbuf.st_size,
-            ptr, opt_flags, (unsigned long)opt_expires);
-    }
-
-    // The file may be empty
-    char *file_buffer_ptr= NULL;
-    if (sbuf.st_size > 0)
-    {
-      if ((file_buffer_ptr= (char *)malloc(sizeof(char) * (size_t)sbuf.st_size)) == NULL)
-      {
-        std::cerr << "Error allocating file buffer(" << strerror(errno) << ")" << std::endl;
-        close(fd);
-        exit(EXIT_FAILURE);
-      }
-
-      ssize_t read_length;
-      if ((read_length= ::read(fd, file_buffer_ptr, (size_t)sbuf.st_size)) == -1)
-      {
-        std::cerr << "Error while reading file " << file_buffer_ptr << " (" << strerror(errno) << ")" << std::endl;
-        close(fd);
-        free(file_buffer_ptr);
-        exit(EXIT_FAILURE);
-      }
-
-      if (read_length != sbuf.st_size)
-      {
-        std::cerr << "Failure while reading file. Read length was not equal to stat() length" << std::endl;
-        close(fd);
-        free(file_buffer_ptr);
-        exit(EXIT_FAILURE);
-      }
-    }
-
-    memcached_return_t rc;
-    if (opt_method == OPT_ADD)
-    {
-      rc= memcached_add(memc, ptr, strlen(ptr),
-                        file_buffer_ptr, (size_t)sbuf.st_size,
-                       opt_expires, opt_flags);
-    }
-    else if (opt_method == OPT_REPLACE)
-    {
-      rc= memcached_replace(memc, ptr, strlen(ptr),
-                           file_buffer_ptr, (size_t)sbuf.st_size,
-                           opt_expires, opt_flags);
-    }
-    else
-    {
-      rc= memcached_set(memc, ptr, strlen(ptr),
-                        file_buffer_ptr, (size_t)sbuf.st_size,
-                        opt_expires, opt_flags);
-    }
-
-    if (memcached_failed(rc))
-    {
-      std::cerr << "Error occrrured during memcached_set(): " << memcached_last_error_message(memc) << std::endl;
-      exit_code= EXIT_FAILURE;
-    }
-
-    ::free(file_buffer_ptr);
-    ::close(fd);
-    optind++;
-  }
-
-  if (opt_verbose)
-  {
-    std::cout << "Calling memcached_free()" << std::endl;
-  }
-
-  memcached_free(memc);
-
-  if (opt_servers)
-  {
-    free(opt_servers);
-  }
-
-  if (opt_hash)
-  {
-    free(opt_hash);
-  }
-
-  return exit_code;
-}
-
-static void options_parse(int argc, char *argv[])
-{
-  memcached_programs_help_st help_options[]=
-  {
-    {0},
-  };
-
-  static struct option long_options[]=
-    {
-      {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
-      {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
-      {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
-      {(OPTIONSTRING)"udp", no_argument, NULL, OPT_UDP},
-      {(OPTIONSTRING)"buffer", no_argument, NULL, OPT_BUFFER},
-      {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
-      {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
-      {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
-      {(OPTIONSTRING)"flag", required_argument, NULL, OPT_FLAG},
-      {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
-      {(OPTIONSTRING)"set",  no_argument, NULL, OPT_SET},
-      {(OPTIONSTRING)"add",  no_argument, NULL, OPT_ADD},
-      {(OPTIONSTRING)"replace",  no_argument, NULL, OPT_REPLACE},
-      {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
-      {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
-      {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
-      {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
-      {0, 0, 0, 0},
-    };
-
-  bool opt_version= false;
-  bool opt_help= false;
-  int option_index= 0;
-
-  while (1)
-  {
-    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
-
-    if (option_rv == -1)
-      break;
-
-    switch (option_rv)
-    {
-    case 0:
-      break;
-
-    case OPT_BINARY:
-      opt_binary= true;
-      break;
-
-    case OPT_VERBOSE: /* --verbose or -v */
-      opt_verbose= OPT_VERBOSE;
-      break;
-
-    case OPT_DEBUG: /* --debug or -d */
-      opt_verbose= OPT_DEBUG;
-      break;
-
-    case OPT_VERSION: /* --version or -V */
-      opt_version= true;
-      break;
-
-    case OPT_HELP: /* --help or -h */
-      opt_help= true;
-      break;
-
-    case OPT_SERVERS: /* --servers or -s */
-      opt_servers= strdup(optarg);
-      break;
-
-    case OPT_FLAG: /* --flag */
-      {
-        bool strtol_error;
-        opt_flags= (uint32_t)strtol_wrapper(optarg, 16, &strtol_error);
-        if (strtol_error == true)
-        {
-          fprintf(stderr, "Bad value passed via --flag\n");
-          exit(1);
-        }
-      }
-      break;
-
-    case OPT_EXPIRE: /* --expire */
-      {
-        bool strtol_error;
-        opt_expires= (time_t)strtol_wrapper(optarg, 10, &strtol_error);
-        if (strtol_error == true)
-        {
-          fprintf(stderr, "Bad value passed via --expire\n");
-          exit(1);
-        }
-      }
-      break;
-
-    case OPT_SET:
-      opt_method= OPT_SET;
-      break;
-
-    case OPT_REPLACE:
-      opt_method= OPT_REPLACE;
-      break;
-
-    case OPT_ADD:
-      opt_method= OPT_ADD;
-      break;
-
-    case OPT_HASH:
-      opt_hash= strdup(optarg);
-      break;
-
-    case OPT_USERNAME:
-      opt_username= optarg;
-      break;
-
-    case OPT_PASSWD:
-      opt_passwd= optarg;
-      break;
-
-    case OPT_QUIET:
-      close_stdio();
-      break;
-
-    case OPT_UDP:
-      opt_udp= true;
-      break;
-
-    case OPT_BUFFER:
-      opt_buffer= true;
-      break;
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(1);
-    default:
-      abort();
-    }
-  }
-
-  if (opt_version)
-  {
-    version_command(PROGRAM_NAME);
-    exit(EXIT_SUCCESS);
-  }
-
-  if (opt_help)
-  {
-    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
-    exit(EXIT_SUCCESS);
-  }
-}
diff --git a/clients/memcp.sh b/clients/memcp.sh
deleted file mode 100755 (executable)
index a2f7d53..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-clients/memcp -v --servers localhost mem.testdata
diff --git a/clients/memdump.cc b/clients/memdump.cc
deleted file mode 100644 (file)
index 48c35d3..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-#include "mem_config.h"
-
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <fcntl.h>
-#include <getopt.h>
-#include <inttypes.h>
-#include <iostream>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <libmemcached-1.0/memcached.h>
-
-#include "client_options.h"
-#include "utilities.h"
-
-#define PROGRAM_NAME "memdump"
-#define PROGRAM_DESCRIPTION "Dump all values from one or many servers."
-
-/* Prototypes */
-static void options_parse(int argc, char *argv[]);
-
-static bool opt_binary=0;
-static int opt_verbose= 0;
-static char *opt_servers= NULL;
-static char *opt_hash= NULL;
-static char *opt_username;
-static char *opt_passwd;
-
-/* Print the keys and counter how many were found */
-static memcached_return_t key_printer(const memcached_st *,
-                                      const char *key, size_t key_length,
-                                      void *)
-{
-  std::cout.write(key, key_length);
-  std::cout << std::endl;
-
-  return MEMCACHED_SUCCESS;
-}
-
-int main(int argc, char *argv[])
-{
-  memcached_dump_fn callbacks[1];
-
-  callbacks[0]= &key_printer;
-
-  options_parse(argc, argv);
-
-  if (opt_servers == NULL)
-  {
-    char *temp;
-
-    if ((temp= getenv("MEMCACHED_SERVERS")))
-    {
-      opt_servers= strdup(temp);
-    }
-    else if (argc >= 1 and argv[--argc])
-    {
-      opt_servers= strdup(argv[argc]);
-    }
-
-    if (opt_servers == NULL)
-    {
-      std::cerr << "No Servers provided" << std::endl;
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  memcached_server_st* servers= memcached_servers_parse(opt_servers);
-  if (servers == NULL or memcached_server_list_count(servers) == 0)
-  {
-    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  memcached_st *memc= memcached_create(NULL);
-  if (memc == NULL)
-  {
-    std::cerr << "Could not allocate a memcached_st structure.\n" << std::endl;
-    return EXIT_FAILURE;
-  }
-  process_hash_option(memc, opt_hash);
-
-  memcached_server_push(memc, servers);
-  memcached_server_list_free(servers);
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
-                         (uint64_t)opt_binary);
-
-  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    memcached_free(memc);
-    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  if (opt_username)
-  {
-    memcached_return_t ret;
-    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
-    {
-      std::cerr << memcached_last_error_message(memc) << std::endl;
-      memcached_free(memc);
-      return EXIT_FAILURE;
-    }
-  }
-
-  memcached_return_t rc= memcached_dump(memc, callbacks, NULL, 1);
-
-  int exit_code= EXIT_SUCCESS;
-  if (memcached_failed(rc))
-  {
-    if (opt_verbose)
-    {
-      std::cerr << "Failed to dump keys: " << memcached_last_error_message(memc) << std::endl;
-    }
-    exit_code= EXIT_FAILURE;
-  }
-
-  memcached_free(memc);
-
-  if (opt_servers)
-  {
-    free(opt_servers);
-  }
-  if (opt_hash)
-  {
-    free(opt_hash);
-  }
-
-  return exit_code;
-}
-
-static void options_parse(int argc, char *argv[])
-{
-  static struct option long_options[]=
-    {
-      {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
-      {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
-      {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
-      {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
-      {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
-      {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
-      {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
-      {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
-      {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
-      {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
-      {0, 0, 0, 0}
-    };
-
-  int option_index= 0;
-  bool opt_version= false;
-  bool opt_help= false;
-  while (1)
-  {
-    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
-
-    if (option_rv == -1) break;
-
-    switch (option_rv)
-    {
-    case 0:
-      break;
-
-    case OPT_BINARY:
-      opt_binary= true;
-      break;
-
-    case OPT_VERBOSE: /* --verbose or -v */
-      opt_verbose= OPT_VERBOSE;
-      break;
-
-    case OPT_DEBUG: /* --debug or -d */
-      opt_verbose= OPT_DEBUG;
-      break;
-
-    case OPT_VERSION: /* --version or -V */
-      opt_verbose= true;
-      break;
-
-    case OPT_HELP: /* --help or -h */
-      opt_help= true;
-      break;
-
-    case OPT_SERVERS: /* --servers or -s */
-      opt_servers= strdup(optarg);
-      break;
-
-    case OPT_HASH:
-      opt_hash= strdup(optarg);
-      break;
-
-    case OPT_USERNAME:
-       opt_username= optarg;
-       break;
-
-    case OPT_PASSWD:
-       opt_passwd= optarg;
-       break;
-
-    case OPT_QUIET:
-      close_stdio();
-      break;
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(1);
-    default:
-      abort();
-    }
-  }
-
-  if (opt_version)
-  {
-    version_command(PROGRAM_NAME);
-    exit(EXIT_SUCCESS);
-  }
-
-  if (opt_help)
-  {
-    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, NULL);
-    exit(EXIT_SUCCESS);
-  }
-}
diff --git a/clients/memdump.sh b/clients/memdump.sh
deleted file mode 100755 (executable)
index 6e131d2..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-clients/memdump -v --servers localhost
diff --git a/clients/memerror.cc b/clients/memerror.cc
deleted file mode 100644 (file)
index 3cee64c..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-#include "mem_config.h"
-
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <climits>
-
-#include <getopt.h>
-#include <iostream>
-#include <unistd.h>
-
-#include <libmemcached-1.0/memcached.h>
-
-#include "utilities.h"
-
-#define PROGRAM_NAME "memerror"
-#define PROGRAM_DESCRIPTION "Translate a memcached errror code into a string."
-
-
-/* Prototypes */
-void options_parse(int argc, char *argv[]);
-
-int main(int argc, char *argv[])
-{
-  options_parse(argc, argv);
-
-  if (argc < 2)
-  {
-    return EXIT_FAILURE;
-  }
-
-  while (optind < argc)
-  {
-    errno= 0;
-    char *nptr;
-    unsigned long value= strtoul(argv[optind], &nptr, 10);
-
-    if ((errno != 0) or
-        (nptr == argv[optind] and value == 0) or
-        (value == ULONG_MAX and errno == ERANGE) or
-        (value == 0 and errno == EINVAL))
-    {
-      std::cerr << "strtoul() was unable to parse given value" << std::endl;
-      return EXIT_FAILURE;
-    }
-
-    if (value < MEMCACHED_MAXIMUM_RETURN)
-    {
-      std::cout << memcached_strerror(NULL, (memcached_return_t)value) << std::endl;
-    }
-    else
-    {
-      std::cerr << memcached_strerror(NULL, MEMCACHED_MAXIMUM_RETURN) << std::endl;
-      return EXIT_FAILURE;
-    }
-
-    optind++;
-  }
-
-  return EXIT_SUCCESS;
-}
-
-
-void options_parse(int argc, char *argv[])
-{
-  static struct option long_options[]=
-    {
-      {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
-      {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
-      {0, 0, 0, 0},
-    };
-
-  bool opt_version= false;
-  bool opt_help= false;
-  int option_index= 0;
-  while (1) 
-  {
-    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
-    if (option_rv == -1)
-    {
-      break;
-    }
-
-    switch (option_rv)
-    {
-    case 0:
-      break;
-
-    case OPT_VERSION: /* --version or -V */
-      opt_version= true;
-      break;
-
-    case OPT_HELP: /* --help or -h */
-      opt_help= true;
-      break;
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(EXIT_FAILURE);
-
-    default:
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  if (opt_version)
-  {
-    version_command(PROGRAM_NAME);
-    exit(EXIT_SUCCESS);
-  }
-
-  if (opt_help)
-  {
-    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, NULL);
-    exit(EXIT_SUCCESS);
-  }
-}
diff --git a/clients/memerror.sh b/clients/memerror.sh
deleted file mode 100755 (executable)
index 3843b55..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-clients/memerror 0 1 2 3
diff --git a/clients/memexist.cc b/clients/memexist.cc
deleted file mode 100644 (file)
index 505f538..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-#include "mem_config.h"
-
-#include <cstdio>
-#include <cstring>
-#include <getopt.h>
-#include <iostream>
-#include <unistd.h>
-
-#include <libmemcached-1.0/memcached.h>
-#include "client_options.h"
-#include "utilities.h"
-
-static int opt_binary= 0;
-static int opt_verbose= 0;
-static char *opt_servers= NULL;
-static char *opt_hash= NULL;
-static char *opt_username;
-static char *opt_passwd;
-
-#define PROGRAM_NAME "memexist"
-#define PROGRAM_DESCRIPTION "Check for the existance of a key within a cluster."
-
-/* Prototypes */
-static void options_parse(int argc, char *argv[]);
-
-int main(int argc, char *argv[])
-{
-  options_parse(argc, argv);
-  initialize_sockets();
-
-  if (opt_servers == NULL)
-  {
-    char *temp;
-
-    if ((temp= getenv("MEMCACHED_SERVERS")))
-    {
-      opt_servers= strdup(temp);
-    }
-
-    if (opt_servers == NULL)
-    {
-      std::cerr << "No Servers provided" << std::endl;
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  memcached_server_st* servers= memcached_servers_parse(opt_servers);
-  if (servers == NULL or memcached_server_list_count(servers) == 0)
-  {
-    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  memcached_st* memc= memcached_create(NULL);
-  process_hash_option(memc, opt_hash);
-
-  memcached_server_push(memc, servers);
-  memcached_server_list_free(servers);
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
-                         (uint64_t) opt_binary);
-
-  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    memcached_free(memc);
-    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  if (opt_username)
-  {
-    memcached_return_t ret;
-    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
-    {
-      std::cerr << memcached_last_error_message(memc) << std::endl;
-      memcached_free(memc);
-      return EXIT_FAILURE;
-    }
-  }
-
-  int return_code= EXIT_SUCCESS;
-
-  while (optind < argc)
-  {
-    memcached_return_t rc= memcached_exist(memc, argv[optind], strlen(argv[optind]));
-
-    if (rc == MEMCACHED_NOTFOUND)
-    {
-      if (opt_verbose)
-      {
-        std::cout << "Could not find key \"" << argv[optind] << "\"" << std::endl;
-      }
-
-      return_code= EXIT_FAILURE;
-    }
-    else if (memcached_failed(rc))
-    {
-      if (opt_verbose)
-      {
-        std::cerr << "Fatal error for key \"" << argv[optind] << "\" :" <<  memcached_last_error_message(memc) << std::endl;
-      }
-
-      return_code= EXIT_FAILURE;
-    }
-    else // success
-    {
-      if (opt_verbose)
-      {
-        std::cout << "Found key " << argv[optind] << std::endl;
-      }
-    }
-
-    optind++;
-  }
-
-  memcached_free(memc);
-
-  if (opt_servers)
-  {
-    free(opt_servers);
-  }
-
-  if (opt_hash)
-  {
-    free(opt_hash);
-  }
-
-  return return_code;
-}
-
-
-static void options_parse(int argc, char *argv[])
-{
-  memcached_programs_help_st help_options[]=
-  {
-    {0},
-  };
-
-  static struct option long_options[]=
-  {
-    {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
-    {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
-    {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
-    {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
-    {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
-    {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
-    {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
-    {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
-    {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
-    {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
-    {0, 0, 0, 0},
-  };
-
-  bool opt_version= false;
-  bool opt_help= false;
-  int option_index= 0;
-
-  while (1)
-  {
-    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
-    if (option_rv == -1) 
-    {
-      break;
-    }
-
-    switch (option_rv)
-    {
-    case 0:
-      break;
-
-    case OPT_BINARY:
-      opt_binary = 1;
-      break;
-
-    case OPT_VERBOSE: /* --verbose or -v */
-      opt_verbose = OPT_VERBOSE;
-      break;
-
-    case OPT_DEBUG: /* --debug or -d */
-      opt_verbose = OPT_DEBUG;
-      break;
-
-    case OPT_VERSION: /* --version or -V */
-      opt_version= true;
-      break;
-
-    case OPT_HELP: /* --help or -h */
-      opt_help= true;
-      break;
-
-    case OPT_SERVERS: /* --servers or -s */
-      opt_servers= strdup(optarg);
-      break;
-
-    case OPT_HASH:
-      opt_hash= strdup(optarg);
-      break;
-
-    case OPT_USERNAME:
-      opt_username= optarg;
-      break;
-
-    case OPT_PASSWD:
-      opt_passwd= optarg;
-      break;
-
-    case OPT_QUIET:
-      close_stdio();
-      break;
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(EXIT_SUCCESS);
-
-    default:
-      abort();
-    }
-  }
-
-  if (opt_version)
-  {
-    version_command(PROGRAM_NAME);
-    exit(EXIT_SUCCESS);
-  }
-
-  if (opt_help)
-  {
-    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
-    exit(EXIT_SUCCESS);
-  }
-}
diff --git a/clients/memexist.sh b/clients/memexist.sh
deleted file mode 100755 (executable)
index aa8a2fe..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/bash
-clients/memcp.sh
-clients/memexist -v --servers localhost mem.testdata
diff --git a/clients/memflush.cc b/clients/memflush.cc
deleted file mode 100644 (file)
index 71545ea..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-#include "mem_config.h"
-
-#include <cerrno>
-#include <cstdio>
-#include <cstring>
-#include <getopt.h>
-#include <iostream>
-#include <unistd.h>
-
-#include <libmemcached-1.0/memcached.h>
-#include "client_options.h"
-#include "utilities.h"
-
-static int opt_binary= 0;
-static int opt_verbose= 0;
-static time_t opt_expire= 0;
-static char *opt_servers= NULL;
-static char *opt_username;
-static char *opt_passwd;
-
-#define PROGRAM_NAME "memflush"
-#define PROGRAM_DESCRIPTION "Erase all data in a server of memcached servers."
-
-/* Prototypes */
-void options_parse(int argc, char *argv[]);
-
-int main(int argc, char *argv[])
-{
-  options_parse(argc, argv);
-
-  if (opt_servers == NULL)
-  {
-    char *temp;
-
-    if ((temp= getenv("MEMCACHED_SERVERS")))
-    {
-      opt_servers= strdup(temp);
-    }
-
-    if (opt_servers == NULL)
-    {
-      std::cerr << "No Servers provided" << std::endl;
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  memcached_server_st* servers= memcached_servers_parse(opt_servers);
-  if (servers == NULL or memcached_server_list_count(servers) == 0)
-  {
-    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  memcached_st *memc= memcached_create(NULL);
-  memcached_server_push(memc, servers);
-  memcached_server_list_free(servers);
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
-                         (uint64_t) opt_binary);
-
-  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    memcached_free(memc);
-    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  if (opt_username)
-  {
-    memcached_return_t ret;
-    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
-    {
-      std::cerr << memcached_last_error_message(memc) << std::endl;
-      memcached_free(memc);
-      return EXIT_FAILURE;
-    }
-  }
-
-  memcached_return_t rc = memcached_flush(memc, opt_expire);
-  if (rc != MEMCACHED_SUCCESS)
-  {
-    std::cerr << memcached_last_error_message(memc) << std::endl;
-  }
-
-  memcached_free(memc);
-
-  free(opt_servers);
-
-  return EXIT_SUCCESS;
-}
-
-
-void options_parse(int argc, char *argv[])
-{
-  static struct option long_options[]=
-  {
-    {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
-    {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
-    {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
-    {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
-    {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
-    {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
-    {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
-    {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
-    {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
-    {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
-    {0, 0, 0, 0},
-  };
-
-  bool opt_version= false;
-  bool opt_help= false;
-  int option_index= 0;
-  while (1)
-  {
-    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
-    if (option_rv == -1) break;
-    switch (option_rv)
-    {
-    case 0:
-      break;
-
-    case OPT_BINARY:
-      opt_binary= true;
-      break;
-
-    case OPT_VERBOSE: /* --verbose or -v */
-      opt_verbose= OPT_VERBOSE;
-      break;
-
-    case OPT_DEBUG: /* --debug or -d */
-      opt_verbose= OPT_DEBUG;
-      break;
-
-    case OPT_VERSION: /* --version or -V */
-      opt_version= true;
-      break;
-
-    case OPT_HELP: /* --help or -h */
-      opt_help= true;
-      break;
-
-    case OPT_SERVERS: /* --servers or -s */
-      opt_servers= strdup(optarg);
-      break;
-
-    case OPT_EXPIRE: /* --expire */
-      errno= 0;
-      opt_expire= (time_t)strtoll(optarg, (char **)NULL, 10);
-      if (errno != 0)
-      {
-        std::cerr << "Incorrect value passed to --expire: `" << optarg << "`" << std::endl;
-        exit(EXIT_FAILURE);
-      }
-      break;
-
-    case OPT_USERNAME:
-      opt_username= optarg;
-      break;
-
-    case OPT_PASSWD:
-      opt_passwd= optarg;
-      break;
-
-    case OPT_QUIET:
-      close_stdio();
-      break;
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(EXIT_FAILURE);
-
-    default:
-      abort();
-    }
-  }
-
-  if (opt_version)
-  {
-    version_command(PROGRAM_NAME);
-    exit(EXIT_SUCCESS);
-  }
-
-  if (opt_help)
-  {
-    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, NULL);
-    exit(EXIT_SUCCESS);
-  }
-}
diff --git a/clients/memflush.sh b/clients/memflush.sh
deleted file mode 100755 (executable)
index f841e70..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-clients/memflush -v --servers localhost
diff --git a/clients/memparse.cc b/clients/memparse.cc
deleted file mode 100644 (file)
index fc2cb0c..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <mem_config.h>
-
-#include <cstdio>
-#include <cstring>
-#include <iostream>
-
-#include <libmemcached-1.0/memcached.h>
-
-int main(int argc, char *argv[])
-{
-
-  if (argc < 2)
-  {
-    std::cerr << "No arguments provided." << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  for (int x= 1; x < argc; x++)
-  {
-    char buffer[BUFSIZ];
-    memcached_return_t rc;
-    rc= libmemcached_check_configuration(argv[x], strlen(argv[x]), buffer, sizeof(buffer));
-
-    if (rc != MEMCACHED_SUCCESS)
-    {
-      std::cerr << "Failed to parse argument #" << x << " " << argv[x] << std::endl;
-      std::cerr << buffer << std::endl;
-      return EXIT_FAILURE;
-    }
-  }
-
-  return EXIT_SUCCESS;
-}
diff --git a/clients/memparse.sh b/clients/memparse.sh
deleted file mode 100755 (executable)
index f18b8e0..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-clients/memparse --server=localhost:11211/?1 --server=127.0.0.1:11211/?2
diff --git a/clients/memping.cc b/clients/memping.cc
deleted file mode 100644 (file)
index 180d6a2..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-#include "mem_config.h"
-
-#include <cerrno>
-#include <cstdio>
-#include <cstring>
-#include <getopt.h>
-#include <unistd.h>
-
-#include <libmemcached-1.0/memcached.h>
-#include <libmemcachedutil-1.0/util.h>
-#include "client_options.h"
-#include "utilities.h"
-
-#include <iostream>
-
-static bool opt_binary= false;
-static int opt_verbose= 0;
-static time_t opt_expire= 0;
-static char *opt_servers= NULL;
-static char *opt_username;
-static char *opt_passwd;
-
-#define PROGRAM_NAME "memping"
-#define PROGRAM_DESCRIPTION "Ping a server to see if it is alive"
-
-/* Prototypes */
-void options_parse(int argc, char *argv[]);
-
-int main(int argc, char *argv[])
-{
-  options_parse(argc, argv);
-
-  if (opt_servers == NULL)
-  {
-    char *temp;
-
-    if ((temp= getenv("MEMCACHED_SERVERS")))
-    {
-      opt_servers= strdup(temp);
-    }
-    
-    if (opt_servers == NULL)
-    {
-      std::cerr << "No Servers provided" << std::endl;
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  int exit_code= EXIT_SUCCESS;
-  memcached_server_st *servers= memcached_servers_parse(opt_servers);
-  if (servers == NULL or memcached_server_list_count(servers) == 0)
-  {
-    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
-    exit_code= EXIT_FAILURE;
-  }
-  else
-  {
-    for (uint32_t x= 0; x < memcached_server_list_count(servers); x++)
-    {
-      memcached_return_t instance_rc;
-      const char *hostname= servers[x].hostname;
-      in_port_t port= servers[x].port;
-
-      if (opt_verbose)
-      {
-        std::cout << "Trying to ping " << hostname << ":" << port << std::endl;
-      }
-
-      if (libmemcached_util_ping2(hostname, port, opt_username, opt_passwd, &instance_rc) == false)
-      {
-        std::cerr << "Failed to ping " << hostname << ":" << port << " " << memcached_strerror(NULL, instance_rc) <<  std::endl;
-        exit_code= EXIT_FAILURE;
-      }
-    }
-  }
-  memcached_server_list_free(servers);
-
-  free(opt_servers);
-
-  return exit_code;
-}
-
-
-void options_parse(int argc, char *argv[])
-{
-  memcached_programs_help_st help_options[]=
-  {
-    {0},
-  };
-
-  static struct option long_options[]=
-  {
-    {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
-    {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
-    {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
-    {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
-    {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
-    {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
-    {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
-    {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
-    {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
-    {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
-    {0, 0, 0, 0},
-  };
-
-  bool opt_version= false;
-  bool opt_help= false;
-  int option_index= 0;
-  while (1)
-  {
-    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
-
-    if (option_rv == -1) break;
-
-    switch (option_rv)
-    {
-    case 0:
-      break;
-
-    case OPT_BINARY:
-      opt_binary= true;
-      break;
-
-    case OPT_VERBOSE: /* --verbose or -v */
-      opt_verbose = OPT_VERBOSE;
-      break;
-
-    case OPT_DEBUG: /* --debug or -d */
-      opt_verbose = OPT_DEBUG;
-      break;
-
-    case OPT_VERSION: /* --version or -V */
-      version_command(PROGRAM_NAME);
-      break;
-
-    case OPT_HELP: /* --help or -h */
-      help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
-      break;
-
-    case OPT_SERVERS: /* --servers or -s */
-      opt_servers= strdup(optarg);
-      break;
-
-    case OPT_EXPIRE: /* --expire */
-      errno= 0;
-      opt_expire= time_t(strtoll(optarg, (char **)NULL, 10));
-      if (errno != 0)
-      {
-        std::cerr << "Incorrect value passed to --expire: `" << optarg << "`" << std::endl;
-        exit(EXIT_FAILURE);
-      }
-      break;
-
-    case OPT_USERNAME:
-      opt_username= optarg;
-      opt_binary= true;
-      break;
-
-    case OPT_PASSWD:
-      opt_passwd= optarg;
-      break;
-
-    case OPT_QUIET:
-      close_stdio();
-      break;
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(1);
-    default:
-      abort();
-    }
-  }
-
-  if (opt_version)
-  {
-    version_command(PROGRAM_NAME);
-    exit(EXIT_SUCCESS);
-  }
-
-  if (opt_help)
-  {
-    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
-    exit(EXIT_SUCCESS);
-  }
-}
diff --git a/clients/memping.sh b/clients/memping.sh
deleted file mode 100755 (executable)
index 33100e7..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-clients/memping -v --servers localhost
diff --git a/clients/memrm.cc b/clients/memrm.cc
deleted file mode 100644 (file)
index 50ead7a..0000000
+++ /dev/null
@@ -1,257 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-#include "mem_config.h"
-
-#include <cerrno>
-#include <cstdio>
-#include <cstring>
-#include <getopt.h>
-#include <iostream>
-#include <unistd.h>
-
-#include <libmemcached-1.0/memcached.h>
-#include "client_options.h"
-#include "utilities.h"
-
-static int opt_binary= 0;
-static int opt_verbose= 0;
-static time_t opt_expire= 0;
-static char *opt_servers= NULL;
-static char *opt_hash= NULL;
-static char *opt_username;
-static char *opt_passwd;
-
-#define PROGRAM_NAME "memrm"
-#define PROGRAM_DESCRIPTION "Erase a key or set of keys from a memcached cluster."
-
-/* Prototypes */
-static void options_parse(int argc, char *argv[]);
-
-int main(int argc, char *argv[])
-{
-  options_parse(argc, argv);
-  initialize_sockets();
-
-  if (opt_servers == NULL)
-  {
-    char *temp;
-
-    if ((temp= getenv("MEMCACHED_SERVERS")))
-    {
-      opt_servers= strdup(temp);
-    }
-
-    if (opt_servers == NULL)
-    {
-      std::cerr << "No Servers provided" << std::endl;
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  memcached_server_st* servers= memcached_servers_parse(opt_servers);
-  if (servers == NULL or memcached_server_list_count(servers) == 0)
-  {
-    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  memcached_st* memc= memcached_create(NULL);
-  process_hash_option(memc, opt_hash);
-
-  memcached_server_push(memc, servers);
-  memcached_server_list_free(servers);
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
-                         (uint64_t) opt_binary);
-
-  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    memcached_free(memc);
-    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  if (opt_username)
-  {
-    memcached_return_t ret;
-    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
-    {
-      std::cerr << memcached_last_error_message(memc) << std::endl;
-      memcached_free(memc);
-      return EXIT_FAILURE;
-    }
-  }
-
-  int return_code= EXIT_SUCCESS;
-
-  while (optind < argc)
-  {
-    memcached_return_t rc= memcached_delete(memc, argv[optind], strlen(argv[optind]), opt_expire);
-
-    if (rc == MEMCACHED_NOTFOUND)
-    {
-      if (opt_verbose)
-      {
-        std::cerr << "Could not find key \"" << argv[optind] << "\"" << std::endl;
-      }
-    }
-    else if (memcached_fatal(rc))
-    {
-      if (opt_verbose)
-      {
-        std::cerr << "Failed to delete key \"" << argv[optind] << "\" :" <<  memcached_last_error_message(memc) << std::endl;
-      }
-
-      return_code= EXIT_FAILURE;
-    }
-    else // success
-    {
-      if (opt_verbose)
-      {
-        std::cout << "Deleted key " << argv[optind];
-        if (opt_expire)
-        {
-          std::cout << " expires: " << opt_expire << std::endl;
-        }
-        std::cout << std::endl;
-      }
-    }
-
-    optind++;
-  }
-
-  memcached_free(memc);
-
-  if (opt_servers)
-  {
-    free(opt_servers);
-  }
-
-  if (opt_hash)
-  {
-    free(opt_hash);
-  }
-
-  return return_code;
-}
-
-
-static void options_parse(int argc, char *argv[])
-{
-  memcached_programs_help_st help_options[]=
-  {
-    {0},
-  };
-
-  static struct option long_options[]=
-  {
-    {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
-    {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
-    {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
-    {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
-    {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
-    {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
-    {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
-    {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
-    {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
-    {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
-    {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
-    {0, 0, 0, 0},
-  };
-
-  bool opt_version= false;
-  bool opt_help= false;
-  int option_index= 0;
-
-  while (1)
-  {
-    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
-    if (option_rv == -1) 
-    {
-      break;
-    }
-
-    switch (option_rv)
-    {
-    case 0:
-      break;
-
-    case OPT_BINARY:
-      opt_binary = 1;
-      break;
-
-    case OPT_VERBOSE: /* --verbose or -v */
-      opt_verbose = OPT_VERBOSE;
-      break;
-
-    case OPT_DEBUG: /* --debug or -d */
-      opt_verbose = OPT_DEBUG;
-      break;
-
-    case OPT_VERSION: /* --version or -V */
-      opt_version= true;
-      break;
-
-    case OPT_HELP: /* --help or -h */
-      opt_help= true;
-      break;
-
-    case OPT_SERVERS: /* --servers or -s */
-      opt_servers= strdup(optarg);
-      break;
-
-    case OPT_EXPIRE: /* --expire */
-      errno= 0;
-      opt_expire= (time_t)strtoll(optarg, (char **)NULL, 10);
-      if (errno != 0)
-      {
-        std::cerr << "Incorrect value passed to --expire: `" << optarg << "`" << std::endl;
-        exit(EXIT_FAILURE);
-      }
-      break;
-
-    case OPT_HASH:
-      opt_hash= strdup(optarg);
-      break;
-
-    case OPT_USERNAME:
-      opt_username= optarg;
-      break;
-
-    case OPT_PASSWD:
-      opt_passwd= optarg;
-      break;
-
-    case OPT_QUIET:
-      close_stdio();
-      break;
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(EXIT_SUCCESS);
-
-    default:
-      abort();
-    }
-  }
-
-  if (opt_version)
-  {
-    version_command(PROGRAM_NAME);
-    exit(EXIT_SUCCESS);
-  }
-
-  if (opt_help)
-  {
-    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
-    exit(EXIT_SUCCESS);
-  }
-}
diff --git a/clients/memrm.sh b/clients/memrm.sh
deleted file mode 100755 (executable)
index 4818d4d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-clients/memcp.sh
-clients/memrm -v --servers localhost mem.testdata
diff --git a/clients/memslap.cc b/clients/memslap.cc
deleted file mode 100644 (file)
index 9bc4f23..0000000
+++ /dev/null
@@ -1,577 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <mem_config.h>
-
-#include <cassert>
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <fcntl.h>
-#include <getopt.h>
-#include <memory>
-#include <pthread.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <iostream>
-
-#include <libmemcached-1.0/memcached.h>
-
-#include "client_options.h"
-#include "utilities.h"
-#include "generator.h"
-#include "execute.h"
-
-#define DEFAULT_INITIAL_LOAD 10000
-#define DEFAULT_EXECUTE_NUMBER 10000
-#define DEFAULT_CONCURRENCY 1
-
-#define VALUE_BYTES 4096
-
-#define PROGRAM_NAME "memslap"
-#define PROGRAM_DESCRIPTION "Generates a load against a memcached custer of servers."
-
-/* Global Thread counter */
-volatile unsigned int master_wakeup;
-pthread_mutex_t sleeper_mutex;
-pthread_cond_t sleep_threshhold;
-
-/* Types */
-enum test_t {
-  SET_TEST,
-  GET_TEST,
-  MGET_TEST
-};
-
-struct thread_context_st {
-  unsigned int key_count;
-  pairs_st *initial_pairs;
-  unsigned int initial_number;
-  pairs_st *execute_pairs;
-  unsigned int execute_number;
-  char **keys;
-  size_t *key_lengths;
-  test_t test;
-  memcached_st *memc;
-  const memcached_st* root;
-
-  thread_context_st(const memcached_st* memc_arg, test_t test_arg) :
-    key_count(0),
-    initial_pairs(NULL),
-    initial_number(0),
-    execute_pairs(NULL),
-    execute_number(0),
-    keys(0),
-    key_lengths(NULL),
-    test(test_arg),
-    memc(NULL),
-    root(memc_arg)
-  {
-  }
-
-  void init()
-  {
-    memc= memcached_clone(NULL, root);
-  }
-
-  ~thread_context_st()
-  {
-    if (execute_pairs)
-    {
-      pairs_free(execute_pairs);
-    }
-    memcached_free(memc);
-  }
-};
-
-struct conclusions_st {
-  long int load_time;
-  long int read_time;
-  unsigned int rows_loaded;
-  unsigned int rows_read;
-
-  conclusions_st() :
-    load_time(0),
-    read_time(0),
-    rows_loaded(0),
-    rows_read()
-  { }
-};
-
-/* Prototypes */
-void options_parse(int argc, char *argv[]);
-void conclusions_print(conclusions_st *conclusion);
-void scheduler(memcached_server_st *servers, conclusions_st *conclusion);
-pairs_st *load_create_data(memcached_st *memc, unsigned int number_of,
-                           unsigned int *actual_loaded);
-void flush_all(memcached_st *memc);
-
-static bool opt_binary= 0;
-static int opt_verbose= 0;
-static int opt_flush= 0;
-static int opt_non_blocking_io= 0;
-static int opt_tcp_nodelay= 0;
-static unsigned int opt_execute_number= 0;
-static unsigned int opt_createial_load= 0;
-static unsigned int opt_concurrency= 0;
-static int opt_displayflag= 0;
-static char *opt_servers= NULL;
-static bool opt_udp_io= false;
-test_t opt_test= SET_TEST;
-
-extern "C" {
-
-static __attribute__((noreturn)) void *run_task(void *p)
-{
-  thread_context_st *context= (thread_context_st *)p;
-
-  context->init();
-
-  pthread_mutex_lock(&sleeper_mutex);
-  while (master_wakeup)
-  {
-    pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
-  }
-  pthread_mutex_unlock(&sleeper_mutex);
-
-  /* Do Stuff */
-  switch (context->test)
-  {
-  case SET_TEST:
-    assert(context->execute_pairs);
-    execute_set(context->memc, context->execute_pairs, context->execute_number);
-    break;
-
-  case GET_TEST:
-    execute_get(context->memc, context->initial_pairs, context->initial_number);
-    break;
-
-  case MGET_TEST:
-    execute_mget(context->memc, (const char*const*)context->keys, context->key_lengths, context->initial_number);
-    break;
-  }
-
-  delete context;
-
-  pthread_exit(0);
-}
-
-}
-
-
-int main(int argc, char *argv[])
-{
-  conclusions_st conclusion;
-
-  srandom((unsigned int)time(NULL));
-  options_parse(argc, argv);
-
-  if (opt_servers == NULL)
-  {
-    char *temp;
-
-    if ((temp= getenv("MEMCACHED_SERVERS")))
-    {
-      opt_servers= strdup(temp);
-    }
-    
-    if (opt_servers == NULL)
-    {
-      std::cerr << "No Servers provided" << std::endl;
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  memcached_server_st *servers= memcached_servers_parse(opt_servers);
-  if (servers == NULL or memcached_server_list_count(servers) == 0)
-  {
-    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  pthread_mutex_init(&sleeper_mutex, NULL);
-  pthread_cond_init(&sleep_threshhold, NULL);
-
-  int error_code= EXIT_SUCCESS;
-  try {
-    scheduler(servers, &conclusion);
-  }
-  catch(std::exception& e)
-  {
-    std::cerr << "Died with exception: " << e.what() << std::endl;
-    error_code= EXIT_FAILURE;
-  }
-
-  free(opt_servers);
-
-  (void)pthread_mutex_destroy(&sleeper_mutex);
-  (void)pthread_cond_destroy(&sleep_threshhold);
-  conclusions_print(&conclusion);
-  memcached_server_list_free(servers);
-
-  return error_code;
-}
-
-void scheduler(memcached_server_st *servers, conclusions_st *conclusion)
-{
-  unsigned int actual_loaded= 0; /* Fix warning */
-
-  struct timeval start_time, end_time;
-  pairs_st *pairs= NULL;
-
-  memcached_st *memc= memcached_create(NULL);
-
-  memcached_server_push(memc, servers);
-
-  /* We need to set udp behavior before adding servers to the client */
-  if (opt_udp_io)
-  {
-    if (memcached_failed(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, opt_udp_io)))
-    {
-      std::cerr << "Failed to enable UDP." << std::endl;
-      memcached_free(memc);
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
-                         (uint64_t)opt_binary);
-
-  if (opt_flush)
-  {
-    flush_all(memc);
-  }
-
-  if (opt_createial_load)
-  {
-    pairs= load_create_data(memc, opt_createial_load, &actual_loaded);
-  }
-
-  char **keys= static_cast<char **>(calloc(actual_loaded, sizeof(char*)));
-  size_t *key_lengths= static_cast<size_t *>(calloc(actual_loaded, sizeof(size_t)));
-
-  if (keys == NULL or key_lengths == NULL)
-  {
-    free(keys);
-    free(key_lengths);
-    keys= NULL;
-    key_lengths= NULL;
-  }
-  else
-  {
-    for (uint32_t x= 0; x < actual_loaded; ++x)
-    {
-      keys[x]= pairs[x].key;
-      key_lengths[x]= pairs[x].key_length;
-    }
-  }
-
-  /* We set this after we have loaded */
-  {
-    if (opt_non_blocking_io)
-      memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1);
-
-    if (opt_tcp_nodelay)
-      memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1);
-  }
-
-  pthread_mutex_lock(&sleeper_mutex);
-  master_wakeup= 1;
-  pthread_mutex_unlock(&sleeper_mutex);
-
-  pthread_t *threads= new  (std::nothrow) pthread_t[opt_concurrency];
-
-  if (threads == NULL)
-  {
-    exit(EXIT_FAILURE);
-  }
-
-  for (uint32_t x= 0; x < opt_concurrency; x++)
-  {
-    thread_context_st *context= new thread_context_st(memc, opt_test);
-    context->test= opt_test;
-
-    context->initial_pairs= pairs;
-    context->initial_number= actual_loaded;
-    context->keys= keys;
-    context->key_lengths= key_lengths;
-
-    if (opt_test == SET_TEST)
-    {
-      context->execute_pairs= pairs_generate(opt_execute_number, VALUE_BYTES);
-      context->execute_number= opt_execute_number;
-    }
-
-    /* now you create the thread */
-    if (pthread_create(threads +x, NULL, run_task, (void *)context) != 0)
-    {
-      fprintf(stderr,"Could not create thread\n");
-      exit(1);
-    }
-  }
-
-  pthread_mutex_lock(&sleeper_mutex);
-  master_wakeup= 0;
-  pthread_mutex_unlock(&sleeper_mutex);
-  pthread_cond_broadcast(&sleep_threshhold);
-  gettimeofday(&start_time, NULL);
-
-  for (uint32_t x= 0; x < opt_concurrency; x++)
-  {
-    void *retval;
-    pthread_join(threads[x], &retval);
-  }
-  delete [] threads;
-
-  gettimeofday(&end_time, NULL);
-
-  conclusion->load_time= timedif(end_time, start_time);
-  conclusion->read_time= timedif(end_time, start_time);
-  free(keys);
-  free(key_lengths);
-  pairs_free(pairs);
-  memcached_free(memc);
-}
-
-void options_parse(int argc, char *argv[])
-{
-  memcached_programs_help_st help_options[]=
-  {
-    {0},
-  };
-
-  static struct option long_options[]=
-    {
-      {(OPTIONSTRING)"concurrency", required_argument, NULL, OPT_SLAP_CONCURRENCY},
-      {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
-      {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
-      {(OPTIONSTRING)"execute-number", required_argument, NULL, OPT_SLAP_EXECUTE_NUMBER},
-      {(OPTIONSTRING)"flag", no_argument, &opt_displayflag, OPT_FLAG},
-      {(OPTIONSTRING)"flush", no_argument, &opt_flush, OPT_FLUSH},
-      {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
-      {(OPTIONSTRING)"initial-load", required_argument, NULL, OPT_SLAP_INITIAL_LOAD}, /* Number to load initially */
-      {(OPTIONSTRING)"non-blocking", no_argument, &opt_non_blocking_io, OPT_SLAP_NON_BLOCK},
-      {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
-      {(OPTIONSTRING)"tcp-nodelay", no_argument, &opt_tcp_nodelay, OPT_SLAP_TCP_NODELAY},
-      {(OPTIONSTRING)"test", required_argument, NULL, OPT_SLAP_TEST},
-      {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
-      {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
-      {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
-      {(OPTIONSTRING)"udp", no_argument, NULL, OPT_UDP},
-      {0, 0, 0, 0},
-    };
-
-  bool opt_help= false;
-  bool opt_version= false;
-  int option_index= 0;
-  while (1)
-  {
-    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
-
-    if (option_rv == -1) break;
-
-    switch (option_rv)
-    {
-    case 0:
-      break;
-
-    case OPT_UDP:
-      if (opt_test == GET_TEST)
-      {
-        fprintf(stderr, "You can not run a get test in UDP mode. UDP mode "
-                  "does not currently support get ops.\n");
-        exit(1);
-      }
-      opt_udp_io= true;
-      break;
-
-    case OPT_BINARY:
-      opt_binary= true;
-      break;
-
-    case OPT_VERBOSE: /* --verbose or -v */
-      opt_verbose= OPT_VERBOSE;
-      break;
-
-    case OPT_DEBUG: /* --debug or -d */
-      opt_verbose= OPT_DEBUG;
-      break;
-
-    case OPT_VERSION: /* --version or -V */
-      opt_version= true;
-      break;
-
-    case OPT_HELP: /* --help or -h */
-      opt_help= true;
-      break;
-
-    case OPT_SERVERS: /* --servers or -s */
-      opt_servers= strdup(optarg);
-      break;
-
-    case OPT_SLAP_TEST:
-      if (strcmp(optarg, "get") == 0)
-      {
-        if (opt_udp_io == 1)
-        {
-          fprintf(stderr, "You can not run a get test in UDP mode. UDP mode "
-                  "does not currently support get ops.\n");
-          exit(EXIT_FAILURE);
-        }
-        opt_test= GET_TEST ;
-      }
-      else if (strcmp(optarg, "set") == 0)
-      {
-        opt_test= SET_TEST;
-      }
-      else if (strcmp(optarg, "mget") == 0)
-      {
-        opt_test= MGET_TEST;
-      }
-      else
-      {
-        fprintf(stderr, "Your test, %s, is not a known test\n", optarg);
-        exit(EXIT_FAILURE);
-      }
-      break;
-
-    case OPT_SLAP_CONCURRENCY:
-      errno= 0;
-      opt_concurrency= (unsigned int)strtoul(optarg, (char **)NULL, 10);
-      if (errno != 0)
-      {
-        fprintf(stderr, "Invalid value for concurrency: %s\n", optarg);
-        exit(EXIT_FAILURE);
-      }
-      break;
-
-    case OPT_SLAP_EXECUTE_NUMBER:
-      errno= 0;
-      opt_execute_number= (unsigned int)strtoul(optarg, (char **)NULL, 10);
-      if (errno != 0)
-      {
-        fprintf(stderr, "Invalid value for execute: %s\n", optarg);
-        exit(EXIT_FAILURE);
-      }
-      break;
-
-    case OPT_SLAP_INITIAL_LOAD:
-      errno= 0;
-      opt_createial_load= (unsigned int)strtoul(optarg, (char **)NULL, 10);
-      if (errno != 0)
-      {
-        fprintf(stderr, "Invalid value for initial load: %s\n", optarg);
-        exit(EXIT_FAILURE);
-      }
-      break;
-
-    case OPT_QUIET:
-      close_stdio();
-      break;
-
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(EXIT_FAILURE);
-
-    default:
-      abort();
-    }
-  }
-
-  if (opt_version)
-  {
-    version_command(PROGRAM_NAME);
-    exit(EXIT_SUCCESS);
-  }
-
-  if (opt_help)
-  {
-    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
-    exit(EXIT_SUCCESS);
-  }
-
-  if ((opt_test == GET_TEST or opt_test == MGET_TEST) and opt_createial_load == 0)
-    opt_createial_load= DEFAULT_INITIAL_LOAD;
-
-  if (opt_execute_number == 0)
-    opt_execute_number= DEFAULT_EXECUTE_NUMBER;
-
-  if (opt_concurrency == 0)
-    opt_concurrency= DEFAULT_CONCURRENCY;
-}
-
-void conclusions_print(conclusions_st *conclusion)
-{
-  printf("\tThreads connecting to servers %u\n", opt_concurrency);
-#ifdef NOT_FINISHED
-  printf("\tLoaded %u rows\n", conclusion->rows_loaded);
-  printf("\tRead %u rows\n", conclusion->rows_read);
-#endif
-  if (opt_test == SET_TEST)
-    printf("\tTook %ld.%03ld seconds to load data\n", conclusion->load_time / 1000,
-           conclusion->load_time % 1000);
-  else
-    printf("\tTook %ld.%03ld seconds to read data\n", conclusion->read_time / 1000,
-           conclusion->read_time % 1000);
-}
-
-void flush_all(memcached_st *memc)
-{
-  memcached_flush(memc, 0);
-}
-
-pairs_st *load_create_data(memcached_st *memc, unsigned int number_of,
-                           unsigned int *actual_loaded)
-{
-  memcached_st *memc_clone= memcached_clone(NULL, memc);
-  /* We always used non-blocking IO for load since it is faster */
-  memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_NO_BLOCK, 0);
-
-  pairs_st *pairs= pairs_generate(number_of, VALUE_BYTES);
-  *actual_loaded= execute_set(memc_clone, pairs, number_of);
-
-  memcached_free(memc_clone);
-
-  return pairs;
-}
diff --git a/clients/memslap.sh b/clients/memslap.sh
deleted file mode 100755 (executable)
index 85b78ef..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-clients/memslap -v --servers localhost
diff --git a/clients/memstat.cc b/clients/memstat.cc
deleted file mode 100644 (file)
index e5bac91..0000000
+++ /dev/null
@@ -1,465 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- * Authors: 
- *          Brian Aker
- *          Toru Maesaka
- */
-#include <mem_config.h>
-
-#include <cstdio>
-#include <cstring>
-#include <ctime>
-#include <iostream>
-#include <fcntl.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/types.h>
-
-#include <libmemcached-1.0/memcached.h>
-
-#include "client_options.h"
-#include "utilities.h"
-
-#define PROGRAM_NAME "memstat"
-#define PROGRAM_DESCRIPTION "Output the state of a memcached cluster."
-
-/* Prototypes */
-static void options_parse(int argc, char *argv[]);
-static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat);
-static void print_analysis_report(memcached_st *memc,
-                                  memcached_analysis_st *report);
-
-static bool opt_binary= false;
-static bool opt_verbose= false;
-static bool opt_server_version= false;
-static bool opt_analyze= false;
-static char *opt_servers= NULL;
-static char *stat_args= NULL;
-static char *analyze_mode= NULL;
-static char *opt_username;
-static char *opt_passwd;
-
-static struct option long_options[]=
-{
-  {(OPTIONSTRING)"args", required_argument, NULL, OPT_STAT_ARGS},
-  {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
-  {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
-  {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
-  {(OPTIONSTRING)"verbose", no_argument, NULL, OPT_VERBOSE},
-  {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
-  {(OPTIONSTRING)"debug", no_argument, NULL, OPT_DEBUG},
-  {(OPTIONSTRING)"server-version", no_argument, NULL, OPT_SERVER_VERSION},
-  {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
-  {(OPTIONSTRING)"analyze", optional_argument, NULL, OPT_ANALYZE},
-  {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
-  {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
-  {0, 0, 0, 0},
-};
-
-
-static memcached_return_t stat_printer(const memcached_instance_st * instance,
-                                       const char *key, size_t key_length,
-                                       const char *value, size_t value_length,
-                                       void *context)
-{
-  static const memcached_instance_st * last= NULL;
-  (void)context;
-
-  if (last != instance)
-  {
-    printf("Server: %s (%u)\n", memcached_server_name(instance),
-           (uint32_t)memcached_server_port(instance));
-    last= instance;
-  }
-
-  printf("\t %.*s: %.*s\n", (int)key_length, key, (int)value_length, value);
-
-  return MEMCACHED_SUCCESS;
-}
-
-static memcached_return_t server_print_callback(const memcached_st *,
-                                                const memcached_instance_st * instance,
-                                                void *)
-{
-  std::cerr << memcached_server_name(instance) << ":" << memcached_server_port(instance) <<
-    " " << int(memcached_server_major_version(instance)) << 
-    "." << int(memcached_server_minor_version(instance)) << 
-    "." << int(memcached_server_micro_version(instance)) << std::endl;
-
-  return MEMCACHED_SUCCESS;
-}
-
-int main(int argc, char *argv[])
-{
-  options_parse(argc, argv);
-  initialize_sockets();
-
-  if (opt_servers == NULL)
-  {
-    char *temp;
-    if ((temp= getenv("MEMCACHED_SERVERS")))
-    {
-      opt_servers= strdup(temp);
-    }
-
-    if (opt_servers == NULL)
-    {
-      std::cerr << "No Servers provided" << std::endl;
-      return EXIT_FAILURE;
-    }
-  }
-
-  memcached_server_st* servers= memcached_servers_parse(opt_servers);
-  if (servers == NULL or memcached_server_list_count(servers) == 0)
-  {
-    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
-    return EXIT_FAILURE;
-  }
-  
-  if (opt_servers)
-  {
-    free(opt_servers);
-  }
-
-  memcached_st *memc= memcached_create(NULL);
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, opt_binary);
-
-  memcached_return_t rc= memcached_server_push(memc, servers);
-  memcached_server_list_free(servers);
-
-  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    memcached_free(memc);
-    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  if (opt_username)
-  {
-    memcached_return_t ret;
-    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
-    {
-      std::cerr << memcached_last_error_message(memc) << std::endl;
-      memcached_free(memc);
-      return EXIT_FAILURE;
-    }
-  }
-
-  if (rc != MEMCACHED_SUCCESS and rc != MEMCACHED_SOME_ERRORS)
-  {
-    printf("Failure to communicate with servers (%s)\n",
-           memcached_strerror(memc, rc));
-    exit(EXIT_FAILURE);
-  }
-
-  if (opt_server_version)
-  {
-    if (memcached_failed(memcached_version(memc)))
-    {
-      std::cerr << "Unable to obtain server version";
-      exit(EXIT_FAILURE);
-    }
-
-    memcached_server_fn callbacks[1];
-    callbacks[0]= server_print_callback;
-    memcached_server_cursor(memc, callbacks, NULL,  1);
-  }
-  else if (opt_analyze)
-  {
-    memcached_stat_st *memc_stat= memcached_stat(memc, NULL, &rc);
-
-    if (memc_stat == NULL)
-    {
-      exit(EXIT_FAILURE);
-    }
-
-    run_analyzer(memc, memc_stat);
-
-    memcached_stat_free(memc, memc_stat);
-  }
-  else
-  {
-    rc= memcached_stat_execute(memc, stat_args, stat_printer, NULL);
-  }
-
-  memcached_free(memc);
-
-  return rc == MEMCACHED_SUCCESS ? EXIT_SUCCESS: EXIT_FAILURE;
-}
-
-static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat)
-{
-  memcached_return_t rc;
-
-  if (analyze_mode == NULL)
-  {
-    memcached_analysis_st *report;
-    report= memcached_analyze(memc, memc_stat, &rc);
-    if (rc != MEMCACHED_SUCCESS || report == NULL)
-    {
-      printf("Failure to analyze servers (%s)\n",
-             memcached_strerror(memc, rc));
-      exit(1);
-    }
-    print_analysis_report(memc, report);
-    free(report);
-  }
-  else if (strcmp(analyze_mode, "latency") == 0)
-  {
-    uint32_t flags, server_count= memcached_server_count(memc);
-    uint32_t num_of_tests= 32;
-    const char *test_key= "libmemcached_test_key";
-
-    memcached_st **servers= static_cast<memcached_st**>(malloc(sizeof(memcached_st*) * server_count));
-    if (servers == NULL)
-    {
-      fprintf(stderr, "Failed to allocate memory\n");
-      return;
-    }
-
-    for (uint32_t x= 0; x < server_count; x++)
-    {
-      const memcached_instance_st * instance=
-        memcached_server_instance_by_position(memc, x);
-
-      if ((servers[x]= memcached_create(NULL)) == NULL)
-      {
-        fprintf(stderr, "Failed to memcached_create()\n");
-        if (x > 0)
-        {
-          memcached_free(servers[0]);
-        }
-        x--;
-
-        for (; x > 0; x--)
-        {
-          memcached_free(servers[x]);
-        }
-
-        free(servers);
-
-        return;
-      }
-      memcached_server_add(servers[x],
-                           memcached_server_name(instance),
-                           memcached_server_port(instance));
-    }
-
-    printf("Network Latency Test:\n\n");
-    struct timeval start_time, end_time;
-    uint32_t slowest_server= 0;
-    long elapsed_time, slowest_time= 0;
-
-    for (uint32_t x= 0; x < server_count; x++)
-    {
-      const memcached_instance_st * instance=
-        memcached_server_instance_by_position(memc, x);
-      gettimeofday(&start_time, NULL);
-
-      for (uint32_t y= 0; y < num_of_tests; y++)
-      {
-        size_t vlen;
-        char *val= memcached_get(servers[x], test_key, strlen(test_key),
-                                 &vlen, &flags, &rc);
-        if (rc != MEMCACHED_NOTFOUND and rc != MEMCACHED_SUCCESS)
-        {
-          break;
-        }
-        free(val);
-      }
-      gettimeofday(&end_time, NULL);
-
-      elapsed_time= (long) timedif(end_time, start_time);
-      elapsed_time /= (long) num_of_tests;
-
-      if (elapsed_time > slowest_time)
-      {
-        slowest_server= x;
-        slowest_time= elapsed_time;
-      }
-
-      if (rc != MEMCACHED_NOTFOUND && rc != MEMCACHED_SUCCESS)
-      {
-        printf("\t %s (%d)  =>  failed to reach the server\n",
-               memcached_server_name(instance),
-               memcached_server_port(instance));
-      }
-      else
-      {
-        printf("\t %s (%d)  =>  %ld.%ld seconds\n",
-               memcached_server_name(instance),
-               memcached_server_port(instance),
-               elapsed_time / 1000, elapsed_time % 1000);
-      }
-    }
-
-    if (server_count > 1 && slowest_time > 0)
-    {
-      const memcached_instance_st * slowest=
-        memcached_server_instance_by_position(memc, slowest_server);
-
-      printf("---\n");
-      printf("Slowest Server: %s (%d) => %ld.%ld seconds\n",
-             memcached_server_name(slowest),
-             memcached_server_port(slowest),
-             slowest_time / 1000, slowest_time % 1000);
-    }
-    printf("\n");
-
-    for (uint32_t x= 0; x < server_count; x++)
-    {
-      memcached_free(servers[x]);
-    }
-
-    free(servers);
-    free(analyze_mode);
-  }
-  else
-  {
-    fprintf(stderr, "Invalid Analyzer Option provided\n");
-    free(analyze_mode);
-  }
-}
-
-static void print_analysis_report(memcached_st *memc,
-                                  memcached_analysis_st *report)
-                                  
-{
-  uint32_t server_count= memcached_server_count(memc);
-  const memcached_instance_st * most_consumed_server= memcached_server_instance_by_position(memc, report->most_consumed_server);
-  const memcached_instance_st * least_free_server= memcached_server_instance_by_position(memc, report->least_free_server);
-  const memcached_instance_st * oldest_server= memcached_server_instance_by_position(memc, report->oldest_server);
-
-  printf("Memcached Cluster Analysis Report\n\n");
-
-  printf("\tNumber of Servers Analyzed         : %u\n", server_count);
-  printf("\tAverage Item Size (incl/overhead)  : %u bytes\n",
-         report->average_item_size);
-
-  if (server_count == 1)
-  {
-    printf("\nFor a detailed report, you must supply multiple servers.\n");
-    return;
-  }
-
-  printf("\n");
-  printf("\tNode with most memory consumption  : %s:%u (%llu bytes)\n",
-         memcached_server_name(most_consumed_server),
-         (uint32_t)memcached_server_port(most_consumed_server),
-         (unsigned long long)report->most_used_bytes);
-  printf("\tNode with least free space         : %s:%u (%llu bytes remaining)\n",
-         memcached_server_name(least_free_server),
-         (uint32_t)memcached_server_port(least_free_server),
-         (unsigned long long)report->least_remaining_bytes);
-  printf("\tNode with longest uptime           : %s:%u (%us)\n",
-         memcached_server_name(oldest_server),
-         (uint32_t)memcached_server_port(oldest_server),
-         report->longest_uptime);
-  printf("\tPool-wide Hit Ratio                : %1.f%%\n", report->pool_hit_ratio);
-  printf("\n");
-}
-
-static void options_parse(int argc, char *argv[])
-{
-  memcached_programs_help_st help_options[]=
-  {
-    {0},
-  };
-
-  int option_index= 0;
-
-  bool opt_version= false;
-  bool opt_help= false;
-  while (1) 
-  {
-    int option_rv= getopt_long(argc, argv, "Vhvds:a", long_options, &option_index);
-
-    if (option_rv == -1)
-      break;
-
-    switch (option_rv)
-    {
-    case 0:
-      break;
-
-    case OPT_VERBOSE: /* --verbose or -v */
-      opt_verbose= true;
-      break;
-
-    case OPT_DEBUG: /* --debug or -d */
-      opt_verbose= true;
-      break;
-
-    case OPT_BINARY:
-      opt_binary= true;
-      break;
-
-    case OPT_SERVER_VERSION:
-      opt_server_version= true;
-      break;
-
-    case OPT_VERSION: /* --version or -V */
-      opt_version= true;
-      break;
-
-    case OPT_HELP: /* --help or -h */
-      opt_help= true;
-      break;
-
-    case OPT_SERVERS: /* --servers or -s */
-      opt_servers= strdup(optarg);
-      break;
-
-    case OPT_STAT_ARGS:
-      stat_args= strdup(optarg);
-      break;
-
-    case OPT_ANALYZE: /* --analyze or -a */
-      opt_analyze= true;
-      analyze_mode= (optarg) ? strdup(optarg) : NULL;
-      break;
-
-    case OPT_QUIET:
-      close_stdio();
-      break;
-
-    case OPT_USERNAME:
-      opt_username= optarg;
-      opt_binary= true;
-      break;
-
-    case OPT_PASSWD:
-      opt_passwd= optarg;
-      break;
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(1);
-    default:
-      abort();
-    }
-  }
-
-  if (opt_version)
-  {
-    version_command(PROGRAM_NAME);
-    exit(EXIT_SUCCESS);
-  }
-
-  if (opt_help)
-  {
-    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
-    exit(EXIT_SUCCESS);
-  }
-}
diff --git a/clients/memstat.sh b/clients/memstat.sh
deleted file mode 100755 (executable)
index b52ba65..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/bash
-clients/memstat -v --servers localhost
diff --git a/clients/memtouch.cc b/clients/memtouch.cc
deleted file mode 100644 (file)
index 09e0c92..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-#include <mem_config.h>
-
-#include <cerrno>
-#include <cstdio>
-#include <cstring>
-#include <getopt.h>
-#include <iostream>
-#include <unistd.h>
-
-#include <libmemcached-1.0/memcached.h>
-
-#include "utilities.h"
-
-#define PROGRAM_NAME "memtouch"
-#define PROGRAM_DESCRIPTION "Update the expiration value of an already existing value in the server"
-
-
-/* Prototypes */
-void options_parse(int argc, char *argv[]);
-
-static int opt_binary= 0;
-static int opt_verbose= 0;
-static char *opt_servers= NULL;
-static char *opt_hash= NULL;
-static char *opt_username;
-static char *opt_passwd;
-
-time_t expiration= 0;
-
-int main(int argc, char *argv[])
-{
-  int return_code= EXIT_SUCCESS;
-
-  options_parse(argc, argv);
-  initialize_sockets();
-
-  if (opt_servers == NULL)
-  {
-    char *temp;
-
-    if ((temp= getenv("MEMCACHED_SERVERS")))
-    {
-      opt_servers= strdup(temp);
-    }
-
-    if (opt_servers == NULL)
-    {
-      std::cerr << "No Servers provided" << std::endl;
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  memcached_server_st* servers= memcached_servers_parse(opt_servers);
-  if (servers == NULL or memcached_server_list_count(servers) == 0)
-  {
-    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  memcached_st *memc= memcached_create(NULL);
-  process_hash_option(memc, opt_hash);
-
-  memcached_server_push(memc, servers);
-  memcached_server_list_free(servers);
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
-                         (uint64_t)opt_binary);
-
-  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    memcached_free(memc);
-    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
-    return EXIT_FAILURE;
-  }
-
-  if (opt_username)
-  {
-    memcached_return_t ret;
-    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
-    {
-      std::cerr << memcached_last_error_message(memc) << std::endl;
-      memcached_free(memc);
-      return EXIT_FAILURE;
-    }
-  }
-
-  while (optind < argc)
-  {
-    memcached_return_t rc= memcached_touch(memc, argv[optind], strlen(argv[optind]), expiration);
-    if (rc == MEMCACHED_NOTFOUND)
-    {
-      if (opt_verbose)
-      {
-        std::cout << "Could not find key \"" << argv[optind] << "\"" << std::endl;
-      }
-
-      return_code= EXIT_FAILURE;
-    }
-    else if (memcached_failed(rc))
-    {
-      if (opt_verbose)
-      {
-        std::cerr << "Fatal error for key \"" << argv[optind] << "\" :" <<  memcached_last_error_message(memc) << std::endl;
-      }
-
-      return_code= EXIT_FAILURE;
-    }
-    else // success
-    {
-      if (opt_verbose)
-      {
-        std::cout << "Found key " << argv[optind] << std::endl;
-      }
-    }
-
-    optind++;
-  }
-
-  memcached_free(memc);
-
-  if (opt_servers)
-  {
-    free(opt_servers);
-  }
-
-  if (opt_hash)
-  {
-    free(opt_hash);
-  }
-
-  return return_code;
-}
-
-
-void options_parse(int argc, char *argv[])
-{
-  memcached_programs_help_st help_options[]=
-  {
-    {0},
-  };
-
-  static struct option long_options[]=
-    {
-      {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
-      {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
-      {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
-      {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
-      {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
-      {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
-      {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
-      {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
-      {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
-      {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
-      {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
-      {0, 0, 0, 0},
-    };
-
-  bool opt_version= false;
-  bool opt_help= false;
-  int option_index= 0;
-
-  while (1)
-  {
-    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
-    if (option_rv == -1) 
-    {
-      break;
-    }
-
-    switch (option_rv)
-    {
-    case 0:
-      break;
-
-    case OPT_BINARY:
-      opt_binary = true;
-      break;
-
-    case OPT_VERBOSE: /* --verbose or -v */
-      opt_verbose = OPT_VERBOSE;
-      break;
-
-    case OPT_DEBUG: /* --debug or -d */
-      opt_verbose = OPT_DEBUG;
-      break;
-
-    case OPT_VERSION: /* --version or -V */
-      opt_version= true;
-      break;
-
-    case OPT_HELP: /* --help or -h */
-      opt_help= true;
-      break;
-
-    case OPT_SERVERS: /* --servers or -s */
-      opt_servers= strdup(optarg);
-      break;
-
-    case OPT_HASH:
-      opt_hash= strdup(optarg);
-      break;
-
-    case OPT_USERNAME:
-      opt_username= optarg;
-      break;
-
-    case OPT_PASSWD:
-      opt_passwd= optarg;
-      break;
-
-    case OPT_EXPIRE:
-      errno= 0;
-      expiration= time_t(strtoul(optarg, (char **)NULL, 10));
-      if (errno != 0)
-      {
-        fprintf(stderr, "Invalid value for --expire: %s\n", optarg);
-        exit(EXIT_FAILURE);
-      }
-      break;
-
-    case OPT_QUIET:
-      close_stdio();
-      break;
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(EXIT_FAILURE);
-
-    default:
-      abort();
-    }
-  }
-
-  if (opt_version)
-  {
-    version_command(PROGRAM_NAME);
-    exit(EXIT_SUCCESS);
-  }
-
-  if (opt_help)
-  {
-    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
-    exit(EXIT_SUCCESS);
-  }
-}
diff --git a/clients/memtouch.sh b/clients/memtouch.sh
deleted file mode 100755 (executable)
index 36531d5..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-clients/memcp.sh
-clients/memtouch -v --servers localhost mem.testdata
diff --git a/clients/ms_atomic.h b/clients/ms_atomic.h
deleted file mode 100644 (file)
index 6ec990c..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-#ifndef CLIENTS_MS_ATOMIC_H
-#define CLIENTS_MS_ATOMIC_H
-
-#if HAVE_C_STDATOMIC
-# define ATOMIC _Atomic
-#else
-# define ATOMIC volatile
-#endif
-
-#if defined(__SUNPRO_C)
-# define _KERNEL
-# include <atomic.h>
-# if SIZEOF_SIZE_T == 8
-#  define  atomic_add_size(X, Y) atomic_add_64((X), (Y))
-#  define  atomic_add_size_nv(X, Y) atomic_add_64((X), (Y))
-#  define  atomic_dec_size(X, Y) atomic_add_64((X), (Y))
-#  define  atomic_dec_size_nv(X, Y) atomic_add_64((X), (Y))
-# else
-#  define  atomic_add_size(X, Y) atomic_add_32((X), (Y))
-#  define  atomic_add_size_nv(X, Y) atomic_add_32((X), (Y))
-#  define  atomic_dec_size(X, Y) atomic_add_32((X), (Y))
-#  define  atomic_dec_size_nv(X, Y) atomic_add_32((X), (Y))
-# endif
-# undef _KERNEL
-#elif HAVE_GCC_ATOMIC_BUILTINS
-# define atomic_add_8(X, Y)  __sync_fetch_and_add((X), (Y))
-# define atomic_add_16(X, Y) __sync_fetch_and_add((X), (Y))
-# define atomic_add_32(X, Y) __sync_fetch_and_add((X), (Y))
-# define atomic_add_size(X, Y) __sync_fetch_and_add((X), (Y))
-# define atomic_dec_8(X)  __sync_fetch_and_sub((X), 1)
-# define atomic_dec_16(X) __sync_fetch_and_sub((X), 1)
-# define atomic_dec_32(X) __sync_fetch_and_sub((X), 1)
-# define atomic_dec_size(X) __sync_fetch_and_sub((X), 1)
-/* The same as above, but these return the new value instead of void */
-# define atomic_add_8_nv(X, Y)  __sync_fetch_and_add((X), (Y))
-# define atomic_add_16_nv(X, Y) __sync_fetch_and_add((X), (Y))
-# define atomic_add_32_nv(X, Y) __sync_fetch_and_add((X), (Y))
-# define atomic_add_size_nv(X, Y) __sync_fetch_and_add((X), (Y))
-# define atomic_dec_8_nv(X)  __sync_fetch_and_sub((X), 1)
-# define atomic_dec_16_nv(X) __sync_fetch_and_sub((X), 1)
-# define atomic_dec_32_nv(X) __sync_fetch_and_sub((X), 1)
-# define atomic_dec_size_nv(X) __sync_fetch_and_sub((X), 1)
-#elif HAVE_C_STDATOMIC
-# include <stdatomic.h>
-# define atomic_add_8(X, Y) atomic_fetch_add(X, Y)
-# define atomic_add_16(X, Y) atomic_fetch_add(X, Y)
-# define atomic_add_32(X, Y) atomic_fetch_add(X, Y)
-# define atomic_add_size(X, Y) atomic_fetch_add(X, Y)
-# define atomic_dec_8(X) atomic_fetch_sub(X, 1)
-# define atomic_dec_16(X) atomic_fetch_sub(X, 1)
-# define atomic_dec_32(X) atomic_fetch_sub(X, 1)
-# define atomic_dec_size(X) atomic_fetch_sub(X, 1)
-/* The same as above, but these return the new value instead of void */
-# define ATOMIC_ADD_FETCH_DECL(T) \
-static inline T atomic_add_fetch_##T(ATOMIC T *ptr, T add) { \
-       T des, cur = atomic_load(ptr); \
-       do { \
-               des = cur + add; \
-       } while(!atomic_compare_exchange_weak(ptr, &cur, des)); \
-       return des; \
-}
-# define ATOMIC_SUB_FETCH_DECL(T) \
-T atomic_sub_fetch_##T(ATOMIC T *ptr) { \
-       T des, cur = atomic_load(ptr); \
-       do { \
-               des = cur - 1; \
-       } while(!atomic_compare_exchange_weak(ptr, &cur, des)); \
-       return des; \
-}
-ATOMIC_ADD_FETCH_DECL(uint8_t)
-# define atomic_add_8_nv(X, Y) atomic_add_fetch_uint8_t(X, Y)
-ATOMIC_ADD_FETCH_DECL(uint16_t)
-# define atomic_add_16_nv(X, Y) atomic_add_fetch_uint16_t(X, Y)
-ATOMIC_ADD_FETCH_DECL(uint32_t)
-# define atomic_add_32_nv(X, Y) atomic_add_fetch_uint32_t(X, Y)
-ATOMIC_ADD_FETCH_DECL(size_t)
-# define atomic_add_size_nv(X, Y) atomic_add_fetch_size_t(X, Y)
-# define atomic_dec_8_nv(X) atomic_sub_fetch<uint8_t>(X, Y)
-# define atomic_dec_16_nv(X) atomic_sub_fetch<uint16_t>(X, Y)
-# define atomic_dec_32_nv(X) atomic_sub_fetch<uint32_t>(X, Y)
-# define atomic_dec_size_nv(X) atomic_sub_fetch<size_t>(X, Y)
-#else
-#warning "Atomic operators not found so memslap will not work correctly"
-# define atomic_add_8(X, Y) 0
-# define atomic_add_16(X, Y) 0
-# define atomic_add_32(X, Y) 0
-# define atomic_add_size(X, Y) 0
-# define atomic_dec_8(X) 0
-# define atomic_dec_16(X) 0
-# define atomic_dec_32(X) 0
-# define atomic_dec_size(X) 0
-/* The same as above, but these return the new value instead of void */
-# define atomic_add_8_nv(X, Y) 0
-# define atomic_add_16_nv(X, Y) 0
-# define atomic_add_32_nv(X, Y) 0
-# define atomic_add_size_nv(X, Y) 0
-# define atomic_dec_8_nv(X) 0
-# define atomic_dec_16_nv(X) 0
-# define atomic_dec_32_nv(X) 0
-# define atomic_dec_size_nv(X) 0
-#endif /* defined(__SUNPRO_C) */
-
-#endif /* CLIENTS_MS_ATOMIC_H */
diff --git a/clients/ms_conn.c b/clients/ms_conn.c
deleted file mode 100644 (file)
index 71353d5..0000000
+++ /dev/null
@@ -1,3427 +0,0 @@
-/*
- * File:   ms_conn.c
- * Author: Mingqiang Zhuang
- *
- * Created on February 10, 2009
- *
- * (c) Copyright 2009, Schooner Information Technology, Inc.
- * http://www.schoonerinfotech.com/
- *
- */
-
-#include "mem_config.h"
-
-#include <stdio.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <sys/uio.h>
-#include <event.h>
-#include <fcntl.h>
-#include <netinet/tcp.h>
-#include <netinet/in.h>
-
-#if defined(HAVE_ARPA_INET_H)
-# include <arpa/inet.h>
-#endif
-
-#if defined(HAVE_SYS_TIME_H)
-# include <sys/time.h>
-#endif
-
-#if defined(HAVE_TIME_H)
-# include <time.h>
-#endif
-
-#include "ms_setting.h"
-#include "ms_thread.h"
-#include "ms_atomic.h"
-
-#ifdef linux
-/* /usr/include/netinet/in.h defines macros from ntohs() to _bswap_nn to
- * optimize the conversion functions, but the prototypes generate warnings
- * from gcc. The conversion methods isn't the bottleneck for my app, so
- * just remove the warnings by undef'ing the optimization ..
- */
-#undef ntohs
-#undef ntohl
-#undef htons
-#undef htonl
-#endif
-
-/* for network write */
-#define TRANSMIT_COMPLETE      0
-#define TRANSMIT_INCOMPLETE    1
-#define TRANSMIT_SOFT_ERROR    2
-#define TRANSMIT_HARD_ERROR    3
-
-/* for generating key */
-#define KEY_PREFIX_BASE        0x1010101010101010 /* not include ' ' '\r' '\n' '\0' */
-#define KEY_PREFIX_MASK        0x1010101010101010
-
-/* For parse the value length return by server */
-#define KEY_TOKEN              1
-#define VALUELEN_TOKEN         3
-
-/* global increasing counter, to ensure the key prefix unique */
-static uint64_t key_prefix_seq= KEY_PREFIX_BASE;
-
-/* global increasing counter, generating request id for UDP */
-static ATOMIC uint32_t udp_request_id= 0;
-
-extern pthread_key_t ms_thread_key;
-
-/* generate upd request id */
-static uint32_t ms_get_udp_request_id(void);
-
-
-/* connect initialize */
-static void ms_task_init(ms_conn_t *c);
-static int ms_conn_udp_init(ms_conn_t *c, const bool is_udp);
-static int ms_conn_sock_init(ms_conn_t *c);
-static int ms_conn_event_init(ms_conn_t *c);
-static int ms_conn_init(ms_conn_t *c,
-                        const int init_state,
-                        const int read_buffer_size,
-                        const bool is_udp);
-static void ms_warmup_num_init(ms_conn_t *c);
-static int ms_item_win_init(ms_conn_t *c);
-
-
-/* connection close */
-void ms_conn_free(ms_conn_t *c);
-static void ms_conn_close(ms_conn_t *c);
-
-
-/* create network connection */
-static int ms_new_socket(struct addrinfo *ai);
-static void ms_maximize_sndbuf(const int sfd);
-static int ms_network_connect(ms_conn_t *c,
-                              char *srv_host_name,
-                              const int srv_port,
-                              const bool is_udp,
-                              int *ret_sfd);
-static int ms_reconn(ms_conn_t *c);
-
-
-/* read and parse */
-static int ms_tokenize_command(char *command,
-                               token_t *tokens,
-                               const int max_tokens);
-static int ms_ascii_process_line(ms_conn_t *c, char *command);
-static int ms_try_read_line(ms_conn_t *c);
-static int ms_sort_udp_packet(ms_conn_t *c, char *buf, int rbytes);
-static int ms_udp_read(ms_conn_t *c, char *buf, int len);
-static int ms_try_read_network(ms_conn_t *c);
-static void ms_verify_value(ms_conn_t *c,
-                            ms_mlget_task_item_t *mlget_item,
-                            char *value,
-                            int vlen);
-static void ms_ascii_complete_nread(ms_conn_t *c);
-static void ms_bin_complete_nread(ms_conn_t *c);
-static void ms_complete_nread(ms_conn_t *c);
-
-
-/* send functions */
-static int ms_add_msghdr(ms_conn_t *c);
-static int ms_ensure_iov_space(ms_conn_t *c);
-static int ms_add_iov(ms_conn_t *c, const void *buf, int len);
-static int ms_build_udp_headers(ms_conn_t *c);
-static int ms_transmit(ms_conn_t *c);
-
-
-/* status adjustment */
-static void ms_conn_shrink(ms_conn_t *c);
-static void ms_conn_set_state(ms_conn_t *c, int state);
-static bool ms_update_event(ms_conn_t *c, const int new_flags);
-static uint32_t ms_get_rep_sock_index(ms_conn_t *c, int cmd);
-static uint32_t ms_get_next_sock_index(ms_conn_t *c);
-static int ms_update_conn_sock_event(ms_conn_t *c);
-static bool ms_need_yield(ms_conn_t *c);
-static void ms_update_start_time(ms_conn_t *c);
-
-
-/* main loop */
-static void ms_drive_machine(ms_conn_t *c);
-void ms_event_handler(const int fd, const short which, void *arg);
-
-
-/* ascii protocol */
-static int ms_build_ascii_write_buf_set(ms_conn_t *c, ms_task_item_t *item);
-static int ms_build_ascii_write_buf_get(ms_conn_t *c, ms_task_item_t *item);
-static int ms_build_ascii_write_buf_mlget(ms_conn_t *c);
-
-
-/* binary protocol */
-static int ms_bin_process_response(ms_conn_t *c);
-static void ms_add_bin_header(ms_conn_t *c,
-                              uint8_t opcode,
-                              uint8_t hdr_len,
-                              uint16_t key_len,
-                              uint32_t body_len);
-static void ms_add_key_to_iov(ms_conn_t *c, ms_task_item_t *item);
-static int ms_build_bin_write_buf_set(ms_conn_t *c, ms_task_item_t *item);
-static int ms_build_bin_write_buf_get(ms_conn_t *c, ms_task_item_t *item);
-static int ms_build_bin_write_buf_mlget(ms_conn_t *c);
-
-
-/**
- * each key has two parts, prefix and suffix. The suffix is a
- * string random get form the character table. The prefix is a
- * uint64_t variable. And the prefix must be unique. we use the
- * prefix to identify a key. And the prefix can't include
- * character ' ' '\r' '\n' '\0'.
- *
- * @return uint64_t
- */
-uint64_t ms_get_key_prefix(void)
-{
-  uint64_t key_prefix;
-
-  pthread_mutex_lock(&ms_global.seq_mutex);
-  key_prefix_seq|= KEY_PREFIX_MASK;
-  key_prefix= key_prefix_seq;
-  key_prefix_seq++;
-  pthread_mutex_unlock(&ms_global.seq_mutex);
-
-  return key_prefix;
-} /* ms_get_key_prefix */
-
-
-/**
- * get an unique udp request id
- *
- * @return an unique UDP request id
- */
-static uint32_t ms_get_udp_request_id(void)
-{
-  return atomic_add_32_nv(&udp_request_id, 1);
-}
-
-
-/**
- * initialize current task structure
- *
- * @param c, pointer of the concurrency
- */
-static void ms_task_init(ms_conn_t *c)
-{
-  c->curr_task.cmd= CMD_NULL;
-  c->curr_task.item= 0;
-  c->curr_task.verify= false;
-  c->curr_task.finish_verify= true;
-  c->curr_task.get_miss= true;
-
-  c->curr_task.get_opt= 0;
-  c->curr_task.set_opt= 0;
-  c->curr_task.cycle_undo_get= 0;
-  c->curr_task.cycle_undo_set= 0;
-  c->curr_task.verified_get= 0;
-  c->curr_task.overwrite_set= 0;
-} /* ms_task_init */
-
-
-/**
- * initialize udp for the connection structure
- *
- * @param c, pointer of the concurrency
- * @param is_udp, whether it's udp
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_conn_udp_init(ms_conn_t *c, const bool is_udp)
-{
-  c->hdrbuf= 0;
-  c->rudpbuf= 0;
-  c->udppkt= 0;
-
-  c->rudpsize= UDP_DATA_BUFFER_SIZE;
-  c->hdrsize= 0;
-
-  c->rudpbytes= 0;
-  c->packets= 0;
-  c->recvpkt= 0;
-  c->pktcurr= 0;
-  c->ordcurr= 0;
-
-  c->udp= is_udp;
-
-  if (c->udp || (! c->udp && ms_setting.facebook_test))
-  {
-    c->rudpbuf= (char *)malloc((size_t)c->rudpsize);
-    c->udppkt= (ms_udppkt_t *)malloc(MAX_UDP_PACKET * sizeof(ms_udppkt_t));
-
-    if ((c->rudpbuf == NULL) || (c->udppkt == NULL))
-    {
-      if (c->rudpbuf != NULL)
-        free(c->rudpbuf);
-      if (c->udppkt != NULL)
-        free(c->udppkt);
-      fprintf(stderr, "malloc()\n");
-      return -1;
-    }
-    memset(c->udppkt, 0, MAX_UDP_PACKET * sizeof(ms_udppkt_t));
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_conn_udp_init */
-
-
-/**
- * initialize the connection structure
- *
- * @param c, pointer of the concurrency
- * @param init_state, (conn_read, conn_write, conn_closing)
- * @param read_buffer_size
- * @param is_udp, whether it's udp
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_conn_init(ms_conn_t *c,
-                        const int init_state,
-                        const int read_buffer_size,
-                        const bool is_udp)
-{
-  assert(c != NULL);
-
-  c->rbuf= c->wbuf= 0;
-  c->iov= 0;
-  c->msglist= 0;
-
-  c->rsize= read_buffer_size;
-  c->wsize= WRITE_BUFFER_SIZE;
-  c->iovsize= IOV_LIST_INITIAL;
-  c->msgsize= MSG_LIST_INITIAL;
-
-  /* for replication, each connection need connect all the server */
-  if (ms_setting.rep_write_srv > 0)
-  {
-    c->total_sfds= ms_setting.srv_cnt * ms_setting.sock_per_conn;
-  }
-  else
-  {
-    c->total_sfds= ms_setting.sock_per_conn;
-  }
-  c->alive_sfds= 0;
-
-  c->rbuf= (char *)malloc((size_t)c->rsize);
-  c->wbuf= (char *)malloc((size_t)c->wsize);
-  c->iov= (struct iovec *)malloc(sizeof(struct iovec) * (size_t)c->iovsize);
-  c->msglist= (struct msghdr *)malloc(
-    sizeof(struct msghdr) * (size_t)c->msgsize);
-  if (ms_setting.mult_key_num > 1)
-  {
-    c->mlget_task.mlget_item= (ms_mlget_task_item_t *)
-                              malloc(
-      sizeof(ms_mlget_task_item_t) * (size_t)ms_setting.mult_key_num);
-  }
-  c->tcpsfd= (int *)malloc((size_t)c->total_sfds * sizeof(int));
-
-  if ((c->rbuf == NULL) || (c->wbuf == NULL) || (c->iov == NULL)
-      || (c->msglist == NULL) || (c->tcpsfd == NULL)
-      || ((ms_setting.mult_key_num > 1)
-          && (c->mlget_task.mlget_item == NULL)))
-  {
-    if (c->rbuf != NULL)
-      free(c->rbuf);
-    if (c->wbuf != NULL)
-      free(c->wbuf);
-    if (c->iov != NULL)
-      free(c->iov);
-    if (c->msglist != NULL)
-      free(c->msglist);
-    if (c->mlget_task.mlget_item != NULL)
-      free(c->mlget_task.mlget_item);
-    if (c->tcpsfd != NULL)
-      free(c->tcpsfd);
-    fprintf(stderr, "malloc()\n");
-    return -1;
-  }
-
-  c->state= init_state;
-  c->rvbytes= 0;
-  c->rbytes= 0;
-  c->rcurr= c->rbuf;
-  c->wcurr= c->wbuf;
-  c->iovused= 0;
-  c->msgcurr= 0;
-  c->msgused= 0;
-  c->cur_idx= c->total_sfds;       /* default index is a invalid value */
-
-  c->ctnwrite= false;
-  c->readval= false;
-  c->change_sfd= false;
-
-  c->precmd.cmd= c->currcmd.cmd= CMD_NULL;
-  c->precmd.isfinish= true;         /* default the previous command finished */
-  c->currcmd.isfinish= false;
-  c->precmd.retstat= c->currcmd.retstat= MCD_FAILURE;
-  c->precmd.key_prefix= c->currcmd.key_prefix= 0;
-
-  c->mlget_task.mlget_num= 0;
-  c->mlget_task.value_index= -1;         /* default invalid value */
-
-  if (ms_setting.binary_prot_)
-  {
-    c->protocol= binary_prot;
-  }
-  else
-  {
-    c->protocol= ascii_prot;
-  }
-
-  /* initialize udp */
-  if (ms_conn_udp_init(c, is_udp) != 0)
-  {
-    return -1;
-  }
-
-  /* initialize task */
-  ms_task_init(c);
-
-  if (! (ms_setting.facebook_test && is_udp))
-  {
-    atomic_add_32(&ms_stats.active_conns, 1);
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_conn_init */
-
-
-/**
- * when doing 100% get operation, it could preset some objects
- * to warmup the server. this function is used to initialize the
- * number of the objects to preset.
- *
- * @param c, pointer of the concurrency
- */
-static void ms_warmup_num_init(ms_conn_t *c)
-{
-  /* no set operation, preset all the items in the window  */
-  if (ms_setting.cmd_distr[CMD_SET].cmd_prop < PROP_ERROR)
-  {
-    c->warmup_num= c->win_size;
-    c->remain_warmup_num= c->warmup_num;
-  }
-  else
-  {
-    c->warmup_num= 0;
-    c->remain_warmup_num= c->warmup_num;
-  }
-} /* ms_warmup_num_init */
-
-
-/**
- * each connection has an item window, this function initialize
- * the window. The window is used to generate task.
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_item_win_init(ms_conn_t *c)
-{
-  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
-  int exp_cnt= 0;
-
-  c->win_size= (int)ms_setting.win_size;
-  c->set_cursor= 0;
-  c->exec_num= ms_thread->thread_ctx->exec_num_perconn;
-  c->remain_exec_num= c->exec_num;
-
-  c->item_win= (ms_task_item_t *)malloc(
-    sizeof(ms_task_item_t) * (size_t)c->win_size);
-  if (c->item_win == NULL)
-  {
-    fprintf(stderr, "Can't allocate task item array for conn.\n");
-    return -1;
-  }
-  memset(c->item_win, 0, sizeof(ms_task_item_t) * (size_t)c->win_size);
-
-  for (int i= 0; i < c->win_size; i++)
-  {
-    c->item_win[i].key_size= (int)ms_setting.distr[i].key_size;
-    c->item_win[i].key_prefix= ms_get_key_prefix();
-    c->item_win[i].key_suffix_offset= ms_setting.distr[i].key_offset;
-    c->item_win[i].value_size= (int)ms_setting.distr[i].value_size;
-    c->item_win[i].value_offset= INVALID_OFFSET;         /* default in invalid offset */
-    c->item_win[i].client_time= 0;
-
-    /* set expire time base on the proportion */
-    if (exp_cnt < ms_setting.exp_ver_per * i)
-    {
-      c->item_win[i].exp_time= FIXED_EXPIRE_TIME;
-      exp_cnt++;
-    }
-    else
-    {
-      c->item_win[i].exp_time= 0;
-    }
-  }
-
-  ms_warmup_num_init(c);
-
-  return EXIT_SUCCESS;
-} /* ms_item_win_init */
-
-
-/**
- * each connection structure can include one or more sock
- * handlers. this function create these socks and connect the
- * server(s).
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_conn_sock_init(ms_conn_t *c)
-{
-  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
-  uint32_t i;
-  int ret_sfd;
-  uint32_t srv_idx= 0;
-
-  assert(c != NULL);
-  assert(c->tcpsfd != NULL);
-
-  for (i= 0; i < c->total_sfds; i++)
-  {
-    ret_sfd= 0;
-    if (ms_setting.rep_write_srv > 0)
-    {
-      /* for replication, each connection need connect all the server */
-      srv_idx= i % ms_setting.srv_cnt;
-    }
-    else
-    {
-      /* all the connections in a thread connects the same server */
-      srv_idx= ms_thread->thread_ctx->srv_idx;
-    }
-
-    if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name,
-                           ms_setting.servers[srv_idx].srv_port,
-                           ms_setting.udp, &ret_sfd) != 0)
-    {
-      break;
-    }
-
-    if (i == 0)
-    {
-      c->sfd= ret_sfd;
-    }
-
-    if (! ms_setting.udp)
-    {
-      c->tcpsfd[i]= ret_sfd;
-    }
-
-    c->alive_sfds++;
-  }
-
-  /* initialize udp sock handler if necessary */
-  if (ms_setting.facebook_test)
-  {
-    ret_sfd= 0;
-    if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name,
-                           ms_setting.servers[srv_idx].srv_port,
-                           true, &ret_sfd) != 0)
-    {
-      c->udpsfd= 0;
-    }
-    else
-    {
-      c->udpsfd= ret_sfd;
-    }
-  }
-
-  if ((i != c->total_sfds) || (ms_setting.facebook_test && (c->udpsfd == 0)))
-  {
-    if (ms_setting.udp)
-    {
-      close(c->sfd);
-    }
-    else
-    {
-      for (uint32_t j= 0; j < i; j++)
-      {
-        close(c->tcpsfd[j]);
-      }
-    }
-
-    if (c->udpsfd != 0)
-    {
-      close(c->udpsfd);
-    }
-
-    return -1;
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_conn_sock_init */
-
-
-/**
- * each connection is managed by libevent, this function
- * initialize the event of the connection structure.
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_conn_event_init(ms_conn_t *c)
-{
-  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
-  short event_flags= EV_WRITE | EV_PERSIST;
-
-  event_set(&c->event, c->sfd, event_flags, ms_event_handler, (void *)c);
-  event_base_set(ms_thread->base, &c->event);
-  c->ev_flags= event_flags;
-
-  if (event_add(&c->event, NULL) == -1)
-  {
-    return -1;
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_conn_event_init */
-
-
-/**
- * setup a connection, each connection structure of each
- * thread must call this function to initialize.
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-int ms_setup_conn(ms_conn_t *c)
-{
-  if (ms_item_win_init(c) != 0)
-  {
-    return -1;
-  }
-
-  if (ms_conn_init(c, conn_write, DATA_BUFFER_SIZE, ms_setting.udp) != 0)
-  {
-    return -1;
-  }
-
-  if (ms_conn_sock_init(c) != 0)
-  {
-    return -1;
-  }
-
-  if (ms_conn_event_init(c) != 0)
-  {
-    return -1;
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_setup_conn */
-
-
-/**
- * Frees a connection.
- *
- * @param c, pointer of the concurrency
- */
-void ms_conn_free(ms_conn_t *c)
-{
-  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
-  if (c != NULL)
-  {
-    if (c->hdrbuf != NULL)
-      free(c->hdrbuf);
-    if (c->msglist != NULL)
-      free(c->msglist);
-    if (c->rbuf != NULL)
-      free(c->rbuf);
-    if (c->wbuf != NULL)
-      free(c->wbuf);
-    if (c->iov != NULL)
-      free(c->iov);
-    if (c->mlget_task.mlget_item != NULL)
-      free(c->mlget_task.mlget_item);
-    if (c->rudpbuf != NULL)
-      free(c->rudpbuf);
-    if (c->udppkt != NULL)
-      free(c->udppkt);
-    if (c->item_win != NULL)
-      free(c->item_win);
-    if (c->tcpsfd != NULL)
-      free(c->tcpsfd);
-
-    if (--ms_thread->nactive_conn == 0)
-    {
-      free(ms_thread->conn);
-    }
-  }
-} /* ms_conn_free */
-
-
-/**
- * close a connection
- *
- * @param c, pointer of the concurrency
- */
-static void ms_conn_close(ms_conn_t *c)
-{
-  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
-  assert(c != NULL);
-
-  /* delete the event, the socket and the connection */
-  event_del(&c->event);
-
-  for (uint32_t i= 0; i < c->total_sfds; i++)
-  {
-    if (c->tcpsfd[i] > 0)
-    {
-      close(c->tcpsfd[i]);
-    }
-  }
-  c->sfd= 0;
-
-  if (ms_setting.facebook_test)
-  {
-    close(c->udpsfd);
-  }
-
-  atomic_dec_32(&ms_stats.active_conns);
-
-  ms_conn_free(c);
-
-  if (ms_setting.run_time == 0)
-  {
-    pthread_mutex_lock(&ms_global.run_lock.lock);
-    ms_global.run_lock.count++;
-    pthread_cond_signal(&ms_global.run_lock.cond);
-    pthread_mutex_unlock(&ms_global.run_lock.lock);
-  }
-
-  if (ms_thread->nactive_conn == 0)
-  {
-    pthread_exit(NULL);
-  }
-} /* ms_conn_close */
-
-
-/**
- * create a new sock
- *
- * @param ai, server address information
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_new_socket(struct addrinfo *ai)
-{
-  int sfd;
-
-  if ((sfd= socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == -1)
-  {
-    fprintf(stderr, "socket() error: %s.\n", strerror(errno));
-    return -1;
-  }
-
-  return sfd;
-} /* ms_new_socket */
-
-
-/**
- * Sets a socket's send buffer size to the maximum allowed by the system.
- *
- * @param sfd, file descriptor of socket
- */
-static void ms_maximize_sndbuf(const int sfd)
-{
-  socklen_t intsize= sizeof(int);
-  unsigned int last_good= 0;
-  unsigned int min, max, avg;
-  unsigned int old_size;
-
-  /* Start with the default size. */
-  if (getsockopt(sfd, SOL_SOCKET, SO_SNDBUF, &old_size, &intsize) != 0)
-  {
-    fprintf(stderr, "getsockopt(SO_SNDBUF)\n");
-    return;
-  }
-
-  /* Binary-search for the real maximum. */
-  min= old_size;
-  max= MAX_SENDBUF_SIZE;
-
-  while (min <= max)
-  {
-    avg= ((unsigned int)(min + max)) / 2;
-    if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, (void *)&avg, intsize) == 0)
-    {
-      last_good= avg;
-      min= avg + 1;
-    }
-    else
-    {
-      max= avg - 1;
-    }
-  }
-  (void)last_good;
-} /* ms_maximize_sndbuf */
-
-
-/**
- * socket connects the server
- *
- * @param c, pointer of the concurrency
- * @param srv_host_name, the host name of the server
- * @param srv_port, port of server
- * @param is_udp, whether it's udp
- * @param ret_sfd, the connected socket file descriptor
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_network_connect(ms_conn_t *c,
-                              char *srv_host_name,
-                              const int srv_port,
-                              const bool is_udp,
-                              int *ret_sfd)
-{
-  int sfd;
-  struct linger ling=
-  {
-    0, 0
-  };
-  struct addrinfo *ai;
-  struct addrinfo *next;
-  struct addrinfo hints;
-  char port_buf[NI_MAXSERV];
-  int  error;
-  int  success= 0;
-
-  int flags= 1;
-
-  /*
-   * the memset call clears nonstandard fields in some impementations
-   * that otherwise mess things up.
-   */
-  memset(&hints, 0, sizeof(hints));
-#ifdef AI_ADDRCONFIG
-  hints.ai_flags= AI_PASSIVE | AI_ADDRCONFIG;
-#else
-  hints.ai_flags= AI_PASSIVE;
-#endif /* AI_ADDRCONFIG */
-  if (is_udp)
-  {
-    hints.ai_protocol= IPPROTO_UDP;
-    hints.ai_socktype= SOCK_DGRAM;
-    hints.ai_family= AF_INET;      /* This left here because of issues with OSX 10.5 */
-  }
-  else
-  {
-    hints.ai_family= AF_UNSPEC;
-    hints.ai_protocol= IPPROTO_TCP;
-    hints.ai_socktype= SOCK_STREAM;
-  }
-
-  snprintf(port_buf, NI_MAXSERV, "%d", srv_port);
-  error= getaddrinfo(srv_host_name, port_buf, &hints, &ai);
-  if (error != 0)
-  {
-    if (error != EAI_SYSTEM)
-      fprintf(stderr, "getaddrinfo(): %s.\n", gai_strerror(error));
-    else
-      perror("getaddrinfo()\n");
-
-    return -1;
-  }
-
-  for (next= ai; next; next= next->ai_next)
-  {
-    if ((sfd= ms_new_socket(next)) == -1)
-    {
-      freeaddrinfo(ai);
-      return -1;
-    }
-
-    setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
-    if (is_udp)
-    {
-      ms_maximize_sndbuf(sfd);
-    }
-    else
-    {
-      setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags,
-                 sizeof(flags));
-      setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
-      setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags,
-                 sizeof(flags));
-    }
-
-    if (is_udp)
-    {
-      c->srv_recv_addr_size= sizeof(struct sockaddr);
-      memcpy(&c->srv_recv_addr, next->ai_addr, c->srv_recv_addr_size);
-    }
-    else
-    {
-      if (connect(sfd, next->ai_addr, next->ai_addrlen) == -1)
-      {
-        close(sfd);
-        freeaddrinfo(ai);
-        return -1;
-      }
-    }
-
-    if (((flags= fcntl(sfd, F_GETFL, 0)) < 0)
-        || (fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0))
-    {
-      fprintf(stderr, "setting O_NONBLOCK\n");
-      close(sfd);
-      freeaddrinfo(ai);
-      return -1;
-    }
-
-    if (ret_sfd != NULL)
-    {
-      *ret_sfd= sfd;
-    }
-
-    success++;
-  }
-
-  freeaddrinfo(ai);
-
-  /* Return zero if we detected no errors in starting up connections */
-  return success == 0;
-} /* ms_network_connect */
-
-
-/**
- * reconnect a disconnected sock
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_reconn(ms_conn_t *c)
-{
-  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
-  uint32_t srv_idx= 0;
-  uint32_t srv_conn_cnt= 0;
-
-  if (ms_setting.rep_write_srv > 0)
-  {
-    srv_idx= c->cur_idx % ms_setting.srv_cnt;
-    srv_conn_cnt= ms_setting.sock_per_conn  * ms_setting.nconns;
-  }
-  else
-  {
-    srv_idx= ms_thread->thread_ctx->srv_idx;
-    srv_conn_cnt= ms_setting.nconns / ms_setting.srv_cnt;
-  }
-
-  /* close the old socket handler */
-  close(c->sfd);
-  c->tcpsfd[c->cur_idx]= 0;
-
-  if (atomic_add_32_nv(&ms_setting.servers[srv_idx].disconn_cnt, 1)
-      % srv_conn_cnt == 0)
-  {
-    gettimeofday(&ms_setting.servers[srv_idx].disconn_time, NULL);
-    fprintf(stderr, "Server %s:%d disconnect\n",
-            ms_setting.servers[srv_idx].srv_host_name,
-            ms_setting.servers[srv_idx].srv_port);
-  }
-
-  if (ms_setting.rep_write_srv > 0)
-  {
-    uint32_t i= 0;
-
-    for (i= 0; i < c->total_sfds; i++)
-    {
-      if (c->tcpsfd[i] != 0)
-      {
-        break;
-      }
-    }
-
-    /* all socks disconnect */
-    if (i == c->total_sfds)
-    {
-      return -1;
-    }
-  }
-  else
-  {
-    do
-    {
-      /* reconnect success, break the loop */
-      if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name,
-                             ms_setting.servers[srv_idx].srv_port,
-                             ms_setting.udp, &c->sfd) == 0)
-      {
-        c->tcpsfd[c->cur_idx]= c->sfd;
-        if (atomic_add_32_nv(&ms_setting.servers[srv_idx].reconn_cnt, 1)
-            % (uint32_t)srv_conn_cnt == 0)
-        {
-          gettimeofday(&ms_setting.servers[srv_idx].reconn_time, NULL);
-          int reconn_time=
-            (int)(ms_setting.servers[srv_idx].reconn_time.tv_sec
-                  - ms_setting.servers[srv_idx].disconn_time
-                     .tv_sec);
-          fprintf(stderr, "Server %s:%d reconnect after %ds\n",
-                  ms_setting.servers[srv_idx].srv_host_name,
-                  ms_setting.servers[srv_idx].srv_port, reconn_time);
-        }
-        break;
-      }
-
-      if (ms_setting.rep_write_srv == 0 && c->total_sfds > 0)
-      {
-        /* wait a second and reconnect */
-        sleep(1);
-      }
-    }
-    while (ms_setting.rep_write_srv == 0 && c->total_sfds > 0);
-  }
-
-  if ((c->total_sfds > 1) && (c->tcpsfd[c->cur_idx] == 0))
-  {
-    c->sfd= 0;
-    c->alive_sfds--;
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_reconn */
-
-
-/**
- *  reconnect several disconnected socks in the connection
- *  structure, the ever-1-second timer of the thread will check
- *  whether some socks in the connections disconnect. if
- *  disconnect, reconnect the sock.
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-int ms_reconn_socks(ms_conn_t *c)
-{
-  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
-  uint32_t srv_idx= 0;
-  int ret_sfd= 0;
-  uint32_t srv_conn_cnt= 0;
-  struct timeval cur_time;
-
-  assert(c != NULL);
-
-  if ((c->total_sfds == 1) || (c->total_sfds == c->alive_sfds))
-  {
-    return EXIT_SUCCESS;
-  }
-
-  for (uint32_t i= 0; i < c->total_sfds; i++)
-  {
-    if (c->tcpsfd[i] == 0)
-    {
-      gettimeofday(&cur_time, NULL);
-
-      /**
-       *  For failover test of replication, reconnect the socks after
-       *  it disconnects more than 5 seconds, Otherwise memslap will
-       *  block at connect() function and the work threads can't work
-       *  in this interval.
-       */
-      if (cur_time.tv_sec
-          - ms_setting.servers[srv_idx].disconn_time.tv_sec < 5)
-      {
-        break;
-      }
-
-      if (ms_setting.rep_write_srv > 0)
-      {
-        srv_idx= i % ms_setting.srv_cnt;
-        srv_conn_cnt= ms_setting.sock_per_conn * ms_setting.nconns;
-      }
-      else
-      {
-        srv_idx= ms_thread->thread_ctx->srv_idx;
-        srv_conn_cnt= ms_setting.nconns / ms_setting.srv_cnt;
-      }
-
-      if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name,
-                             ms_setting.servers[srv_idx].srv_port,
-                             ms_setting.udp, &ret_sfd) == 0)
-      {
-        c->tcpsfd[i]= ret_sfd;
-        c->alive_sfds++;
-
-        if (atomic_add_32_nv(&ms_setting.servers[srv_idx].reconn_cnt, 1)
-            % (uint32_t)srv_conn_cnt == 0)
-        {
-          gettimeofday(&ms_setting.servers[srv_idx].reconn_time, NULL);
-          int reconn_time=
-            (int)(ms_setting.servers[srv_idx].reconn_time.tv_sec
-                  - ms_setting.servers[srv_idx].disconn_time
-                     .tv_sec);
-          fprintf(stderr, "Server %s:%d reconnect after %ds\n",
-                  ms_setting.servers[srv_idx].srv_host_name,
-                  ms_setting.servers[srv_idx].srv_port, reconn_time);
-        }
-      }
-    }
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_reconn_socks */
-
-
-/**
- * Tokenize the command string by replacing whitespace with '\0' and update
- * the token array tokens with pointer to start of each token and length.
- * Returns total number of tokens.  The last valid token is the terminal
- * token (value points to the first unprocessed character of the string and
- * length zero).
- *
- * Usage example:
- *
- *  while(ms_tokenize_command(command, ncommand, tokens, max_tokens) > 0) {
- *      for(int ix = 0; tokens[ix].length != 0; ix++) {
- *          ...
- *      }
- *      ncommand = tokens[ix].value - command;
- *      command  = tokens[ix].value;
- *   }
- *
- * @param command, the command string to token
- * @param tokens, array to store tokens
- * @param max_tokens, maximum tokens number
- *
- * @return int, the number of tokens
- */
-static int ms_tokenize_command(char *command,
-                               token_t *tokens,
-                               const int max_tokens)
-{
-  char *s, *e;
-  int  ntokens= 0;
-
-  assert(command != NULL && tokens != NULL && max_tokens > 1);
-
-  for (s= e= command; ntokens < max_tokens - 1; ++e)
-  {
-    if (*e == ' ')
-    {
-      if (s != e)
-      {
-        tokens[ntokens].value= s;
-        tokens[ntokens].length= (size_t)(e - s);
-        ntokens++;
-        *e= '\0';
-      }
-      s= e + 1;
-    }
-    else if (*e == '\0')
-    {
-      if (s != e)
-      {
-        tokens[ntokens].value= s;
-        tokens[ntokens].length= (size_t)(e - s);
-        ntokens++;
-      }
-
-      break;       /* string end */
-    }
-  }
-
-  return ntokens;
-} /* ms_tokenize_command */
-
-
-/**
- * parse the response of server.
- *
- * @param c, pointer of the concurrency
- * @param command, the string responded by server
- *
- * @return int, if the command completed return EXIT_SUCCESS, else return
- *         -1
- */
-static int ms_ascii_process_line(ms_conn_t *c, char *command)
-{
-  int ret= 0;
-  int64_t value_len;
-  char *buffer= command;
-
-  assert(c != NULL);
-
-  /**
-   * for command get, we store the returned value into local buffer
-   * then continue in ms_complete_nread().
-   */
-
-  switch (buffer[0])
-  {
-  case 'V':                     /* VALUE || VERSION */
-    if (buffer[1] == 'A')       /* VALUE */
-    {
-      token_t tokens[MAX_TOKENS];
-      ms_tokenize_command(command, tokens, MAX_TOKENS);
-      errno= 0;
-      value_len= strtol(tokens[VALUELEN_TOKEN].value, NULL, 10);
-      if (errno != 0)
-      {
-        printf("<%d ERROR %s\n", c->sfd, strerror(errno));
-      }
-      c->currcmd.key_prefix= *(uint64_t *)tokens[KEY_TOKEN].value;
-
-      /*
-       *  We read the \r\n into the string since not doing so is more
-       *  cycles then the waster of memory to do so.
-       *
-       *  We are null terminating through, which will most likely make
-       *  some people lazy about using the return length.
-       */
-      c->rvbytes= (int)(value_len + 2);
-      c->readval= true;
-      ret= -1;
-    }
-
-    break;
-
-  case 'O':   /* OK */
-    c->currcmd.retstat= MCD_SUCCESS;
-    break;
-
-  case 'S':                    /* STORED STATS SERVER_ERROR */
-    if (buffer[2] == 'A')      /* STORED STATS */
-    {       /* STATS*/
-      c->currcmd.retstat= MCD_STAT;
-    }
-    else if (buffer[1] == 'E')
-    {
-      /* SERVER_ERROR */
-      printf("<%d %s\n", c->sfd, buffer);
-
-      c->currcmd.retstat= MCD_SERVER_ERROR;
-    }
-    else if (buffer[1] == 'T')
-    {
-      /* STORED */
-      c->currcmd.retstat= MCD_STORED;
-    }
-    else
-    {
-      c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
-    }
-    break;
-
-  case 'D':   /* DELETED DATA */
-    if (buffer[1] == 'E')
-    {
-      c->currcmd.retstat= MCD_DELETED;
-    }
-    else
-    {
-      c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
-    }
-
-    break;
-
-  case 'N':   /* NOT_FOUND NOT_STORED*/
-    if (buffer[4] == 'F')
-    {
-      c->currcmd.retstat= MCD_NOTFOUND;
-    }
-    else if (buffer[4] == 'S')
-    {
-      printf("<%d %s\n", c->sfd, buffer);
-      c->currcmd.retstat= MCD_NOTSTORED;
-    }
-    else
-    {
-      c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
-    }
-    break;
-
-  case 'E':   /* PROTOCOL ERROR or END */
-    if (buffer[1] == 'N')
-    {
-      /* END */
-      c->currcmd.retstat= MCD_END;
-    }
-    else if (buffer[1] == 'R')
-    {
-      printf("<%d ERROR\n", c->sfd);
-      c->currcmd.retstat= MCD_PROTOCOL_ERROR;
-    }
-    else if (buffer[1] == 'X')
-    {
-      c->currcmd.retstat= MCD_DATA_EXISTS;
-      printf("<%d %s\n", c->sfd, buffer);
-    }
-    else
-    {
-      c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
-    }
-    break;
-
-  case 'C':   /* CLIENT ERROR */
-    printf("<%d %s\n", c->sfd, buffer);
-    c->currcmd.retstat= MCD_CLIENT_ERROR;
-    break;
-
-  default:
-    c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
-    break;
-  } /* switch */
-
-  return ret;
-} /* ms_ascii_process_line */
-
-
-/**
- * after one operation completes, reset the concurrency
- *
- * @param c, pointer of the concurrency
- * @param timeout, whether it's timeout
- */
-void ms_reset_conn(ms_conn_t *c, bool timeout)
-{
-  assert(c != NULL);
-
-  if (c->udp)
-  {
-    if ((c->packets > 0) && (c->packets < MAX_UDP_PACKET))
-    {
-      memset(c->udppkt, 0, sizeof(ms_udppkt_t) * (size_t)c->packets);
-    }
-
-    c->packets= 0;
-    c->recvpkt= 0;
-    c->pktcurr= 0;
-    c->ordcurr= 0;
-    c->rudpbytes= 0;
-  }
-  c->currcmd.isfinish= true;
-  c->ctnwrite= false;
-  c->rbytes= 0;
-  c->rcurr= c->rbuf;
-  c->msgcurr = 0;
-  c->msgused = 0;
-  c->iovused = 0;
-  ms_conn_set_state(c, conn_write);
-  memcpy(&c->precmd, &c->currcmd, sizeof(ms_cmdstat_t));    /* replicate command state */
-
-  if (timeout)
-  {
-    ms_drive_machine(c);
-  }
-} /* ms_reset_conn */
-
-
-/**
- * if we have a complete line in the buffer, process it.
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_try_read_line(ms_conn_t *c)
-{
-  if (c->protocol == binary_prot)
-  {
-    /* Do we have the complete packet header? */
-    if ((uint64_t)c->rbytes < sizeof(c->binary_header))
-    {
-      /* need more data! */
-      return EXIT_SUCCESS;
-    }
-    else
-    {
-#ifdef NEED_ALIGN
-      if (((long)(c->rcurr)) % 8 != 0)
-      {
-        /* must realign input buffer */
-        memmove(c->rbuf, c->rcurr, c->rbytes);
-        c->rcurr= c->rbuf;
-        if (settings.verbose)
-        {
-          fprintf(stderr, "%d: Realign input buffer.\n", c->sfd);
-        }
-      }
-#endif
-      protocol_binary_response_header *rsp;
-      rsp= (protocol_binary_response_header *)c->rcurr;
-
-      c->binary_header= *rsp;
-      c->binary_header.response.extlen= rsp->response.extlen;
-      c->binary_header.response.keylen= ntohs(rsp->response.keylen);
-      c->binary_header.response.bodylen= ntohl(rsp->response.bodylen);
-      c->binary_header.response.status= ntohs(rsp->response.status);
-
-      if (c->binary_header.response.magic != PROTOCOL_BINARY_RES)
-      {
-        fprintf(stderr, "Invalid magic:  %x\n",
-                c->binary_header.response.magic);
-        ms_conn_set_state(c, conn_closing);
-        return EXIT_SUCCESS;
-      }
-
-      /* process this complete response */
-      if (ms_bin_process_response(c) == 0)
-      {
-        /* current operation completed */
-        ms_reset_conn(c, false);
-        return -1;
-      }
-      else
-      {
-        c->rbytes-= (int32_t)sizeof(c->binary_header);
-        c->rcurr+= sizeof(c->binary_header);
-      }
-    }
-  }
-  else
-  {
-    char *el, *cont;
-
-    assert(c != NULL);
-    assert(c->rcurr <= (c->rbuf + c->rsize));
-
-    if (c->rbytes == 0)
-      return EXIT_SUCCESS;
-
-    el= memchr(c->rcurr, '\n', (size_t)c->rbytes);
-    if (! el)
-      return EXIT_SUCCESS;
-
-    cont= el + 1;
-    if (((el - c->rcurr) > 1) && (*(el - 1) == '\r'))
-    {
-      el--;
-    }
-    *el= '\0';
-
-    assert(cont <= (c->rcurr + c->rbytes));
-
-    /* process this complete line */
-    if (ms_ascii_process_line(c, c->rcurr) == 0)
-    {
-      /* current operation completed */
-      ms_reset_conn(c, false);
-      return -1;
-    }
-    else
-    {
-      /* current operation didn't complete */
-      c->rbytes-= (int32_t)(cont - c->rcurr);
-      c->rcurr= cont;
-    }
-
-    assert(c->rcurr <= (c->rbuf + c->rsize));
-  }
-
-  return -1;
-} /* ms_try_read_line */
-
-
-/**
- *  because the packet of UDP can't ensure the order, the
- *  function is used to sort the received udp packet.
- *
- * @param c, pointer of the concurrency
- * @param buf, the buffer to store the ordered packages data
- * @param rbytes, the maximum capacity of the buffer
- *
- * @return int, if success, return the copy bytes, else return
- *         -1
- */
-static int ms_sort_udp_packet(ms_conn_t *c, char *buf, int rbytes)
-{
-  int len= 0;
-  int wbytes= 0;
-  uint16_t req_id= 0;
-  uint16_t seq_num= 0;
-  uint16_t packets= 0;
-  unsigned char *header= NULL;
-
-  /* no enough data */
-  assert(c != NULL);
-  assert(buf != NULL);
-  assert(c->rudpbytes >= UDP_HEADER_SIZE);
-
-  /* calculate received packets count */
-  if (c->rudpbytes % UDP_MAX_PAYLOAD_SIZE >= UDP_HEADER_SIZE)
-  {
-    /* the last packet has some data */
-    c->recvpkt= c->rudpbytes / UDP_MAX_PAYLOAD_SIZE + 1;
-  }
-  else
-  {
-    c->recvpkt= c->rudpbytes / UDP_MAX_PAYLOAD_SIZE;
-  }
-
-  /* get the total packets count if necessary */
-  if (c->packets == 0)
-  {
-    c->packets= HEADER_TO_PACKETS((unsigned char *)c->rudpbuf);
-  }
-
-  /* build the ordered packet array */
-  for (int i= c->pktcurr; i < c->recvpkt; i++)
-  {
-    header= (unsigned char *)c->rudpbuf + i * UDP_MAX_PAYLOAD_SIZE;
-    req_id= (uint16_t)HEADER_TO_REQID(header);
-    assert(req_id == c->request_id % (1 << 16));
-
-    packets= (uint16_t)HEADER_TO_PACKETS(header);
-    assert(c->packets == HEADER_TO_PACKETS(header));
-
-    seq_num= (uint16_t)HEADER_TO_SEQNUM(header);
-    c->udppkt[seq_num].header= header;
-    c->udppkt[seq_num].data= (char *)header + UDP_HEADER_SIZE;
-
-    if (i == c->recvpkt - 1)
-    {
-      /* last received packet */
-      if (c->rudpbytes % UDP_MAX_PAYLOAD_SIZE == 0)
-      {
-        c->udppkt[seq_num].rbytes= UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE;
-        c->pktcurr++;
-      }
-      else
-      {
-        c->udppkt[seq_num].rbytes= c->rudpbytes % UDP_MAX_PAYLOAD_SIZE
-                                   - UDP_HEADER_SIZE;
-      }
-    }
-    else
-    {
-      c->udppkt[seq_num].rbytes= UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE;
-      c->pktcurr++;
-    }
-  }
-
-  for (int i= c->ordcurr; i < c->recvpkt; i++)
-  {
-    /* there is some data to copy */
-    if ((c->udppkt[i].data != NULL)
-        && (c->udppkt[i].copybytes < c->udppkt[i].rbytes))
-    {
-      header= c->udppkt[i].header;
-      len= c->udppkt[i].rbytes - c->udppkt[i].copybytes;
-      if (len > rbytes - wbytes)
-      {
-        len= rbytes - wbytes;
-      }
-
-      assert(len <= rbytes - wbytes);
-      assert(i == HEADER_TO_SEQNUM(header));
-
-      memcpy(buf + wbytes, c->udppkt[i].data + c->udppkt[i].copybytes,
-             (size_t)len);
-      wbytes+= len;
-      c->udppkt[i].copybytes+= len;
-
-      if ((c->udppkt[i].copybytes == c->udppkt[i].rbytes)
-          && (c->udppkt[i].rbytes == UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE))
-      {
-        /* finish copying all the data of this packet, next */
-        c->ordcurr++;
-      }
-
-      /* last received packet, and finish copying all the data */
-      if ((c->recvpkt == c->packets) && (i == c->recvpkt - 1)
-          && (c->udppkt[i].copybytes == c->udppkt[i].rbytes))
-      {
-        break;
-      }
-
-      /* no space to copy data */
-      if (wbytes >= rbytes)
-      {
-        break;
-      }
-
-      /* it doesn't finish reading all the data of the packet from network */
-      if ((i != c->recvpkt - 1)
-          && (c->udppkt[i].rbytes < UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE))
-      {
-        break;
-      }
-    }
-    else
-    {
-      /* no data to copy */
-      break;
-    }
-  }
-  (void)packets;
-
-  return wbytes == 0 ? -1 : wbytes;
-} /* ms_sort_udp_packet */
-
-
-/**
- * encapsulate upd read like tcp read
- *
- * @param c, pointer of the concurrency
- * @param buf, read buffer
- * @param len, length to read
- *
- * @return int, if success, return the read bytes, else return
- *         -1
- */
-static int ms_udp_read(ms_conn_t *c, char *buf, int len)
-{
-  int res= 0;
-  int avail= 0;
-  int rbytes= 0;
-  int copybytes= 0;
-
-  assert(c->udp);
-
-  while (1)
-  {
-    if (c->rudpbytes + UDP_MAX_PAYLOAD_SIZE > c->rudpsize)
-    {
-      char *new_rbuf= realloc(c->rudpbuf, (size_t)c->rudpsize * 2);
-      if (! new_rbuf)
-      {
-        fprintf(stderr, "Couldn't realloc input buffer.\n");
-        c->rudpbytes= 0;          /* ignore what we read */
-        return -1;
-      }
-      c->rudpbuf= new_rbuf;
-      c->rudpsize*= 2;
-    }
-
-    avail= c->rudpsize - c->rudpbytes;
-    /* UDP each time read a packet, 1400 bytes */
-    res= (int)read(c->sfd, c->rudpbuf + c->rudpbytes, (size_t)avail);
-
-    if (res > 0)
-    {
-      atomic_add_size(&ms_stats.bytes_read, res);
-      c->rudpbytes+= res;
-      rbytes+= res;
-      if (res == avail)
-      {
-        continue;
-      }
-      else
-      {
-        break;
-      }
-    }
-
-    if (res == 0)
-    {
-      /* "connection" closed */
-      return res;
-    }
-
-    if (res == -1)
-    {
-      /* no data to read */
-      return res;
-    }
-  }
-
-  /* copy data to read buffer */
-  if (rbytes > 0)
-  {
-    copybytes= ms_sort_udp_packet(c, buf, len);
-  }
-
-  if (copybytes == -1)
-  {
-    atomic_add_size(&ms_stats.pkt_disorder, 1);
-  }
-
-  return copybytes;
-} /* ms_udp_read */
-
-
-/*
- * read from network as much as we can, handle buffer overflow and connection
- * close.
- * before reading, move the remaining incomplete fragment of a command
- * (if any) to the beginning of the buffer.
- * return EXIT_SUCCESS if there's nothing to read on the first read.
- */
-
-/**
- * read from network as much as we can, handle buffer overflow and connection
- * close. before reading, move the remaining incomplete fragment of a command
- * (if any) to the beginning of the buffer.
- *
- * @param c, pointer of the concurrency
- *
- * @return int,
- *         return EXIT_SUCCESS if there's nothing to read on the first read.
- *         return EXIT_FAILURE if get data
- *         return -1 if error happens
- */
-static int ms_try_read_network(ms_conn_t *c)
-{
-  int gotdata= 0;
-  int res;
-  int64_t avail;
-
-  assert(c != NULL);
-
-  if ((c->rcurr != c->rbuf)
-      && (! c->readval || (c->rvbytes > c->rsize - (c->rcurr - c->rbuf))
-          || (c->readval && (c->rcurr - c->rbuf > c->rbytes))))
-  {
-    if (c->rbytes != 0)     /* otherwise there's nothing to copy */
-      memmove(c->rbuf, c->rcurr, (size_t)c->rbytes);
-    c->rcurr= c->rbuf;
-  }
-
-  while (1)
-  {
-    if (c->rbytes >= c->rsize)
-    {
-      char *new_rbuf= realloc(c->rbuf, (size_t)c->rsize * 2);
-      if (! new_rbuf)
-      {
-        fprintf(stderr, "Couldn't realloc input buffer.\n");
-        c->rbytes= 0;          /* ignore what we read */
-        return -1;
-      }
-      c->rcurr= c->rbuf= new_rbuf;
-      c->rsize*= 2;
-    }
-
-    avail= c->rsize - c->rbytes - (c->rcurr - c->rbuf);
-    if (avail == 0)
-    {
-      break;
-    }
-
-    if (c->udp)
-    {
-      res= (int32_t)ms_udp_read(c, c->rcurr + c->rbytes, (int32_t)avail);
-    }
-    else
-    {
-      res= (int)read(c->sfd, c->rcurr + c->rbytes, (size_t)avail);
-    }
-
-    if (res > 0)
-    {
-      if (! c->udp)
-      {
-        atomic_add_size(&ms_stats.bytes_read, res);
-      }
-      gotdata= 1;
-      c->rbytes+= res;
-      if (res == avail)
-      {
-        continue;
-      }
-      else
-      {
-        break;
-      }
-    }
-    if (res == 0)
-    {
-      /* connection closed */
-      ms_conn_set_state(c, conn_closing);
-      return -1;
-    }
-    if (res == -1)
-    {
-      if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
-        break;
-      /* Should close on unhandled errors. */
-      ms_conn_set_state(c, conn_closing);
-      return -1;
-    }
-  }
-
-  return gotdata;
-} /* ms_try_read_network */
-
-
-/**
- * after get the object from server, verify the value if
- * necessary.
- *
- * @param c, pointer of the concurrency
- * @param mlget_item, pointer of mulit-get task item structure
- * @param value, received value string
- * @param vlen, received value string length
- */
-static void ms_verify_value(ms_conn_t *c,
-                            ms_mlget_task_item_t *mlget_item,
-                            char *value,
-                            int vlen)
-{
-  if (c->curr_task.verify)
-  {
-    assert(c->curr_task.item->value_offset != INVALID_OFFSET);
-    char *orignval= &ms_setting.char_block[c->curr_task.item->value_offset];
-    char *orignkey=
-      &ms_setting.char_block[c->curr_task.item->key_suffix_offset];
-
-    /* verify expire time if necessary */
-    if (c->curr_task.item->exp_time > 0)
-    {
-      struct timeval curr_time;
-      gettimeofday(&curr_time, NULL);
-
-      /* object expired but get it now */
-      if (curr_time.tv_sec - c->curr_task.item->client_time
-          > c->curr_task.item->exp_time + EXPIRE_TIME_ERROR)
-      {
-        atomic_add_size(&ms_stats.exp_get, 1);
-
-        if (ms_setting.verbose)
-        {
-          char set_time[64];
-          char cur_time[64];
-          strftime(set_time, 64, "%Y-%m-%d %H:%M:%S",
-                   localtime(&c->curr_task.item->client_time));
-          strftime(cur_time, 64, "%Y-%m-%d %H:%M:%S",
-                   localtime(&curr_time.tv_sec));
-          fprintf(stderr,
-                  "\n<%d expire time verification failed, "
-                  "object expired but get it now\n"
-                  "\tkey len: %d\n"
-                  "\tkey: %" PRIx64 " %.*s\n"
-                  "\tset time: %s current time: %s "
-                  "diff time: %d expire time: %d\n"
-                  "\texpected data: \n"
-                  "\treceived data len: %d\n"
-                  "\treceived data: %.*s\n",
-                  c->sfd,
-                  c->curr_task.item->key_size,
-                  c->curr_task.item->key_prefix,
-                  c->curr_task.item->key_size - (int)KEY_PREFIX_SIZE,
-                  orignkey,
-                  set_time,
-                  cur_time,
-                  (int)(curr_time.tv_sec - c->curr_task.item->client_time),
-                  c->curr_task.item->exp_time,
-                  vlen,
-                  vlen,
-                  value);
-          fflush(stderr);
-        }
-      }
-    }
-    else
-    {
-      if ((c->curr_task.item->value_size != vlen)
-          || (memcmp(orignval, value, (size_t)vlen) != 0))
-      {
-        atomic_add_size(&ms_stats.vef_failed, 1);
-
-        if (ms_setting.verbose)
-        {
-          fprintf(stderr,
-                  "\n<%d data verification failed\n"
-                  "\tkey len: %d\n"
-                  "\tkey: %" PRIx64" %.*s\n"
-                  "\texpected data len: %d\n"
-                  "\texpected data: %.*s\n"
-                  "\treceived data len: %d\n"
-                  "\treceived data: %.*s\n",
-                  c->sfd,
-                  c->curr_task.item->key_size,
-                  c->curr_task.item->key_prefix,
-                  c->curr_task.item->key_size - (int)KEY_PREFIX_SIZE,
-                  orignkey,
-                  c->curr_task.item->value_size,
-                  c->curr_task.item->value_size,
-                  orignval,
-                  vlen,
-                  vlen,
-                  value);
-          fflush(stderr);
-        }
-      }
-    }
-
-    c->curr_task.finish_verify= true;
-
-    if (mlget_item != NULL)
-    {
-      mlget_item->finish_verify= true;
-    }
-  }
-} /* ms_verify_value */
-
-
-/**
- * For ASCII protocol, after store the data into the local
- * buffer, run this function to handle the data.
- *
- * @param c, pointer of the concurrency
- */
-static void ms_ascii_complete_nread(ms_conn_t *c)
-{
-  assert(c != NULL);
-  assert(c->rbytes >= c->rvbytes);
-  assert(c->protocol == ascii_prot);
-  if (c->rvbytes > 2)
-  {
-    assert(
-      c->rcurr[c->rvbytes - 1] == '\n' && c->rcurr[c->rvbytes - 2] == '\r');
-  }
-
-  /* multi-get */
-  ms_mlget_task_item_t *mlget_item= NULL;
-  if (((ms_setting.mult_key_num > 1)
-       && (c->mlget_task.mlget_num >= ms_setting.mult_key_num))
-      || ((c->remain_exec_num == 0) && (c->mlget_task.mlget_num > 0)))
-  {
-    c->mlget_task.value_index++;
-    mlget_item= &c->mlget_task.mlget_item[c->mlget_task.value_index];
-
-    if (mlget_item->item->key_prefix == c->currcmd.key_prefix)
-    {
-      c->curr_task.item= mlget_item->item;
-      c->curr_task.verify= mlget_item->verify;
-      c->curr_task.finish_verify= mlget_item->finish_verify;
-      mlget_item->get_miss= false;
-    }
-    else
-    {
-      /* Try to find the task item in multi-get task array */
-      for (int i= 0; i < c->mlget_task.mlget_num; i++)
-      {
-        mlget_item= &c->mlget_task.mlget_item[i];
-        if (mlget_item->item->key_prefix == c->currcmd.key_prefix)
-        {
-          c->curr_task.item= mlget_item->item;
-          c->curr_task.verify= mlget_item->verify;
-          c->curr_task.finish_verify= mlget_item->finish_verify;
-          mlget_item->get_miss= false;
-
-          break;
-        }
-      }
-    }
-  }
-
-  ms_verify_value(c, mlget_item, c->rcurr, c->rvbytes - 2);
-
-  c->curr_task.get_miss= false;
-  c->rbytes-= c->rvbytes;
-  c->rcurr= c->rcurr + c->rvbytes;
-  assert(c->rcurr <= (c->rbuf + c->rsize));
-  c->readval= false;
-  c->rvbytes= 0;
-} /* ms_ascii_complete_nread */
-
-
-/**
- * For binary protocol, after store the data into the local
- * buffer, run this function to handle the data.
- *
- * @param c, pointer of the concurrency
- */
-static void ms_bin_complete_nread(ms_conn_t *c)
-{
-  assert(c != NULL);
-  assert(c->rbytes >= c->rvbytes);
-  assert(c->protocol == binary_prot);
-
-  int extlen= c->binary_header.response.extlen;
-  int keylen= c->binary_header.response.keylen;
-  uint8_t opcode= c->binary_header.response.opcode;
-
-  /* not get command or not include value, just return */
-  if (((opcode != PROTOCOL_BINARY_CMD_GET)
-       && (opcode != PROTOCOL_BINARY_CMD_GETQ))
-      || (c->rvbytes <= extlen + keylen))
-  {
-    /* get miss */
-    if (c->binary_header.response.opcode == PROTOCOL_BINARY_CMD_GET)
-    {
-      c->currcmd.retstat= MCD_END;
-      c->curr_task.get_miss= true;
-    }
-
-    c->readval= false;
-    c->rvbytes= 0;
-    ms_reset_conn(c, false);
-    return;
-  }
-
-  /* multi-get */
-  ms_mlget_task_item_t *mlget_item= NULL;
-  if (((ms_setting.mult_key_num > 1)
-       && (c->mlget_task.mlget_num >= ms_setting.mult_key_num))
-      || ((c->remain_exec_num == 0) && (c->mlget_task.mlget_num > 0)))
-  {
-    c->mlget_task.value_index++;
-    mlget_item= &c->mlget_task.mlget_item[c->mlget_task.value_index];
-
-    c->curr_task.item= mlget_item->item;
-    c->curr_task.verify= mlget_item->verify;
-    c->curr_task.finish_verify= mlget_item->finish_verify;
-    mlget_item->get_miss= false;
-  }
-
-  ms_verify_value(c,
-                  mlget_item,
-                  c->rcurr + extlen + keylen,
-                  c->rvbytes - extlen - keylen);
-
-  c->currcmd.retstat= MCD_END;
-  c->curr_task.get_miss= false;
-  c->rbytes-= c->rvbytes;
-  c->rcurr= c->rcurr + c->rvbytes;
-  assert(c->rcurr <= (c->rbuf + c->rsize));
-  c->readval= false;
-  c->rvbytes= 0;
-
-  if (ms_setting.mult_key_num > 1)
-  {
-    /* multi-get have check all the item */
-    if (c->mlget_task.value_index == c->mlget_task.mlget_num - 1)
-    {
-      ms_reset_conn(c, false);
-    }
-  }
-  else
-  {
-    /* single get */
-    ms_reset_conn(c, false);
-  }
-} /* ms_bin_complete_nread */
-
-
-/**
- * we get here after reading the value of get commands.
- *
- * @param c, pointer of the concurrency
- */
-static void ms_complete_nread(ms_conn_t *c)
-{
-  assert(c != NULL);
-  assert(c->rbytes >= c->rvbytes);
-  assert(c->protocol == ascii_prot
-         || c->protocol == binary_prot);
-
-  if (c->protocol == binary_prot)
-  {
-    ms_bin_complete_nread(c);
-  }
-  else
-  {
-    ms_ascii_complete_nread(c);
-  }
-} /* ms_complete_nread */
-
-
-/**
- * Adds a message header to a connection.
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_add_msghdr(ms_conn_t *c)
-{
-  struct msghdr *msg;
-
-  assert(c != NULL);
-
-  if (c->msgsize == c->msgused)
-  {
-    msg=
-      realloc(c->msglist, (size_t)c->msgsize * 2 * sizeof(struct msghdr));
-    if (! msg)
-      return -1;
-
-    c->msglist= msg;
-    c->msgsize*= 2;
-  }
-
-  msg= c->msglist + c->msgused;
-
-  /**
-   *  this wipes msg_iovlen, msg_control, msg_controllen, and
-   *  msg_flags, the last 3 of which aren't defined on solaris:
-   */
-  memset(msg, 0, sizeof(struct msghdr));
-
-  msg->msg_iov= &c->iov[c->iovused];
-
-  if (c->udp && (c->srv_recv_addr_size > 0))
-  {
-    msg->msg_name= &c->srv_recv_addr;
-    msg->msg_namelen= c->srv_recv_addr_size;
-  }
-
-  c->msgbytes= 0;
-  c->msgused++;
-
-  if (c->udp)
-  {
-    /* Leave room for the UDP header, which we'll fill in later. */
-    return ms_add_iov(c, NULL, UDP_HEADER_SIZE);
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_add_msghdr */
-
-
-/**
- * Ensures that there is room for another structure iovec in a connection's
- * iov list.
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_ensure_iov_space(ms_conn_t *c)
-{
-  assert(c != NULL);
-
-  if (c->iovused >= c->iovsize)
-  {
-    int i, iovnum;
-    struct iovec *new_iov= (struct iovec *)realloc(c->iov,
-                                                   ((size_t)c->iovsize
-                                                    * 2)
-                                                   * sizeof(struct iovec));
-    if (! new_iov)
-      return -1;
-
-    c->iov= new_iov;
-    c->iovsize*= 2;
-
-    /* Point all the msghdr structures at the new list. */
-    for (i= 0, iovnum= 0; i < c->msgused; i++)
-    {
-      c->msglist[i].msg_iov= &c->iov[iovnum];
-      iovnum+= (int)c->msglist[i].msg_iovlen;
-    }
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_ensure_iov_space */
-
-
-/**
- * Adds data to the list of pending data that will be written out to a
- * connection.
- *
- * @param c, pointer of the concurrency
- * @param buf, the buffer includes data to send
- * @param len, the data length in the buffer
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_add_iov(ms_conn_t *c, const void *buf, int len)
-{
-  struct msghdr *m;
-  int  leftover;
-  bool limit_to_mtu;
-
-  assert(c != NULL);
-
-  do
-  {
-    m= &c->msglist[c->msgused - 1];
-
-    /*
-     * Limit UDP packets, to UDP_MAX_PAYLOAD_SIZE bytes.
-     */
-    limit_to_mtu= c->udp;
-
-#ifdef IOV_MAX
-    /* We may need to start a new msghdr if this one is full. */
-    if ((m->msg_iovlen == IOV_MAX)
-        || (limit_to_mtu && (c->msgbytes >= UDP_MAX_SEND_PAYLOAD_SIZE)))
-    {
-      ms_add_msghdr(c);
-      m= &c->msglist[c->msgused - 1];
-    }
-#endif
-
-    if (ms_ensure_iov_space(c) != 0)
-      return -1;
-
-    /* If the fragment is too big to fit in the datagram, split it up */
-    if (limit_to_mtu && (len + c->msgbytes > UDP_MAX_SEND_PAYLOAD_SIZE))
-    {
-      leftover= len + c->msgbytes - UDP_MAX_SEND_PAYLOAD_SIZE;
-      len-= leftover;
-    }
-    else
-    {
-      leftover= 0;
-    }
-
-    m= &c->msglist[c->msgused - 1];
-    m->msg_iov[m->msg_iovlen].iov_base= (void *)buf;
-    m->msg_iov[m->msg_iovlen].iov_len= (size_t)len;
-
-    c->msgbytes+= len;
-    c->iovused++;
-    m->msg_iovlen++;
-
-    buf= ((char *)buf) + len;
-    len= leftover;
-  }
-  while (leftover > 0);
-
-  return EXIT_SUCCESS;
-} /* ms_add_iov */
-
-
-/**
- * Constructs a set of UDP headers and attaches them to the outgoing messages.
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_build_udp_headers(ms_conn_t *c)
-{
-  int i;
-  unsigned char *hdr;
-
-  assert(c != NULL);
-
-  c->request_id= ms_get_udp_request_id();
-
-  if (c->msgused > c->hdrsize)
-  {
-    void *new_hdrbuf;
-    if (c->hdrbuf)
-      new_hdrbuf= realloc(c->hdrbuf,
-                          (size_t)c->msgused * 2 * UDP_HEADER_SIZE);
-    else
-      new_hdrbuf= malloc((size_t)c->msgused * 2 * UDP_HEADER_SIZE);
-    if (! new_hdrbuf)
-      return -1;
-
-    c->hdrbuf= (unsigned char *)new_hdrbuf;
-    c->hdrsize= c->msgused * 2;
-  }
-
-  /* If this is a multi-packet request, drop it. */
-  if (c->udp && (c->msgused > 1))
-  {
-    fprintf(stderr, "multi-packet request for UDP not supported.\n");
-    return -1;
-  }
-
-  hdr= c->hdrbuf;
-  for (i= 0; i < c->msgused; i++)
-  {
-    c->msglist[i].msg_iov[0].iov_base= (void *)hdr;
-    c->msglist[i].msg_iov[0].iov_len= UDP_HEADER_SIZE;
-    *hdr++= (unsigned char)(c->request_id / 256);
-    *hdr++= (unsigned char)(c->request_id % 256);
-    *hdr++= (unsigned char)(i / 256);
-    *hdr++= (unsigned char)(i % 256);
-    *hdr++= (unsigned char)(c->msgused / 256);
-    *hdr++= (unsigned char)(c->msgused % 256);
-    *hdr++= (unsigned char)1;          /* support facebook memcached */
-    *hdr++= (unsigned char)0;
-    assert(hdr ==
-           ((unsigned char *)c->msglist[i].msg_iov[0].iov_base
-            + UDP_HEADER_SIZE));
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_build_udp_headers */
-
-
-/**
- * Transmit the next chunk of data from our list of msgbuf structures.
- *
- * @param c, pointer of the concurrency
- *
- * @return  TRANSMIT_COMPLETE   All done writing.
- *          TRANSMIT_INCOMPLETE More data remaining to write.
- *          TRANSMIT_SOFT_ERROR Can't write any more right now.
- *          TRANSMIT_HARD_ERROR Can't write (c->state is set to conn_closing)
- */
-static int ms_transmit(ms_conn_t *c)
-{
-  assert(c != NULL);
-
-  if ((c->msgcurr < c->msgused)
-      && (c->msglist[c->msgcurr].msg_iovlen == 0))
-  {
-    /* Finished writing the current msg; advance to the next. */
-    c->msgcurr++;
-  }
-
-  if (c->msgcurr < c->msgused)
-  {
-    ssize_t res;
-    struct msghdr *m= &c->msglist[c->msgcurr];
-
-    res= sendmsg(c->sfd, m, 0);
-    if (res > 0)
-    {
-      atomic_add_size(&ms_stats.bytes_written, res);
-
-      /* We've written some of the data. Remove the completed
-       *  iovec entries from the list of pending writes. */
-      while (m->msg_iovlen > 0 && res >= (ssize_t)m->msg_iov->iov_len)
-      {
-        res-= (ssize_t)m->msg_iov->iov_len;
-        m->msg_iovlen--;
-        m->msg_iov++;
-      }
-
-      /* Might have written just part of the last iovec entry;
-       *  adjust it so the next write will do the rest. */
-      if (res > 0)
-      {
-        m->msg_iov->iov_base= (void *)((unsigned char *)m->msg_iov->iov_base + res);
-        m->msg_iov->iov_len-= (size_t)res;
-      }
-      return TRANSMIT_INCOMPLETE;
-    }
-    if ((res == -1) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
-    {
-      if (! ms_update_event(c, EV_WRITE | EV_PERSIST))
-      {
-        fprintf(stderr, "Couldn't update event.\n");
-        ms_conn_set_state(c, conn_closing);
-        return TRANSMIT_HARD_ERROR;
-      }
-      return TRANSMIT_SOFT_ERROR;
-    }
-
-    /* if res==0 or res==-1 and error is not EAGAIN or EWOULDBLOCK,
-     *  we have a real error, on which we close the connection */
-    fprintf(stderr, "Failed to write, and not due to blocking.\n");
-
-    ms_conn_set_state(c, conn_closing);
-    return TRANSMIT_HARD_ERROR;
-  }
-  else
-  {
-    return TRANSMIT_COMPLETE;
-  }
-} /* ms_transmit */
-
-
-/**
- * Shrinks a connection's buffers if they're too big.  This prevents
- * periodic large "mget" response from server chewing lots of client
- * memory.
- *
- * This should only be called in between requests since it can wipe output
- * buffers!
- *
- * @param c, pointer of the concurrency
- */
-static void ms_conn_shrink(ms_conn_t *c)
-{
-  assert(c != NULL);
-
-  if (c->udp)
-    return;
-
-  if ((c->rsize > READ_BUFFER_HIGHWAT) && (c->rbytes < DATA_BUFFER_SIZE))
-  {
-    char *newbuf;
-
-    if (c->rcurr != c->rbuf)
-      memmove(c->rbuf, c->rcurr, (size_t)c->rbytes);
-
-    newbuf= (char *)realloc((void *)c->rbuf, DATA_BUFFER_SIZE);
-
-    if (newbuf)
-    {
-      c->rbuf= newbuf;
-      c->rsize= DATA_BUFFER_SIZE;
-    }
-    c->rcurr= c->rbuf;
-  }
-
-  if (c->udp && (c->rudpsize > UDP_DATA_BUFFER_HIGHWAT)
-      && (c->rudpbytes + UDP_MAX_PAYLOAD_SIZE < UDP_DATA_BUFFER_SIZE))
-  {
-    char *new_rbuf= (char *)realloc(c->rudpbuf, (size_t)c->rudpsize * 2);
-    if (new_rbuf)
-    {
-      c->rudpbuf= new_rbuf;
-      c->rudpsize= UDP_DATA_BUFFER_SIZE;
-    }
-    /* TODO check error condition? */
-  }
-
-  if (c->msgsize > MSG_LIST_HIGHWAT)
-  {
-    struct msghdr *newbuf= (struct msghdr *)realloc(
-      (void *)c->msglist,
-      MSG_LIST_INITIAL
-      * sizeof(c->msglist[0]));
-    if (newbuf)
-    {
-      c->msglist= newbuf;
-      c->msgsize= MSG_LIST_INITIAL;
-    }
-    /* TODO check error condition? */
-  }
-
-  if (c->iovsize > IOV_LIST_HIGHWAT)
-  {
-    struct iovec *newbuf= (struct iovec *)realloc((void *)c->iov,
-                                                  IOV_LIST_INITIAL
-                                                  * sizeof(c->iov[0]));
-    if (newbuf)
-    {
-      c->iov= newbuf;
-      c->iovsize= IOV_LIST_INITIAL;
-    }
-    /* TODO check return value */
-  }
-} /* ms_conn_shrink */
-
-
-/**
- * Sets a connection's current state in the state machine. Any special
- * processing that needs to happen on certain state transitions can
- * happen here.
- *
- * @param c, pointer of the concurrency
- * @param state, connection state
- */
-static void ms_conn_set_state(ms_conn_t *c, int state)
-{
-  assert(c != NULL);
-
-  if (state != c->state)
-  {
-    if (state == conn_read)
-    {
-      ms_conn_shrink(c);
-    }
-    c->state= state;
-  }
-} /* ms_conn_set_state */
-
-
-/**
- * update the event if socks change state. for example: when
- * change the listen scoket read event to sock write event, or
- * change socket handler, we could call this function.
- *
- * @param c, pointer of the concurrency
- * @param new_flags, new event flags
- *
- * @return bool, if success, return true, else return false
- */
-static bool ms_update_event(ms_conn_t *c, const int new_flags)
-{
-  assert(c != NULL);
-
-  struct event_base *base= c->event.ev_base;
-  if ((c->ev_flags == new_flags) && (ms_setting.rep_write_srv == 0)
-      && (! ms_setting.facebook_test || (c->total_sfds == 1)))
-  {
-    return true;
-  }
-
-  if (event_del(&c->event) == -1)
-  {
-    /* try to delete the event again */
-    if (event_del(&c->event) == -1)
-    {
-      return false;
-    }
-  }
-
-  event_set(&c->event,
-            c->sfd,
-            (short)new_flags,
-            ms_event_handler,
-            (void *)c);
-  event_base_set(base, &c->event);
-  c->ev_flags= (short)new_flags;
-
-  if (event_add(&c->event, NULL) == -1)
-  {
-    return false;
-  }
-
-  return true;
-} /* ms_update_event */
-
-
-/**
- * If user want to get the expected throughput, we could limit
- * the performance of memslap. we could give up some work and
- * just wait a short time. The function is used to check this
- * case.
- *
- * @param c, pointer of the concurrency
- *
- * @return bool, if success, return true, else return false
- */
-static bool ms_need_yield(ms_conn_t *c)
-{
-  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
-  int64_t tps= 0;
-  int64_t time_diff= 0;
-  struct timeval curr_time;
-  ms_task_t *task= &c->curr_task;
-
-  if (ms_setting.expected_tps > 0)
-  {
-    gettimeofday(&curr_time, NULL);
-    time_diff= ms_time_diff(&ms_thread->startup_time, &curr_time);
-    tps= (int64_t)(((task->get_opt + task->set_opt) / (uint64_t)time_diff) * 1000000);
-
-    /* current throughput is greater than expected throughput */
-    if (tps > ms_thread->thread_ctx->tps_perconn)
-    {
-      return true;
-    }
-  }
-
-  return false;
-} /* ms_need_yield */
-
-
-/**
- * used to update the start time of each operation
- *
- * @param c, pointer of the concurrency
- */
-static void ms_update_start_time(ms_conn_t *c)
-{
-  ms_task_item_t *item= c->curr_task.item;
-
-  if ((ms_setting.stat_freq > 0) || c->udp
-      || ((c->currcmd.cmd == CMD_SET) && (item->exp_time > 0)))
-  {
-    gettimeofday(&c->start_time, NULL);
-    if ((c->currcmd.cmd == CMD_SET) && (item->exp_time > 0))
-    {
-      /* record the current time */
-      item->client_time= c->start_time.tv_sec;
-    }
-  }
-} /* ms_update_start_time */
-
-
-/**
- * run the state machine
- *
- * @param c, pointer of the concurrency
- */
-static void ms_drive_machine(ms_conn_t *c)
-{
-  bool stop= false;
-
-  assert(c != NULL);
-
-  while (! stop)
-  {
-    switch (c->state)
-    {
-    case conn_read:
-      if (c->readval)
-      {
-        if (c->rbytes >= c->rvbytes)
-        {
-          ms_complete_nread(c);
-          break;
-        }
-      }
-      else
-      {
-        if (ms_try_read_line(c) != 0)
-        {
-          break;
-        }
-      }
-
-      if (ms_try_read_network(c) != 0)
-      {
-        break;
-      }
-
-      /* doesn't read all the response data, wait event wake up */
-      if (! c->currcmd.isfinish)
-      {
-        if (! ms_update_event(c, EV_READ | EV_PERSIST))
-        {
-          fprintf(stderr, "Couldn't update event.\n");
-          ms_conn_set_state(c, conn_closing);
-          break;
-        }
-        stop= true;
-        break;
-      }
-
-      /* we have no command line and no data to read from network, next write */
-      ms_conn_set_state(c, conn_write);
-      memcpy(&c->precmd, &c->currcmd, sizeof(ms_cmdstat_t));        /* replicate command state */
-
-      break;
-
-    case conn_write:
-      if (! c->ctnwrite && ms_need_yield(c))
-      {
-        usleep(10);
-
-        if (! ms_update_event(c, EV_WRITE | EV_PERSIST))
-        {
-          fprintf(stderr, "Couldn't update event.\n");
-          ms_conn_set_state(c, conn_closing);
-          break;
-        }
-        stop= true;
-        break;
-      }
-
-      if (! c->ctnwrite && (ms_exec_task(c) != 0))
-      {
-        ms_conn_set_state(c, conn_closing);
-        break;
-      }
-
-      /* record the start time before starting to send data if necessary */
-      if (! c->ctnwrite || (c->change_sfd && c->ctnwrite))
-      {
-        if (c->change_sfd)
-        {
-          c->change_sfd= false;
-        }
-        ms_update_start_time(c);
-      }
-
-      /* change sfd if necessary */
-      if (c->change_sfd)
-      {
-        c->ctnwrite= true;
-        stop= true;
-        break;
-      }
-
-      /* execute task until nothing need be written to network */
-      if (! c->ctnwrite && (c->msgcurr == c->msgused))
-      {
-        if (! ms_update_event(c, EV_WRITE | EV_PERSIST))
-        {
-          fprintf(stderr, "Couldn't update event.\n");
-          ms_conn_set_state(c, conn_closing);
-          break;
-        }
-        stop= true;
-        break;
-      }
-
-      switch (ms_transmit(c))
-      {
-      case TRANSMIT_COMPLETE:
-        /* we have no data to write to network, next wait repose */
-        if (! ms_update_event(c, EV_READ | EV_PERSIST))
-        {
-          fprintf(stderr, "Couldn't update event.\n");
-          ms_conn_set_state(c, conn_closing);
-          c->ctnwrite= false;
-          break;
-        }
-        ms_conn_set_state(c, conn_read);
-        c->ctnwrite= false;
-        stop= true;
-        break;
-
-      case TRANSMIT_INCOMPLETE:
-        c->ctnwrite= true;
-        break;                           /* Continue in state machine. */
-
-      case TRANSMIT_HARD_ERROR:
-        c->ctnwrite= false;
-        break;
-
-      case TRANSMIT_SOFT_ERROR:
-        c->ctnwrite= true;
-        stop= true;
-        break;
-
-      default:
-        break;
-      } /* switch */
-
-      break;
-
-    case conn_closing:
-      /* recovery mode, need reconnect if connection close */
-      if (ms_setting.reconnect && (! ms_global.time_out
-                                   || ((ms_setting.run_time == 0)
-                                       && (c->remain_exec_num > 0))))
-      {
-        if (ms_reconn(c) != 0)
-        {
-          ms_conn_close(c);
-          stop= true;
-          break;
-        }
-
-        ms_reset_conn(c, false);
-
-        if (c->total_sfds == 1)
-        {
-          if (! ms_update_event(c, EV_WRITE | EV_PERSIST))
-          {
-            fprintf(stderr, "Couldn't update event.\n");
-            ms_conn_set_state(c, conn_closing);
-            break;
-          }
-        }
-
-        break;
-      }
-      else
-      {
-        ms_conn_close(c);
-        stop= true;
-        break;
-      }
-
-    default:
-      assert(0);
-    } /* switch */
-  }
-} /* ms_drive_machine */
-
-
-/**
- * the event handler of each thread
- *
- * @param fd, the file descriptor of socket
- * @param which, event flag
- * @param arg, argument
- */
-void ms_event_handler(const int fd, const short which, void *arg)
-{
-  ms_conn_t *c= (ms_conn_t *)arg;
-
-  assert(c != NULL);
-
-  c->which= which;
-
-  /* sanity */
-  if (fd != c->sfd)
-  {
-    fprintf(stderr,
-            "Catastrophic: event fd: %d doesn't match conn fd: %d\n",
-            fd,
-            c->sfd);
-    ms_conn_close(c);
-    exit(1);
-  }
-  assert(fd == c->sfd);
-
-  ms_drive_machine(c);
-
-  /* wait for next event */
-} /* ms_event_handler */
-
-
-/**
- * get the next socket descriptor index to run for replication
- *
- * @param c, pointer of the concurrency
- * @param cmd, command(get or set )
- *
- * @return int, if success, return the index, else return EXIT_SUCCESS
- */
-static uint32_t ms_get_rep_sock_index(ms_conn_t *c, int cmd)
-{
-  uint32_t sock_index= 0;
-  uint32_t i= 0;
-
-  if (c->total_sfds == 1)
-  {
-    return EXIT_SUCCESS;
-  }
-
-  if (ms_setting.rep_write_srv == 0)
-  {
-    return sock_index;
-  }
-
-  do
-  {
-    if (cmd == CMD_SET)
-    {
-      for (i= 0; i < ms_setting.rep_write_srv; i++)
-      {
-        if (c->tcpsfd[i] > 0)
-        {
-          break;
-        }
-      }
-
-      if (i == ms_setting.rep_write_srv)
-      {
-        /* random get one replication server to read */
-        sock_index= (uint32_t)random() % c->total_sfds;
-      }
-      else
-      {
-        /* random get one replication writing server to write */
-        sock_index= (uint32_t)random() % ms_setting.rep_write_srv;
-      }
-    }
-    else if (cmd == CMD_GET)
-    {
-      /* random get one replication server to read */
-      sock_index= (uint32_t)random() % c->total_sfds;
-    }
-  }
-  while (c->tcpsfd[sock_index] == 0);
-
-  return sock_index;
-} /* ms_get_rep_sock_index */
-
-
-/**
- * get the next socket descriptor index to run
- *
- * @param c, pointer of the concurrency
- *
- * @return int, return the index
- */
-static uint32_t ms_get_next_sock_index(ms_conn_t *c)
-{
-  uint32_t sock_index= 0;
-
-  do
-  {
-    sock_index= (++c->cur_idx == c->total_sfds) ? 0 : c->cur_idx;
-  }
-  while (c->tcpsfd[sock_index] == 0);
-
-  return sock_index;
-} /* ms_get_next_sock_index */
-
-
-/**
- * update socket event of the connections
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_update_conn_sock_event(ms_conn_t *c)
-{
-  assert(c != NULL);
-
-  switch (c->currcmd.cmd)
-  {
-  case CMD_SET:
-    if (ms_setting.facebook_test && c->udp)
-    {
-      c->sfd= c->tcpsfd[0];
-      c->udp= false;
-      c->change_sfd= true;
-    }
-    break;
-
-  case CMD_GET:
-    if (ms_setting.facebook_test && ! c->udp)
-    {
-      c->sfd= c->udpsfd;
-      c->udp= true;
-      c->change_sfd= true;
-    }
-    break;
-
-  default:
-    break;
-  } /* switch */
-
-  if (! c->udp && (c->total_sfds > 1))
-  {
-    if (c->cur_idx != c->total_sfds)
-    {
-      if (ms_setting.rep_write_srv == 0)
-      {
-        c->cur_idx= ms_get_next_sock_index(c);
-      }
-      else
-      {
-        c->cur_idx= ms_get_rep_sock_index(c, c->currcmd.cmd);
-      }
-    }
-    else
-    {
-      /* must select the first sock of the connection at the beginning */
-      c->cur_idx= 0;
-    }
-
-    c->sfd= c->tcpsfd[c->cur_idx];
-    assert(c->sfd != 0);
-    c->change_sfd= true;
-  }
-
-  if (c->change_sfd)
-  {
-    if (! ms_update_event(c, EV_WRITE | EV_PERSIST))
-    {
-      fprintf(stderr, "Couldn't update event.\n");
-      ms_conn_set_state(c, conn_closing);
-      return -1;
-    }
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_update_conn_sock_event */
-
-
-/**
- * for ASCII protocol, this function build the set command
- * string and send the command.
- *
- * @param c, pointer of the concurrency
- * @param item, pointer of task item which includes the object
- *            information
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_build_ascii_write_buf_set(ms_conn_t *c, ms_task_item_t *item)
-{
-  int value_offset;
-  int write_len;
-  char *buffer= c->wbuf;
-
-  write_len= snprintf(buffer,
-                      c->wsize,
-                      " %u %d %d\r\n",
-                      0,
-                      item->exp_time,
-                      item->value_size);
-
-  if (write_len > c->wsize || write_len < 0)
-  {
-    /* ought to be always enough. just fail for simplicity */
-    fprintf(stderr, "output command line too long.\n");
-    return -1;
-  }
-
-  if (item->value_offset == INVALID_OFFSET)
-  {
-    value_offset= item->key_suffix_offset;
-  }
-  else
-  {
-    value_offset= item->value_offset;
-  }
-
-  if ((ms_add_iov(c, "set ", 4) != 0)
-      || (ms_add_iov(c, (char *)&item->key_prefix,
-                     (int)KEY_PREFIX_SIZE) != 0)
-      || (ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset],
-                     item->key_size - (int)KEY_PREFIX_SIZE) != 0)
-      || (ms_add_iov(c, buffer, write_len) != 0)
-      || (ms_add_iov(c, &ms_setting.char_block[value_offset],
-                     item->value_size) != 0)
-      || (ms_add_iov(c, "\r\n", 2) != 0)
-      || (c->udp && (ms_build_udp_headers(c) != 0)))
-  {
-    return -1;
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_build_ascii_write_buf_set */
-
-
-/**
- * used to send set command to server
- *
- * @param c, pointer of the concurrency
- * @param item, pointer of task item which includes the object
- *            information
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-int ms_mcd_set(ms_conn_t *c, ms_task_item_t *item)
-{
-  assert(c != NULL);
-
-  c->currcmd.cmd= CMD_SET;
-  c->currcmd.isfinish= false;
-  c->currcmd.retstat= MCD_FAILURE;
-
-  if (ms_update_conn_sock_event(c) != 0)
-  {
-    return -1;
-  }
-
-  c->msgcurr= 0;
-  c->msgused= 0;
-  c->iovused= 0;
-  if (ms_add_msghdr(c) != 0)
-  {
-    fprintf(stderr, "Out of memory preparing request.");
-    return -1;
-  }
-
-  /* binary protocol */
-  if (c->protocol == binary_prot)
-  {
-    if (ms_build_bin_write_buf_set(c, item) != 0)
-    {
-      return -1;
-    }
-  }
-  else
-  {
-    if (ms_build_ascii_write_buf_set(c, item) != 0)
-    {
-      return -1;
-    }
-  }
-
-  atomic_add_size(&ms_stats.obj_bytes,
-                  item->key_size + item->value_size);
-  atomic_add_size(&ms_stats.cmd_set, 1);
-
-  return EXIT_SUCCESS;
-} /* ms_mcd_set */
-
-
-/**
- * for ASCII protocol, this function build the get command
- * string and send the command.
- *
- * @param c, pointer of the concurrency
- * @param item, pointer of task item which includes the object
- *            information
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_build_ascii_write_buf_get(ms_conn_t *c, ms_task_item_t *item)
-{
-  if ((ms_add_iov(c, "get ", 4) != 0)
-      || (ms_add_iov(c, (char *)&item->key_prefix,
-                     (int)KEY_PREFIX_SIZE) != 0)
-      || (ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset],
-                     item->key_size - (int)KEY_PREFIX_SIZE) != 0)
-      || (ms_add_iov(c, "\r\n", 2) != 0)
-      || (c->udp && (ms_build_udp_headers(c) != 0)))
-  {
-    return -1;
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_build_ascii_write_buf_get */
-
-
-/**
- * used to send the get command to server
- *
- * @param c, pointer of the concurrency
- * @param item, pointer of task item which includes the object
- *            information
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-int ms_mcd_get(ms_conn_t *c, ms_task_item_t *item)
-{
-  assert(c != NULL);
-
-  c->currcmd.cmd= CMD_GET;
-  c->currcmd.isfinish= false;
-  c->currcmd.retstat= MCD_FAILURE;
-
-  if (ms_update_conn_sock_event(c) != 0)
-  {
-    return -1;
-  }
-
-  c->msgcurr= 0;
-  c->msgused= 0;
-  c->iovused= 0;
-  if (ms_add_msghdr(c) != 0)
-  {
-    fprintf(stderr, "Out of memory preparing request.");
-    return -1;
-  }
-
-  /* binary protocol */
-  if (c->protocol == binary_prot)
-  {
-    if (ms_build_bin_write_buf_get(c, item) != 0)
-    {
-      return -1;
-    }
-  }
-  else
-  {
-    if (ms_build_ascii_write_buf_get(c, item) != 0)
-    {
-      return -1;
-    }
-  }
-
-  atomic_add_size(&ms_stats.cmd_get, 1);
-
-  return EXIT_SUCCESS;
-} /* ms_mcd_get */
-
-
-/**
- * for ASCII protocol, this function build the multi-get command
- * string and send the command.
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_build_ascii_write_buf_mlget(ms_conn_t *c)
-{
-  ms_task_item_t *item;
-
-  if (ms_add_iov(c, "get", 3) != 0)
-  {
-    return -1;
-  }
-
-  for (int i= 0; i < c->mlget_task.mlget_num; i++)
-  {
-    item= c->mlget_task.mlget_item[i].item;
-    assert(item != NULL);
-    if ((ms_add_iov(c, " ", 1) != 0)
-        || (ms_add_iov(c, (char *)&item->key_prefix,
-                       (int)KEY_PREFIX_SIZE) != 0)
-        || (ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset],
-                       item->key_size - (int)KEY_PREFIX_SIZE) != 0))
-    {
-      return -1;
-    }
-  }
-
-  if ((ms_add_iov(c, "\r\n", 2) != 0)
-      || (c->udp && (ms_build_udp_headers(c) != 0)))
-  {
-    return -1;
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_build_ascii_write_buf_mlget */
-
-
-/**
- * used to send the multi-get command to server
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-int ms_mcd_mlget(ms_conn_t *c)
-{
-  ms_task_item_t *item;
-
-  assert(c != NULL);
-  assert(c->mlget_task.mlget_num >= 1);
-
-  c->currcmd.cmd= CMD_GET;
-  c->currcmd.isfinish= false;
-  c->currcmd.retstat= MCD_FAILURE;
-
-  if (ms_update_conn_sock_event(c) != 0)
-  {
-    return -1;
-  }
-
-  c->msgcurr= 0;
-  c->msgused= 0;
-  c->iovused= 0;
-  if (ms_add_msghdr(c) != 0)
-  {
-    fprintf(stderr, "Out of memory preparing request.");
-    return -1;
-  }
-
-  /* binary protocol */
-  if (c->protocol == binary_prot)
-  {
-    if (ms_build_bin_write_buf_mlget(c) != 0)
-    {
-      return -1;
-    }
-  }
-  else
-  {
-    if (ms_build_ascii_write_buf_mlget(c) != 0)
-    {
-      return -1;
-    }
-  }
-
-  /* decrease operation time of each item */
-  for (int i= 0; i < c->mlget_task.mlget_num; i++)
-  {
-    item= c->mlget_task.mlget_item[i].item;
-    atomic_add_size(&ms_stats.cmd_get, 1);
-  }
-
-  (void)item;
-
-  return EXIT_SUCCESS;
-} /* ms_mcd_mlget */
-
-
-/**
- * binary protocol support
- */
-
-/**
- * for binary protocol, parse the response of server
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_bin_process_response(ms_conn_t *c)
-{
-  const char *errstr= NULL;
-
-  assert(c != NULL);
-
-  uint32_t bodylen= c->binary_header.response.bodylen;
-  uint8_t  opcode= c->binary_header.response.opcode;
-  uint16_t status= c->binary_header.response.status;
-
-  if (bodylen > 0)
-  {
-    c->rvbytes= (int32_t)bodylen;
-    c->readval= true;
-    return EXIT_FAILURE;
-  }
-  else
-  {
-    switch (status)
-    {
-    case PROTOCOL_BINARY_RESPONSE_SUCCESS:
-      if (opcode == PROTOCOL_BINARY_CMD_SET)
-      {
-        c->currcmd.retstat= MCD_STORED;
-      }
-      else if (opcode == PROTOCOL_BINARY_CMD_DELETE)
-      {
-        c->currcmd.retstat= MCD_DELETED;
-      }
-      else if (opcode == PROTOCOL_BINARY_CMD_GET)
-      {
-        c->currcmd.retstat= MCD_END;
-      }
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_ENOMEM:
-      errstr= "Out of memory";
-      c->currcmd.retstat= MCD_SERVER_ERROR;
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
-      errstr= "Unknown command";
-      c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT:
-      errstr= "Not found";
-      c->currcmd.retstat= MCD_NOTFOUND;
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_EINVAL:
-      errstr= "Invalid arguments";
-      c->currcmd.retstat= MCD_PROTOCOL_ERROR;
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS:
-      errstr= "Data exists for key.";
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_E2BIG:
-      errstr= "Too large.";
-      c->currcmd.retstat= MCD_SERVER_ERROR;
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_NOT_STORED:
-      errstr= "Not stored.";
-      c->currcmd.retstat= MCD_NOTSTORED;
-      break;
-
-    default:
-      errstr= "Unknown error";
-      c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
-      break;
-    } /* switch */
-
-    if (errstr != NULL)
-    {
-      fprintf(stderr, "%s\n", errstr);
-    }
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_bin_process_response */
-
-
-/* build binary header and add the header to the buffer to send */
-
-/**
- * build binary header and add the header to the buffer to send
- *
- * @param c, pointer of the concurrency
- * @param opcode, operation code
- * @param hdr_len, length of header
- * @param key_len, length of key
- * @param body_len. length of body
- */
-static void ms_add_bin_header(ms_conn_t *c,
-                              uint8_t opcode,
-                              uint8_t hdr_len,
-                              uint16_t key_len,
-                              uint32_t body_len)
-{
-  protocol_binary_request_header *header;
-
-  assert(c != NULL);
-
-  header= (protocol_binary_request_header *)c->wcurr;
-
-  header->request.magic= (uint8_t)PROTOCOL_BINARY_REQ;
-  header->request.opcode= (uint8_t)opcode;
-  header->request.keylen= htons(key_len);
-
-  header->request.extlen= (uint8_t)hdr_len;
-  header->request.datatype= (uint8_t)PROTOCOL_BINARY_RAW_BYTES;
-  header->request.vbucket= 0;
-
-  header->request.bodylen= htonl(body_len);
-  header->request.opaque= 0;
-  header->request.cas= 0;
-
-  ms_add_iov(c, c->wcurr, sizeof(header->request));
-} /* ms_add_bin_header */
-
-
-/**
- * add the key to the socket write buffer array
- *
- * @param c, pointer of the concurrency
- * @param item, pointer of task item which includes the object
- *            information
- */
-static void ms_add_key_to_iov(ms_conn_t *c, ms_task_item_t *item)
-{
-  ms_add_iov(c, (char *)&item->key_prefix, (int)KEY_PREFIX_SIZE);
-  ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset],
-             item->key_size - (int)KEY_PREFIX_SIZE);
-}
-
-
-/**
- * for binary protocol, this function build the set command
- * and add the command to send buffer array.
- *
- * @param c, pointer of the concurrency
- * @param item, pointer of task item which includes the object
- *            information
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_build_bin_write_buf_set(ms_conn_t *c, ms_task_item_t *item)
-{
-  assert(c->wbuf == c->wcurr);
-
-  int value_offset;
-  protocol_binary_request_set *rep= (protocol_binary_request_set *)c->wcurr;
-  uint16_t keylen= (uint16_t)item->key_size;
-  uint32_t bodylen= (uint32_t)sizeof(rep->message.body)
-                    + (uint32_t)keylen + (uint32_t)item->value_size;
-
-  ms_add_bin_header(c,
-                    PROTOCOL_BINARY_CMD_SET,
-                    sizeof(rep->message.body),
-                    keylen,
-                    bodylen);
-  rep->message.body.flags= 0;
-  rep->message.body.expiration= htonl((uint32_t)item->exp_time);
-  ms_add_iov(c, &rep->message.body, sizeof(rep->message.body));
-  ms_add_key_to_iov(c, item);
-
-  if (item->value_offset == INVALID_OFFSET)
-  {
-    value_offset= item->key_suffix_offset;
-  }
-  else
-  {
-    value_offset= item->value_offset;
-  }
-  ms_add_iov(c, &ms_setting.char_block[value_offset], item->value_size);
-
-  return EXIT_SUCCESS;
-} /* ms_build_bin_write_buf_set */
-
-
-/**
- * for binary protocol, this function build the get command and
- * add the command to send buffer array.
- *
- * @param c, pointer of the concurrency
- * @param item, pointer of task item which includes the object
- *            information
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_build_bin_write_buf_get(ms_conn_t *c, ms_task_item_t *item)
-{
-  assert(c->wbuf == c->wcurr);
-
-  ms_add_bin_header(c, PROTOCOL_BINARY_CMD_GET, 0, (uint16_t)item->key_size,
-                    (uint32_t)item->key_size);
-  ms_add_key_to_iov(c, item);
-
-  return EXIT_SUCCESS;
-} /* ms_build_bin_write_buf_get */
-
-
-/**
- * for binary protocol, this function build the multi-get
- * command and add the command to send buffer array.
- *
- * @param c, pointer of the concurrency
- * @param item, pointer of task item which includes the object
- *            information
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_build_bin_write_buf_mlget(ms_conn_t *c)
-{
-  ms_task_item_t *item;
-
-  assert(c->wbuf == c->wcurr);
-
-  for (int i= 0; i < c->mlget_task.mlget_num; i++)
-  {
-    item= c->mlget_task.mlget_item[i].item;
-    assert(item != NULL);
-
-    ms_add_bin_header(c,
-                      PROTOCOL_BINARY_CMD_GET,
-                      0,
-                      (uint16_t)item->key_size,
-                      (uint32_t)item->key_size);
-    ms_add_key_to_iov(c, item);
-    c->wcurr+= sizeof(protocol_binary_request_get);
-  }
-
-  c->wcurr= c->wbuf;
-
-  return EXIT_SUCCESS;
-} /* ms_build_bin_write_buf_mlget */
diff --git a/clients/ms_conn.h b/clients/ms_conn.h
deleted file mode 100644 (file)
index 943965c..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * File:   ms_conn.h
- * Author: Mingqiang Zhuang
- *
- * Created on February 10, 2009
- *
- * (c) Copyright 2009, Schooner Information Technology, Inc.
- * http://www.schoonerinfotech.com/
- *
- */
-#ifndef MS_CONN_H
-#define MS_CONN_H
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <event.h>
-#include <netdb.h>
-
-#include "ms_task.h"
-#include <libmemcachedprotocol-0.0/binary.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define DATA_BUFFER_SIZE             (1024 * 1024 + 2048) /* read buffer, 1M + 2k, enough for the max value(1M) */
-#define WRITE_BUFFER_SIZE            (32 * 1024)          /* write buffer, 32k */
-#define UDP_DATA_BUFFER_SIZE         (1 * 1024 * 1024)    /* read buffer for UDP, 1M */
-#define UDP_MAX_PAYLOAD_SIZE         1400                 /* server limit UDP payload size */
-#define UDP_MAX_SEND_PAYLOAD_SIZE    1400                 /* mtu size is 1500 */
-#define UDP_HEADER_SIZE              8                    /* UDP header size */
-#define MAX_SENDBUF_SIZE             (256 * 1024 * 1024)  /* Maximum socket buffer size */
-#define SOCK_WAIT_TIMEOUT            30                   /* maximum waiting time of UDP, 30s */
-#define MAX_UDP_PACKET               (1 << 16)            /* maximum UDP packets, 65536 */
-
-/* Initial size of the sendmsg() scatter/gather array. */
-#define IOV_LIST_INITIAL             400
-
-/* Initial number of sendmsg() argument structures to allocate. */
-#define MSG_LIST_INITIAL             10
-
-/* High water marks for buffer shrinking */
-#define READ_BUFFER_HIGHWAT          (2 * DATA_BUFFER_SIZE)
-#define UDP_DATA_BUFFER_HIGHWAT      (4 * UDP_DATA_BUFFER_SIZE)
-#define IOV_LIST_HIGHWAT             600
-#define MSG_LIST_HIGHWAT             100
-
-/* parse udp header */
-#define HEADER_TO_REQID(ptr)      ((uint16_t)*ptr * 256 \
-                                   + (uint16_t)*(ptr + 1))
-#define HEADER_TO_SEQNUM(ptr)     ((uint16_t)*(ptr        \
-                                               + 2) * 256 \
-                                   + (uint16_t)*(ptr + 3))
-#define HEADER_TO_PACKETS(ptr)    ((uint16_t)*(ptr        \
-                                               + 4) * 256 \
-                                   + (uint16_t)*(ptr + 5))
-
-/* states of connection */
-enum conn_states
-{
-  conn_read,         /* reading in a command line */
-  conn_write,        /* writing out a simple response */
-  conn_closing      /* closing this connection */
-};
-
-/* returned states of memcached command */
-enum mcd_ret
-{
-  MCD_SUCCESS,                      /* command success */
-  MCD_FAILURE,                      /* command failure */
-  MCD_UNKNOWN_READ_FAILURE,         /* unknown read failure */
-  MCD_PROTOCOL_ERROR,               /* protocol error */
-  MCD_CLIENT_ERROR,                 /* client error, wrong command */
-  MCD_SERVER_ERROR,                 /* server error, server run command failed */
-  MCD_DATA_EXISTS,                  /* object is existent in server */
-  MCD_NOTSTORED,                    /* server doesn't set the object successfully */
-  MCD_STORED,                       /* server set the object successfully */
-  MCD_NOTFOUND,                     /* server not find the object */
-  MCD_END,                          /* end of the response of get command */
-  MCD_DELETED,                      /* server delete the object successfully */
-  MCD_STAT                         /* response of stats command */
-};
-
-/* used to store the current or previous running command state */
-typedef struct cmdstat
-{
-  int cmd;                  /* command name */
-  int retstat;              /* return state of this command */
-  bool isfinish;            /* if it read all the response data */
-  uint64_t key_prefix;      /* key prefix */
-} ms_cmdstat_t;
-
-/* udp packet structure */
-typedef struct udppkt
-{
-  uint8_t *header;          /* udp header of the packet */
-  char *data;               /* udp data of the packet */
-  int rbytes;               /* number of data in the packet */
-  int copybytes;            /* number of copied data in the packet */
-} ms_udppkt_t;
-
-/* three protocols supported */
-enum protocol
-{
-  ascii_prot = 3,           /* ASCII protocol */
-  binary_prot              /* binary protocol */
-};
-
-/**
- *  concurrency structure
- *
- *  Each thread has a libevent to manage the events of network.
- *  Each thread has one or more self-governed concurrencies;
- *  each concurrency has one or more socket connections. This
- *  concurrency structure includes all the private variables of
- *  the concurrency.
- */
-typedef struct conn
-{
-  uint32_t conn_idx;             /* connection index in the thread */
-  int sfd;                  /* current tcp sock handler of the connection structure */
-  int udpsfd;               /* current udp sock handler of the connection structure*/
-  int state;                /* state of the connection */
-  struct event event;       /* event for libevent */
-  short ev_flags;           /* event flag for libevent */
-  short which;              /* which events were just triggered */
-  bool change_sfd;          /* whether change sfd */
-
-  int *tcpsfd;              /* TCP sock array */
-  uint32_t total_sfds;           /* how many socks in the tcpsfd array */
-  uint32_t alive_sfds;           /* alive socks */
-  uint32_t cur_idx;              /* current sock index in tcpsfd array */
-
-  ms_cmdstat_t precmd;      /* previous command state */
-  ms_cmdstat_t currcmd;     /* current command state */
-
-  char *rbuf;               /* buffer to read commands into */
-  char *rcurr;              /* but if we parsed some already, this is where we stopped */
-  int rsize;                /* total allocated size of rbuf */
-  int rbytes;               /* how much data, starting from rcur, do we have unparsed */
-
-  bool readval;             /* read value state, read known data size */
-  int rvbytes;              /* total value size need to read */
-
-  char *wbuf;               /* buffer to write commands out */
-  char *wcurr;              /* for multi-get, where we stopped */
-  int wsize;                /* total allocated size of wbuf */
-  bool ctnwrite;            /* continue to write */
-
-  /* data for the mwrite state */
-  struct iovec *iov;
-  int iovsize;              /* number of elements allocated in iov[] */
-  int iovused;              /* number of elements used in iov[] */
-
-  struct msghdr *msglist;
-  int msgsize;              /* number of elements allocated in msglist[] */
-  int msgused;              /* number of elements used in msglist[] */
-  int msgcurr;              /* element in msglist[] being transmitted now */
-  int msgbytes;             /* number of bytes in current msg */
-
-  /* data for UDP clients */
-  bool udp;                          /* is this is a UDP "connection" */
-  uint32_t request_id;                   /* UDP request ID of current operation, if this is a UDP "connection" */
-  uint8_t *hdrbuf;                  /* udp packet headers */
-  int hdrsize;                      /* number of headers' worth of space is allocated */
-  struct  sockaddr srv_recv_addr;   /* Sent the most recent request to which server */
-  socklen_t srv_recv_addr_size;
-
-  /* udp read buffer */
-  char *rudpbuf;                    /* buffer to read commands into for udp */
-  int rudpsize;                     /* total allocated size of rudpbuf */
-  int rudpbytes;                    /* how much data, starting from rudpbuf */
-
-  /* order udp packet */
-  ms_udppkt_t *udppkt;              /* the offset of udp packet in rudpbuf */
-  int packets;                      /* number of total packets need to read */
-  int recvpkt;                      /* number of received packets */
-  int pktcurr;                      /* current packet in rudpbuf being ordered */
-  int ordcurr;                      /* current ordered packet */
-
-  ms_task_item_t *item_win;         /* task sequence */
-  int win_size;                     /* current task window size */
-  uint64_t set_cursor;              /* current set item index in the item window */
-  ms_task_t curr_task;              /* current running task */
-  ms_mlget_task_t mlget_task;       /* multi-get task */
-
-  int warmup_num;                   /* to run how many warm up operations*/
-  int remain_warmup_num;            /* left how many warm up operations to run */
-  int64_t exec_num;                 /* to run how many task operations */
-  int64_t remain_exec_num;          /* how many remained task operations to run */
-
-  /* response time statistic and time out control */
-  struct timeval start_time;        /* start time of current operation(s) */
-  struct timeval end_time;          /* end time of current operation(s) */
-
-  /* Binary protocol stuff */
-  protocol_binary_response_header binary_header;    /* local temporary binary header */
-  enum protocol protocol;                           /* which protocol this connection speaks */
-} ms_conn_t;
-
-/* used to generate the key prefix */
-uint64_t ms_get_key_prefix(void);
-
-
-/**
- * setup a connection, each connection structure of each
- * thread must call this function to initialize.
- */
-int ms_setup_conn(ms_conn_t *c);
-
-
-/* after one operation completes, reset the connection */
-void ms_reset_conn(ms_conn_t *c, bool timeout);
-
-
-/**
- *  reconnect several disconnected socks in the connection
- *  structure, the ever-1-second timer of the thread will check
- *  whether some socks in the connections disconnect. if
- *  disconnect, reconnect the sock.
- */
-int ms_reconn_socks(ms_conn_t *c);
-
-
-/* used to send set command to server */
-int ms_mcd_set(ms_conn_t *c, ms_task_item_t *item);
-
-
-/* used to send the get command to server */
-int ms_mcd_get(ms_conn_t *c, ms_task_item_t *item);
-
-
-/* used to send the multi-get command to server */
-int ms_mcd_mlget(ms_conn_t *c);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* end of MS_CONN_H */
diff --git a/clients/ms_memslap.h b/clients/ms_memslap.h
deleted file mode 100644 (file)
index 9575a81..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * File:   ms_memslap.h
- * Author: Mingqiang Zhuang
- *
- * Created on February 10, 2009
- *
- * (c) Copyright 2009, Schooner Information Technology, Inc.
- * http://www.schoonerinfotech.com/
- *
- */
-#ifndef MS_MEMSLAP_H
-#define MS_MEMSLAP_H
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <assert.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <pthread.h>
-#if !defined(__cplusplus)
-# include <stdbool.h>
-#endif
-#include <math.h>
-
-#include "ms_stats.h"
-#include "ms_atomic.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* command line option  */
-typedef enum
-{
-  OPT_VERSION= 'V',
-  OPT_HELP= 'h',
-  OPT_UDP= 'U',
-  OPT_SERVERS= 's',
-  OPT_EXECUTE_NUMBER= 'x',
-  OPT_THREAD_NUMBER= 'T',
-  OPT_CONCURRENCY= 'c',
-  OPT_FIXED_LTH= 'X',
-  OPT_VERIFY= 'v',
-  OPT_GETS_DIVISION= 'd',
-  OPT_TIME= 't',
-  OPT_CONFIG_CMD= 'F',
-  OPT_WINDOW_SIZE= 'w',
-  OPT_EXPIRE= 'e',
-  OPT_STAT_FREQ= 'S',
-  OPT_RECONNECT= 'R',
-  OPT_VERBOSE= 'b',
-  OPT_FACEBOOK_TEST= 'a',
-  OPT_SOCK_PER_CONN= 'n',
-  OPT_BINARY_PROTOCOL= 'B',
-  OPT_OVERWRITE= 'o',
-  OPT_TPS= 'P',
-  OPT_REP_WRITE_SRV= 'p'
-} ms_options_t;
-
-/* global statistic of response time */
-typedef struct statistic
-{
-  pthread_mutex_t stat_mutex;       /* synchronize the following members */
-
-  ms_stat_t get_stat;               /* statistics of get command */
-  ms_stat_t set_stat;               /* statistics of set command */
-  ms_stat_t total_stat;             /* statistics of both get and set commands */
-} ms_statistic_t;
-
-/* global status statistic structure */
-typedef struct stats
-{
-  ATOMIC uint32_t active_conns;   /* active connections */
-  ATOMIC size_t bytes_read;       /* read bytes */
-  ATOMIC size_t bytes_written;    /* written bytes */
-  ATOMIC size_t obj_bytes;        /* object bytes */
-  ATOMIC size_t pre_cmd_get;      /* previous total get command count */
-  ATOMIC size_t pre_cmd_set;      /* previous total set command count */
-  ATOMIC size_t cmd_get;          /* current total get command count */
-  ATOMIC size_t cmd_set;          /* current total set command count */
-  ATOMIC size_t get_misses;       /* total objects of get miss */
-  ATOMIC size_t vef_miss;         /* total objects of verification miss  */
-  ATOMIC size_t vef_failed;       /* total objects of verification failed  */
-  ATOMIC size_t unexp_unget;      /* total objects which is unexpired but not get */
-  ATOMIC size_t exp_get;          /* total objects which is expired but get  */
-  ATOMIC size_t pkt_disorder;     /* disorder packages of UDP */
-  ATOMIC size_t pkt_drop;         /* packages dropped of UDP */
-  ATOMIC size_t udp_timeout;      /* how many times timeout of UDP happens */
-} ms_stats_t;
-
-/* lock adapter */
-typedef struct sync_lock
-{
-  uint32_t count;
-  pthread_mutex_t lock;
-  pthread_cond_t cond;
-} ms_sync_lock_t;
-
-/* global variable structure */
-typedef struct global
-{
-  /* synchronize lock */
-  ms_sync_lock_t init_lock;
-  ms_sync_lock_t warmup_lock;
-  ms_sync_lock_t run_lock;
-
-  /* mutex for outputing error log synchronously when memslap crashes */
-  pthread_mutex_t quit_mutex;
-
-  /* mutex for generating key prefix */
-  pthread_mutex_t seq_mutex;
-
-  /* global synchronous flags for slap mode */
-  bool finish_warmup;
-  bool time_out;
-} ms_global_t;
-
-/* global structure */
-ms_global_t ms_global;
-
-/* global stats information structure */
-ms_stats_t ms_stats;
-
-/* global statistic structure */
-ms_statistic_t ms_statistic;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* end of MS_MEMSLAP_H */
diff --git a/clients/ms_setting.c b/clients/ms_setting.c
deleted file mode 100644 (file)
index eafe459..0000000
+++ /dev/null
@@ -1,1068 +0,0 @@
-/*
- * File:   ms_setting.c
- * Author: Mingqiang Zhuang
- *
- * Created on February 10, 2009
- *
- * (c) Copyright 2009, Schooner Information Technology, Inc.
- * http://www.schoonerinfotech.com/
- *
- */
-
-#include "mem_config.h"
-
-#include <libmemcached/memcached.h>
-
-#include <ctype.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <pwd.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-
-
-#include "ms_setting.h"
-#include "ms_conn.h"
-
-#define MAX_EXEC_NUM               0x4000000000000000      /* 1 << 62 */
-#define ADDR_ALIGN(addr)    ((addr + 15) & ~(16 - 1))      /* 16 bytes aligned */
-#define RAND_CHAR_SIZE             (10 * 1024 * 1024)      /* 10M character table */
-#define RESERVED_RAND_CHAR_SIZE    (2 * 1024 * 1024)       /* reserved 2M to avoid pointer sloping over */
-
-#define DEFAULT_CONFIG_NAME ".memslap.cnf"
-
-#define DEFAULT_THREADS_NUM        1                       /* default start one thread */
-#define DEFAULT_CONNS_NUM          16                      /* default each thread with 16 connections */
-#define DEFAULT_EXE_NUM            0                       /* default execute number is 0 */
-#define DEFAULT_VERIFY_RATE        0.0                     /* default it doesn't do data verification */
-#define DEFAULT_OVERWRITE_RATE     0.0                     /* default it doesn't do overwrite */
-#define DEFAULT_DIV                1                       /* default it runs single get */
-#define DEFAULT_RUN_TIME           600                     /* default run time 10 minutes */
-#define DEFAULT_WINDOW_SIZE        (10 * UNIT_ITEMS_COUNT) /* default window size is 10k */
-#define DEFAULT_SOCK_PER_CONN      1                       /* default socks per connection is 1 */
-
-/* Use this for string generation */
-#define CHAR_COUNT                 64 /* number of characters used to generate character table */
-const char ALPHANUMBERICS[]=
-  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-";
-
-ms_setting_st ms_setting;       /* store the settings specified by user */
-
-
-/* read setting from configuration file */
-static void ms_get_serverlist(char *str);
-static uint32_t ms_get_cpu_count(void);
-ms_conf_type_t ms_get_conf_type(char *line);
-static int ms_is_line_data(char *line);
-static int ms_read_is_data(char *line, ssize_t nread);
-static void ms_no_config_file(void);
-static void ms_parse_cfg_file(char *cfg_file);
-
-
-/* initialize setting structure */
-static void ms_init_random_block(void);
-static void ms_calc_avg_size(void);
-static int ms_shuffle_distr(ms_distr_t *distr, int length);
-static void ms_build_distr(void);
-static void ms_print_setting(void);
-static void ms_setting_slapmode_init_pre(void);
-static void ms_setting_slapmode_init_post(void);
-
-#if !defined(HAVE_GETLINE)
-#include <limits.h>
-static ssize_t getline (char **line, size_t *line_size, FILE *fp)
-{
-  char delim= '\n';
-  ssize_t result= 0;
-  size_t cur_len= 0;
-
-  if (line == NULL || line_size == NULL || fp == NULL)
-  {
-    errno = EINVAL;
-    return -1;
-  }
-
-  if (*line == NULL || *line_size == 0)
-  {
-    char *new_line;
-    *line_size = 120;
-    new_line= (char *) realloc (*line, *line_size);
-    if (new_line == NULL)
-    {
-      result= -1;
-      return result;
-    }
-    *line= new_line;
-  }
-
-  for (;;)
-  {
-    int i= getc(fp);
-    if (i == EOF)
-    {
-      result = -1;
-      break;
-    }
-
-    /* Make enough space for len+1 (for final NUL) bytes.  */
-    if (cur_len + 1 >= *line_size)
-    {
-      size_t needed_max=
-        SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
-      size_t needed= (2 * (*line_size)) + 1;
-      char *new_line;
-
-      if (needed_max < needed)
-        needed= needed_max;
-      if (cur_len + 1 >= needed)
-      {
-        result= -1;
-        errno= EOVERFLOW;
-        return result;
-      }
-
-      new_line= (char *)realloc(*line, needed);
-      if (new_line == NULL)
-      {
-        result= -1;
-        return result;
-      }
-
-      *line= new_line;
-      *line_size= needed;
-    }
-
-    (*line)[cur_len]= (char)i;
-    cur_len++;
-
-    if (i == delim)
-      break;
-  }
-  (*line)[cur_len] = '\0';
-  if (cur_len != 0)
-    return (ssize_t)cur_len;
-  return result;
-}
-#endif
-
-/**
- * parse the server list string, and build the servers
- * information structure array. this function is used to parse
- * the command line options specified by user.
- *
- * @param str, the string of server list
- */
-static void ms_get_serverlist(char *str)
-{
-  ms_mcd_server_t *srvs= NULL;
-
-  /**
-   * Servers list format is like this. For example:
-   * "localhost:11108, localhost:11109"
-   */
-  memcached_server_st *server_pool;
-  server_pool = memcached_servers_parse(str);
-
-  for (uint32_t loop= 0; loop < memcached_server_list_count(server_pool); loop++)
-  {
-    assert(ms_setting.srv_cnt < ms_setting.total_srv_cnt);
-    strcpy(ms_setting.servers[ms_setting.srv_cnt].srv_host_name, server_pool[loop].hostname);
-    ms_setting.servers[ms_setting.srv_cnt].srv_port= server_pool[loop].port;
-    ms_setting.servers[ms_setting.srv_cnt].disconn_cnt= 0;
-    ms_setting.servers[ms_setting.srv_cnt].reconn_cnt= 0;
-    ms_setting.srv_cnt++;
-
-    if (ms_setting.srv_cnt >= ms_setting.total_srv_cnt)
-    {
-      srvs= (ms_mcd_server_t *)realloc( ms_setting.servers,
-                                        (size_t)ms_setting.total_srv_cnt * sizeof(ms_mcd_server_t) * 2);
-      if (srvs == NULL)
-      {
-        fprintf(stderr, "Can't reallocate servers structure.\n");
-        exit(1);
-      }
-      ms_setting.servers= srvs;
-      ms_setting.total_srv_cnt*= 2;
-    }
-  }
-
-  memcached_server_free(server_pool);
-} /* ms_get_serverlist */
-
-
-/**
- * used to get the CPU count of the current system
- *
- * @return return the cpu count if get, else return EXIT_FAILURE
- */
-static uint32_t ms_get_cpu_count()
-{
-#ifdef HAVE__SC_NPROCESSORS_ONLN
-  return sysconf(_SC_NPROCESSORS_CONF);
-
-#else
-# ifdef HAVE_CPU_SET_T
-  int cpu_count= 0;
-  cpu_set_t cpu_set;
-
-  sched_getaffinity(0, sizeof(cpu_set_t), &cpu_set);
-
-  for (int i= 0; i < (sizeof(cpu_set_t) * 8); i++)
-  {
-    if (CPU_ISSET(i, &cpu_set))
-    {
-      cpu_count++;
-    }
-  }
-
-  return cpu_count;
-
-# endif
-#endif
-
-  /* the system with one cpu at least */
-  return EXIT_FAILURE;
-} /* ms_get_cpu_count */
-
-
-/**
- * used to get the configure type based on the type string read
- * from the configuration file.
- *
- * @param line, string of one line
- *
- * @return ms_conf_type_t
- */
-ms_conf_type_t ms_get_conf_type(char *line)
-{
-  if (! memcmp(line, "key", strlen("key")))
-  {
-    return CONF_KEY;
-  }
-  else if (! memcmp(line, "value", strlen("value")))
-  {
-    return CONF_VALUE;
-  }
-  else if (! memcmp(line, "cmd", strlen("cmd")))
-  {
-    return CONF_CMD;
-  }
-  else
-  {
-    return CONF_NULL;
-  }
-} /* ms_get_conf_type */
-
-
-/**
- * judge whether the line is a line with useful data. used to
- * parse the configuration file.
- *
- * @param line, string of one line
- *
- * @return if success, return EXIT_FAILURE, else return EXIT_SUCCESS
- */
-static int ms_is_line_data(char *line)
-{
-  assert(line != NULL);
-
-  char *begin_ptr= line;
-
-  while (isspace(*begin_ptr))
-  {
-    begin_ptr++;
-  }
-  if ((begin_ptr[0] == '\0') || (begin_ptr[0] == '#'))
-    return EXIT_SUCCESS;
-
-  return EXIT_FAILURE;
-} /* ms_is_line_data */
-
-
-/**
- * function to bypass blank line and comments
- *
- * @param line, string of one line
- * @param nread, length of the line
- *
- * @return if it's EOF or not line data, return EXIT_SUCCESS, else return EXIT_FAILURE
- */
-static int ms_read_is_data(char *line, ssize_t nread)
-{
-  if ((nread == EOF) || ! ms_is_line_data(line))
-    return EXIT_SUCCESS;
-
-  return EXIT_FAILURE;
-} /* ms_read_is_data */
-
-
-/**
- *  if no configuration file, use this function to create the default
- *  configuration file.
- */
-static void ms_no_config_file()
-{
-  char userpath[PATH_MAX];
-  struct passwd *usr= NULL;
-  FILE *fd;
-
-  usr= getpwuid(getuid());
-
-  snprintf(userpath, PATH_MAX, "%s/%s", usr->pw_dir, DEFAULT_CONFIG_NAME);
-
-  if (access (userpath, F_OK | R_OK) == 0)
-    goto exit;
-
-  fd= fopen(userpath, "w+");
-
-  if (fd == NULL)
-  {
-    fprintf(stderr, "Could not create default configure file %s\n", userpath);
-    perror(strerror(errno));
-    exit(1);
-  }
-  fprintf(fd, "%s", DEFAULT_CONGIF_STR);
-  fclose(fd);
-
-exit:
-  ms_setting.cfg_file= strdup(userpath);
-} /* ms_no_config_file */
-
-
-/**
- * parse the configuration file
- *
- * @param cfg_file, the configuration file name
- */
-static void ms_parse_cfg_file(char *cfg_file)
-{
-  FILE *f;
-  size_t start_len, end_len;
-  double proportion;
-  char *line= NULL;
-  size_t  read_len;
-  ssize_t nread;
-  int cmd_type;
-  ms_conf_type_t conf_type;
-  int end_of_file= 0;
-  ms_key_distr_t *key_distr= NULL;
-  ms_value_distr_t *val_distr= NULL;
-
-  if (cfg_file == NULL)
-  {
-    ms_no_config_file();
-    cfg_file= ms_setting.cfg_file;
-  }
-
-  /*read key value configure file*/
-  if ((f= fopen(cfg_file, "r")) == NULL)
-  {
-    fprintf(stderr, "Can not open file: '%s'.\n", cfg_file);
-    exit(1);
-  }
-
-  while (1)
-  {
-    if ((((nread= getline(&line, &read_len, f)) == 1)
-         || ! ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */
-      continue;
-
-    if (nread == EOF)
-    {
-      fprintf(stderr, "Bad configuration file, no configuration find.\n");
-      exit(1);
-    }
-    conf_type= ms_get_conf_type(line);
-    break;
-  }
-
-  while (! end_of_file)
-  {
-    switch (conf_type)
-    {
-    case CONF_KEY:
-      while (1)
-      {
-        if ((((nread= getline(&line, &read_len, f)) == 1)
-             || ! ms_read_is_data(line, nread)) && (nread != EOF))     /* bypass blank line */
-          continue;
-
-        if (nread != EOF)
-        {
-          if (sscanf(line, "%zu %zu %lf ", &start_len,
-                     &end_len, &proportion) != 3)
-          {
-            conf_type= ms_get_conf_type(line);
-            break;
-          }
-          ms_setting.key_distr[ms_setting.key_rng_cnt].start_len= start_len;
-          ms_setting.key_distr[ms_setting.key_rng_cnt].end_len= end_len;
-          ms_setting.key_distr[ms_setting.key_rng_cnt].key_prop= proportion;
-          ms_setting.key_rng_cnt++;
-
-          if (ms_setting.key_rng_cnt >= ms_setting.total_key_rng_cnt)
-          {
-            key_distr= (ms_key_distr_t *)realloc(
-              ms_setting.key_distr,
-              (size_t)ms_setting.
-                 total_key_rng_cnt * sizeof(ms_key_distr_t) * 2);
-            if (key_distr == NULL)
-            {
-              fprintf(stderr,
-                      "Can't reallocate key distribution structure.\n");
-              exit(1);
-            }
-            ms_setting.key_distr= key_distr;
-            ms_setting.total_key_rng_cnt*= 2;
-          }
-          continue;
-        }
-        end_of_file= 1;
-        break;
-      }
-      break;
-
-    case CONF_VALUE:
-      while (1)
-      {
-        if ((((nread= getline(&line, &read_len, f)) == 1)
-             || ! ms_read_is_data(line, nread)) && (nread != EOF))     /* bypass blank line */
-          continue;
-
-        if (nread != EOF)
-        {
-          if (sscanf(line, "%zu %zu %lf", &start_len, &end_len,
-                     &proportion) != 3)
-          {
-            conf_type= ms_get_conf_type(line);
-            break;
-          }
-          ms_setting.value_distr[ms_setting.val_rng_cnt].start_len=
-            start_len;
-          ms_setting.value_distr[ms_setting.val_rng_cnt].end_len= end_len;
-          ms_setting.value_distr[ms_setting.val_rng_cnt].value_prop=
-            proportion;
-          ms_setting.val_rng_cnt++;
-
-          if (ms_setting.val_rng_cnt >= ms_setting.total_val_rng_cnt)
-          {
-            val_distr= (ms_value_distr_t *)realloc(
-              ms_setting.value_distr,
-              (size_t)ms_setting.
-                 total_val_rng_cnt * sizeof(ms_value_distr_t) * 2);
-            if (val_distr == NULL)
-            {
-              fprintf(stderr,
-                      "Can't reallocate key distribution structure.\n");
-              exit(1);
-            }
-            ms_setting.value_distr= val_distr;
-            ms_setting.total_val_rng_cnt*= 2;
-          }
-          continue;
-        }
-        end_of_file= 1;
-        break;
-      }
-      break;
-
-    case CONF_CMD:
-      while (1)
-      {
-        if ((((nread= getline(&line, &read_len, f)) == 1)
-             || ! ms_read_is_data(line, nread)) && (nread != EOF))     /* bypass blank line */
-          continue;
-
-        if (nread != EOF)
-        {
-          if (sscanf(line, "%d %lf", &cmd_type, &proportion) != 2)
-          {
-            conf_type= ms_get_conf_type(line);
-            break;
-          }
-          if (cmd_type >= CMD_NULL)
-          {
-            continue;
-          }
-          ms_setting.cmd_distr[ms_setting.cmd_used_count].cmd_type=
-            cmd_type;
-          ms_setting.cmd_distr[ms_setting.cmd_used_count].cmd_prop=
-            proportion;
-          ms_setting.cmd_used_count++;
-          continue;
-        }
-        end_of_file= 1;
-        break;
-      }
-
-    case CONF_NULL:
-      while (1)
-      {
-        if ((((nread= getline(&line, &read_len, f)) == 1)
-             || ! ms_read_is_data(line, nread)) && (nread != EOF))     /* bypass blank line */
-          continue;
-
-        if (nread != EOF)
-        {
-          if ((conf_type= ms_get_conf_type(line)) != CONF_NULL)
-          {
-            break;
-          }
-          continue;
-        }
-        end_of_file= 1;
-        break;
-      }
-      break;
-
-    default:
-      assert(0);
-      break;
-    } /* switch */
-  }
-
-  fclose(f);
-
-  if (line != NULL)
-  {
-    free(line);
-  }
-} /* ms_parse_cfg_file */
-
-
-/* calculate the average size of key and value */
-static void ms_calc_avg_size()
-{
-  double avg_val_size= 0.0;
-  double avg_key_size= 0.0;
-  double val_pro= 0.0;
-  double key_pro= 0.0;
-  double averge_len= 0.0;
-  size_t start_len= 0;
-  size_t end_len= 0;
-
-  for (int j= 0; j < ms_setting.val_rng_cnt; j++)
-  {
-    val_pro= ms_setting.value_distr[j].value_prop;
-    start_len= ms_setting.value_distr[j].start_len;
-    end_len= ms_setting.value_distr[j].end_len;
-
-    averge_len= val_pro * ((double)(start_len + end_len)) / 2;
-    avg_val_size+= averge_len;
-  }
-
-  for (int j= 0; j < ms_setting.key_rng_cnt; j++)
-  {
-    key_pro= ms_setting.key_distr[j].key_prop;
-    start_len= ms_setting.key_distr[j].start_len;
-    end_len= ms_setting.key_distr[j].end_len;
-
-    averge_len= key_pro * ((double)(start_len + end_len)) / 2;
-    avg_key_size+= averge_len;
-  }
-
-  ms_setting.avg_val_size= (size_t)avg_val_size;
-  ms_setting.avg_key_size= (size_t)avg_key_size;
-} /* ms_calc_avg_size */
-
-
-/**
- * used to shuffle key and value distribution array to ensure
- * (key, value) pair with different set.
- *
- * @param distr, pointer of distribution structure array
- * @param length, length of the array
- *
- * @return always return EXIT_SUCCESS
- */
-static int ms_shuffle_distr(ms_distr_t *distr, int length)
-{
-  int i, j;
-  int tmp_offset;
-  size_t  tmp_size;
-  int64_t rnd;
-
-  for (i= 0; i < length; i++)
-  {
-    rnd= random();
-    j= (int)(rnd % (length - i)) + i;
-
-    switch (rnd % 3)
-    {
-    case 0:
-      tmp_size= distr[j].key_size;
-      distr[j].key_size= distr[i].key_size;
-      distr[i].key_size= tmp_size;
-      break;
-
-    case 1:
-      tmp_offset= distr[j].key_offset;
-      distr[j].key_offset= distr[i].key_offset;
-      distr[i].key_offset= tmp_offset;
-      break;
-
-    case 2:
-      tmp_size= distr[j].value_size;
-      distr[j].value_size= distr[i].value_size;
-      distr[i].value_size= tmp_size;
-      break;
-
-    default:
-      break;
-    } /* switch */
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_shuffle_distr */
-
-
-/**
- * according to the key and value distribution, to build the
- * (key, value) pair distribution. the (key, value) pair
- * distribution array is global, each connection set or get
- * object keeping this distribution, for the final result, we
- * can reach the expected key and value distribution.
- */
-static void ms_build_distr()
-{
-  int offset= 0;
-  int end= 0;
-  int key_cnt= 0;
-  int value_cnt= 0;
-  size_t average_len= 0;
-  size_t diff_len= 0;
-  size_t start_len= 0;
-  size_t end_len= 0;
-  int rnd= 0;
-  ms_distr_t *distr= NULL;
-  int units= (int)ms_setting.win_size / UNIT_ITEMS_COUNT;
-
-  /* calculate average value size and key size */
-  ms_calc_avg_size();
-
-  ms_setting.char_blk_size= RAND_CHAR_SIZE;
-  int key_scope_size=
-    (int)((ms_setting.char_blk_size - RESERVED_RAND_CHAR_SIZE)
-          / UNIT_ITEMS_COUNT);
-
-  ms_setting.distr= (ms_distr_t *)malloc(
-    sizeof(ms_distr_t) * ms_setting.win_size);
-  if (ms_setting.distr == NULL)
-  {
-    fprintf(stderr, "Can't allocate distribution array.");
-    exit(1);
-  }
-
-  /**
-   *  character block is divided by how many different key
-   *  size, each different key size has the same size character
-   *  range.
-   */
-  for (int m= 0; m < units; m++)
-  {
-    for (int i= 0; i < UNIT_ITEMS_COUNT; i++)
-    {
-      ms_setting.distr[m * UNIT_ITEMS_COUNT + i].key_offset=
-        ADDR_ALIGN(key_scope_size * i);
-    }
-  }
-
-  /* initialize key size distribution */
-  for (int m= 0; m < units; m++)
-  {
-    for (int j= 0; j < ms_setting.key_rng_cnt; j++)
-    {
-      key_cnt= (int)(UNIT_ITEMS_COUNT * ms_setting.key_distr[j].key_prop);
-      start_len= ms_setting.key_distr[j].start_len;
-      end_len= ms_setting.key_distr[j].end_len;
-      if ((start_len < MIN_KEY_SIZE) || (end_len < MIN_KEY_SIZE))
-      {
-        fprintf(stderr, "key length must be greater than 16 bytes.\n");
-        exit(1);
-      }
-
-      if (! ms_setting.binary_prot_
-          && ((start_len > MAX_KEY_SIZE) || (end_len > MAX_KEY_SIZE)))
-      {
-        fprintf(stderr, "key length must be less than 250 bytes.\n");
-        exit(1);
-      }
-
-      average_len= (start_len + end_len) / 2;
-      diff_len= (end_len - start_len) / 2;
-      for (int k= 0; k < key_cnt; k++)
-      {
-        if (offset >= (m + 1) * UNIT_ITEMS_COUNT)
-        {
-          break;
-        }
-        rnd= (int)random();
-        if (k % 2 == 0)
-        {
-          ms_setting.distr[offset].key_size=
-            (diff_len == 0) ? average_len :
-            average_len + (size_t)rnd
-            % diff_len;
-        }
-        else
-        {
-          ms_setting.distr[offset].key_size=
-            (diff_len == 0) ? average_len :
-            average_len - (size_t)rnd
-            % diff_len;
-        }
-        offset++;
-      }
-    }
-
-    if (offset < (m + 1) * UNIT_ITEMS_COUNT)
-    {
-      end= (m + 1) * UNIT_ITEMS_COUNT - offset;
-      for (int i= 0; i < end; i++)
-      {
-        ms_setting.distr[offset].key_size= ms_setting.avg_key_size;
-        offset++;
-      }
-    }
-  }
-  offset= 0;
-
-  /* initialize value distribution */
-  if (ms_setting.fixed_value_size != 0)
-  {
-    for (int i= 0; i < units * UNIT_ITEMS_COUNT; i++)
-    {
-      ms_setting.distr[i].value_size= ms_setting.fixed_value_size;
-    }
-  }
-  else
-  {
-    for (int m= 0; m < units; m++)
-    {
-      for (int j= 0; j < ms_setting.val_rng_cnt; j++)
-      {
-        value_cnt=
-          (int)(UNIT_ITEMS_COUNT * ms_setting.value_distr[j].value_prop);
-        start_len= ms_setting.value_distr[j].start_len;
-        end_len= ms_setting.value_distr[j].end_len;
-        if ((start_len <= 0) || (end_len <= 0))
-        {
-          fprintf(stderr, "value length must be greater than 0 bytes.\n");
-          exit(1);
-        }
-
-        if ((start_len > MAX_VALUE_SIZE) || (end_len > MAX_VALUE_SIZE))
-        {
-          fprintf(stderr, "key length must be less than or equal to 1M.\n");
-          exit(1);
-        }
-
-        average_len= (start_len + end_len) / 2;
-        diff_len= (end_len - start_len) / 2;
-        for (int k= 0; k < value_cnt; k++)
-        {
-          if (offset >= (m + 1) * UNIT_ITEMS_COUNT)
-          {
-            break;
-          }
-          rnd= (int)random();
-          if (k % 2 == 0)
-          {
-            ms_setting.distr[offset].value_size=
-              (diff_len == 0) ? average_len :
-              average_len
-              + (size_t)rnd % diff_len;
-          }
-          else
-          {
-            ms_setting.distr[offset].value_size=
-              (diff_len == 0) ? average_len :
-              average_len
-              - (size_t)rnd % diff_len;
-          }
-          offset++;
-        }
-      }
-
-      if (offset < (m + 1) * UNIT_ITEMS_COUNT)
-      {
-        end= (m + 1) * UNIT_ITEMS_COUNT - offset;
-        for (int i= 0; i < end; i++)
-        {
-          ms_setting.distr[offset++].value_size= ms_setting.avg_val_size;
-        }
-      }
-    }
-  }
-
-  /* shuffle distribution */
-  for (int i= 0; i < units; i++)
-  {
-    distr= &ms_setting.distr[i * UNIT_ITEMS_COUNT];
-    for (int j= 0; j < 4; j++)
-    {
-      ms_shuffle_distr(distr, UNIT_ITEMS_COUNT);
-    }
-  }
-} /* ms_build_distr */
-
-
-/**
- * used to initialize the global character block. The character
- * block is used to generate the suffix of the key and value. we
- * only store a pointer in the character block for each key
- * suffix or value string. It can save much memory to store key
- * or value string.
- */
-static void ms_init_random_block()
-{
-  char *ptr= NULL;
-
-  assert(ms_setting.char_blk_size > 0);
-
-  ms_setting.char_block= (char *)malloc(ms_setting.char_blk_size);
-  if (ms_setting.char_block == NULL)
-  {
-    fprintf(stderr, "Can't allocate global char block.");
-    exit(1);
-  }
-  ptr= ms_setting.char_block;
-
-  for (int i= 0; (size_t)i < ms_setting.char_blk_size; i++)
-  {
-    *(ptr++)= ALPHANUMBERICS[random() % CHAR_COUNT];
-  }
-} /* ms_init_random_block */
-
-
-/**
- * after initialization, call this function to output the main
- * configuration user specified.
- */
-static void ms_print_setting()
-{
-  fprintf(stdout, "servers : %s\n", ms_setting.srv_str);
-  fprintf(stdout, "threads count: %d\n", ms_setting.nthreads);
-  fprintf(stdout, "concurrency: %d\n", ms_setting.nconns);
-  if (ms_setting.run_time > 0)
-  {
-    fprintf(stdout, "run time: %ds\n", ms_setting.run_time);
-  }
-  else
-  {
-    fprintf(stdout, "execute number: %" PRId64 "\n", ms_setting.exec_num);
-  }
-  fprintf(stdout, "windows size: %" PRId64 "k\n",
-          (int64_t)(ms_setting.win_size / 1024));
-  fprintf(stdout, "set proportion: set_prop=%.2f\n",
-          ms_setting.cmd_distr[CMD_SET].cmd_prop);
-  fprintf(stdout, "get proportion: get_prop=%.2f\n",
-          ms_setting.cmd_distr[CMD_GET].cmd_prop);
-  fflush(stdout);
-} /* ms_print_setting */
-
-
-/**
- * previous part of slap mode initialization of setting structure
- */
-static void ms_setting_slapmode_init_pre()
-{
-  ms_setting.exec_num= DEFAULT_EXE_NUM;
-  ms_setting.verify_percent= DEFAULT_VERIFY_RATE;
-  ms_setting.exp_ver_per= DEFAULT_VERIFY_RATE;
-  ms_setting.overwrite_percent= DEFAULT_OVERWRITE_RATE;
-  ms_setting.mult_key_num= DEFAULT_DIV;
-  ms_setting.fixed_value_size= 0;
-  ms_setting.win_size= DEFAULT_WINDOW_SIZE;
-  ms_setting.udp= false;
-  ms_setting.reconnect= false;
-  ms_setting.verbose= false;
-  ms_setting.facebook_test= false;
-  ms_setting.binary_prot_= false;
-  ms_setting.stat_freq= 0;
-  ms_setting.srv_str= NULL;
-  ms_setting.cfg_file= NULL;
-  ms_setting.sock_per_conn= DEFAULT_SOCK_PER_CONN;
-  ms_setting.expected_tps= 0;
-  ms_setting.rep_write_srv= 0;
-} /* ms_setting_slapmode_init_pre */
-
-
-/**
- * previous part of initialization of setting structure
- */
-void ms_setting_init_pre()
-{
-  memset(&ms_setting, 0, sizeof(ms_setting));
-
-  /* common initialize */
-  ms_setting.ncpu= ms_get_cpu_count();
-  ms_setting.nthreads= DEFAULT_THREADS_NUM;
-  ms_setting.nconns= DEFAULT_CONNS_NUM;
-  ms_setting.run_time= DEFAULT_RUN_TIME;
-  ms_setting.total_srv_cnt= MCD_SRVS_NUM_INIT;
-  ms_setting.servers= (ms_mcd_server_t *)malloc(
-    (size_t)ms_setting.total_srv_cnt
-    * sizeof(ms_mcd_server_t));
-  if (ms_setting.servers == NULL)
-  {
-    fprintf(stderr, "Can't allocate servers structure.\n");
-    exit(1);
-  }
-
-  ms_setting_slapmode_init_pre();
-} /* ms_setting_init_pre */
-
-
-/**
- * post part of slap mode initialization of setting structure
- */
-static void ms_setting_slapmode_init_post()
-{
-  ms_setting.total_key_rng_cnt= KEY_RANGE_COUNT_INIT;
-  ms_setting.key_distr=
-    (ms_key_distr_t *)malloc((size_t)ms_setting.total_key_rng_cnt * sizeof(ms_key_distr_t));
-
-  if (ms_setting.key_distr == NULL)
-  {
-    fprintf(stderr, "Can't allocate key distribution structure.\n");
-    exit(1);
-  }
-
-  ms_setting.total_val_rng_cnt= VALUE_RANGE_COUNT_INIT;
-
-  ms_setting.value_distr=
-    (ms_value_distr_t *)malloc((size_t)ms_setting.total_val_rng_cnt * sizeof( ms_value_distr_t));
-
-  if (ms_setting.value_distr == NULL)
-  {
-    fprintf(stderr, "Can't allocate value distribution structure.\n");
-    exit(1);
-  }
-
-  ms_parse_cfg_file(ms_setting.cfg_file);
-
-  /* run time mode */
-  if ((ms_setting.exec_num == 0) && (ms_setting.run_time != 0))
-  {
-    ms_setting.exec_num= (int64_t)MAX_EXEC_NUM;
-  }
-  else
-  {
-    /* execute number mode */
-    ms_setting.run_time= 0;
-  }
-
-  if (ms_setting.rep_write_srv > 0)
-  {
-    /* for replication test, need enable reconnect feature */
-    ms_setting.reconnect= true;
-  }
-
-  if (ms_setting.facebook_test && (ms_setting.mult_key_num < 2))
-  {
-    fprintf(stderr, "facebook test must work with multi-get, "
-                    "please specify multi-get key number "
-                    "with '--division' option.\n");
-    exit(1);
-  }
-
-  if (ms_setting.facebook_test && ms_setting.udp)
-  {
-    fprintf(stderr, "facebook test couldn't work with UDP.\n");
-    exit(1);
-  }
-
-  if (ms_setting.udp && (ms_setting.sock_per_conn > 1))
-  {
-    fprintf(stderr, "UDP doesn't support multi-socks "
-                    "in one connection structure.\n");
-    exit(1);
-  }
-
-  if ((ms_setting.rep_write_srv > 0) && (ms_setting.srv_cnt < 2))
-  {
-    fprintf(stderr, "Please specify 2 servers at least for replication\n");
-    exit(1);
-  }
-
-  if ((ms_setting.rep_write_srv > 0)
-      && (ms_setting.srv_cnt < ms_setting.rep_write_srv))
-  {
-    fprintf(stderr, "Servers to do replication writing "
-                    "is larger than the total servers\n");
-    exit(1);
-  }
-
-  if (ms_setting.udp && (ms_setting.rep_write_srv > 0))
-  {
-    fprintf(stderr, "UDP doesn't support replication.\n");
-    exit(1);
-  }
-
-  if (ms_setting.facebook_test && (ms_setting.rep_write_srv > 0))
-  {
-    fprintf(stderr, "facebook test couldn't work with replication.\n");
-    exit(1);
-  }
-
-  ms_build_distr();
-
-  /* initialize global character block */
-  ms_init_random_block();
-  ms_print_setting();
-} /* ms_setting_slapmode_init_post */
-
-
-/**
- * post part of initialization of setting structure
- */
-void ms_setting_init_post()
-{
-  ms_get_serverlist(ms_setting.srv_str);
-  ms_setting_slapmode_init_post();
-}
-
-
-/**
- * clean up the global setting structure
- */
-void ms_setting_cleanup()
-{
-  if (ms_setting.distr != NULL)
-  {
-    free(ms_setting.distr);
-  }
-
-  if (ms_setting.char_block != NULL)
-  {
-    free(ms_setting.char_block);
-  }
-
-  if (ms_setting.srv_str != NULL)
-  {
-    free(ms_setting.srv_str);
-  }
-
-  if (ms_setting.cfg_file != NULL)
-  {
-    free(ms_setting.cfg_file);
-  }
-
-  if (ms_setting.servers != NULL)
-  {
-    free(ms_setting.servers);
-  }
-
-  if (ms_setting.key_distr != NULL)
-  {
-    free(ms_setting.key_distr);
-  }
-
-  if (ms_setting.value_distr != NULL)
-  {
-    free(ms_setting.value_distr);
-  }
-} /* ms_setting_cleanup */
diff --git a/clients/ms_setting.h b/clients/ms_setting.h
deleted file mode 100644 (file)
index 9db956c..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * File:   ms_setting.h
- * Author: Mingqiang Zhuang
- *
- * Created on February 10, 2009
- *
- * (c) Copyright 2009, Schooner Information Technology, Inc.
- * http://www.schoonerinfotech.com/
- *
- */
-#ifndef MS_SETTING_H
-#define MS_SETTING_H
-
-#include "ms_memslap.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define MCD_SRVS_NUM_INIT         8
-#define MCD_HOST_LENGTH           64
-#define KEY_RANGE_COUNT_INIT      8
-#define VALUE_RANGE_COUNT_INIT    8
-#define PROP_ERROR                0.001
-
-#define MIN_KEY_SIZE              16
-#define MAX_KEY_SIZE              250
-#define MAX_VALUE_SIZE            (1024 * 1024)
-
-/* the content of the configuration file for memslap running without configuration file */
-#define DEFAULT_CONGIF_STR \
-  "key\n"                  \
-  "64 64 1\n"              \
-  "value\n"                \
-  "1024 1024 1\n"          \
-  "cmd\n"                  \
-  "0 0.1\n"                \
-  "1 0.9"
-
-/* Used to parse the value length return by server and path string */
-typedef struct token_s
-{
-  char *value;
-  size_t length;
-} token_t;
-
-#define MAX_TOKENS    10
-
-/* server information */
-typedef struct mcd_server
-{
-  char srv_host_name[MCD_HOST_LENGTH];              /* host name of server */
-  int srv_port;                                     /* server port */
-
-  /* for calculating how long the server disconnects */
-  ATOMIC uint32_t disconn_cnt;                    /* number of disconnections count */
-  ATOMIC uint32_t reconn_cnt;                     /* number of reconnections count */
-  struct timeval disconn_time;                      /* start time of disconnection */
-  struct timeval reconn_time;                       /* end time of reconnection */
-} ms_mcd_server_t;
-
-/* information of an item distribution including key and value */
-typedef struct distr
-{
-  size_t key_size;                  /* size of key */
-  int key_offset;                   /* offset of one key in character block */
-  size_t value_size;                /* size of value */
-} ms_distr_t;
-
-/* information of key distribution */
-typedef struct key_distr
-{
-  size_t start_len;                 /* start of the key length range */
-  size_t end_len;                   /* end of the key length range */
-  double key_prop;                  /* key proportion */
-} ms_key_distr_t;
-
-/* information of value distribution */
-typedef struct value_distr
-{
-  size_t start_len;                 /* start of the value length range */
-  size_t end_len;                   /* end of the value length range */
-  double value_prop;                /* value proportion */
-} ms_value_distr_t;
-
-/* memcached command types */
-typedef enum cmd_type
-{
-  CMD_SET,
-  CMD_GET,
-  CMD_NULL
-} ms_cmd_type_t;
-
-/* types in the configuration file */
-typedef enum conf_type
-{
-  CONF_KEY,
-  CONF_VALUE,
-  CONF_CMD,
-  CONF_NULL
-} ms_conf_type_t;
-
-/* information of command distribution */
-typedef struct cmd_distr
-{
-  ms_cmd_type_t cmd_type;               /* command type */
-  double cmd_prop;                      /* proportion of the command */
-} ms_cmd_distr_t;
-
-/* global setting structure */
-typedef struct setting
-{
-  uint32_t ncpu;                             /* cpu count of this system */
-  uint32_t nthreads;                         /* total thread count, must equal or less than cpu cores */
-  uint32_t nconns;                      /* total conn count, must multiply by total thread count */
-  int64_t exec_num;                     /* total execute number */
-  int run_time;                         /* total run time */
-
-  uint32_t char_blk_size;               /* global character block size */
-  char *char_block;                     /* global character block with random character */
-  ms_distr_t *distr;                    /* distribution from configure file */
-
-  char *srv_str;                        /* string includes servers information */
-  char *cfg_file;                       /* configure file name */
-
-  ms_mcd_server_t *servers;             /* servers array */
-  uint32_t total_srv_cnt;                    /* total servers count of the servers array */
-  uint32_t srv_cnt;                          /* servers count */
-
-  ms_key_distr_t *key_distr;            /* array of key distribution */
-  int total_key_rng_cnt;                /* total key range count of the array */
-  int key_rng_cnt;                      /* actual key range count */
-
-  ms_value_distr_t *value_distr;        /* array of value distribution */
-  int total_val_rng_cnt;                /* total value range count of the array */
-  int val_rng_cnt;                      /* actual value range count */
-
-  ms_cmd_distr_t cmd_distr[CMD_NULL];   /* total we have CMD_NULL commands */
-  int cmd_used_count;                   /* supported command count */
-
-  size_t fixed_value_size;              /* fixed value size */
-  size_t avg_val_size;                  /* average value size */
-  size_t avg_key_size;                  /* average value size */
-
-  double verify_percent;                /* percent of data verification */
-  double exp_ver_per;                   /* percent of data verification with expire time */
-  double overwrite_percent;             /* percent of overwrite */
-  int mult_key_num;                     /* number of keys used by multi-get once */
-  size_t win_size;                      /* item window size per connection */
-  bool udp;                             /* whether or not use UDP */
-  int stat_freq;                        /* statistic frequency second */
-  bool reconnect;                       /* whether it reconnect when connection close */
-  bool verbose;                         /* whether it outputs detailed information when verification */
-  bool facebook_test;                   /* facebook test, TCP set and multi-get with UDP */
-  uint32_t sock_per_conn;                    /* number of socks per connection structure */
-  bool binary_prot_;                     /* whether it use binary protocol */
-  int expected_tps;                     /* expected throughput */
-  uint32_t rep_write_srv;                    /* which servers are used to do replication writing */
-} ms_setting_st;
-
-extern ms_setting_st ms_setting;
-
-/* previous part of initialization of setting structure */
-void ms_setting_init_pre(void);
-
-
-/* post part of initialization of setting structure */
-void ms_setting_init_post(void);
-
-
-/* clean up the global setting structure */
-void ms_setting_cleanup(void);
-
-
-#define UNUSED_ARGUMENT(x)    (void)x
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* end of MS_SETTING_H */
diff --git a/clients/ms_sigsegv.c b/clients/ms_sigsegv.c
deleted file mode 100644 (file)
index 303381f..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * File:   ms_sigsegv.c
- * Author: Mingqiang Zhuang
- *
- * Created on March 15, 2009
- *
- * (c) Copyright 2009, Schooner Information Technology, Inc.
- * http://www.schoonerinfotech.com/
- *
- * Rewrite of stack dump:
- *  Copyright (C) 2009 Sun Microsystems
- *  Author Trond Norbye
- */
-
-#include "mem_config.h"
-
-#include <memory.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <signal.h>
-#include <pthread.h>
-
-#include "ms_memslap.h"
-#include "ms_setting.h"
-
-/* prototypes */
-int ms_setup_sigsegv(void);
-int ms_setup_sigpipe(void);
-int ms_setup_sigint(void);
-
-
-/* signal seg reaches, this function will run */
-static void ms_signal_segv(int signum, siginfo_t *info, void *ptr)
-{
-  UNUSED_ARGUMENT(signum);
-  UNUSED_ARGUMENT(info);
-  UNUSED_ARGUMENT(ptr);
-
-  pthread_mutex_lock(&ms_global.quit_mutex);
-  fprintf(stderr, "Segmentation fault occurred.\nStack trace:\n");
-#if 0
-  pandora_print_callstack(stderr);
-#endif
-  fprintf(stderr, "End of stack trace\n");
-  pthread_mutex_unlock(&ms_global.quit_mutex);
-  abort();
-}
-
-/* signal int reaches, this function will run */
-static void ms_signal_int(int signum, siginfo_t *info, void *ptr)
-{
-  UNUSED_ARGUMENT(signum);
-  UNUSED_ARGUMENT(info);
-  UNUSED_ARGUMENT(ptr);
-
-  pthread_mutex_lock(&ms_global.quit_mutex);
-  fprintf(stderr, "SIGINT handled.\n");
-  pthread_mutex_unlock(&ms_global.quit_mutex);
-  exit(1);
-} /* ms_signal_int */
-
-
-/**
- * redirect signal seg
- *
- * @return if success, return EXIT_SUCCESS, else return -1
- */
-int ms_setup_sigsegv(void)
-{
-  struct sigaction action;
-
-  memset(&action, 0, sizeof(action));
-  action.sa_sigaction= ms_signal_segv;
-  action.sa_flags= SA_SIGINFO;
-  if (sigaction(SIGSEGV, &action, NULL) < 0)
-  {
-    perror("sigaction");
-    return EXIT_SUCCESS;
-  }
-
-  return -1;
-} /* ms_setup_sigsegv */
-
-
-/**
- * redirect signal pipe
- *
- * @return if success, return EXIT_SUCCESS, else return -1
- */
-int ms_setup_sigpipe(void)
-{
-  /* ignore the SIGPIPE signal */
-  signal(SIGPIPE, SIG_IGN);
-
-  return -1;
-} /* ms_setup_sigpipe */
-
-
-/**
- * redirect signal int
- *
- * @return if success, return EXIT_SUCCESS, else return -1
- */
-int ms_setup_sigint(void)
-{
-  struct sigaction action_3;
-
-  memset(&action_3, 0, sizeof(action_3));
-  action_3.sa_sigaction= ms_signal_int;
-  action_3.sa_flags= SA_SIGINFO;
-  if (sigaction(SIGINT, &action_3, NULL) < 0)
-  {
-    perror("sigaction");
-    return EXIT_SUCCESS;
-  }
-
-  return -1;
-} /* ms_setup_sigint */
-
-
-#ifndef SIGSEGV_NO_AUTO_INIT
-static void __attribute((constructor)) ms_init(void)
-{
-  ms_setup_sigsegv();
-  ms_setup_sigpipe();
-  ms_setup_sigint();
-}
-#endif
diff --git a/clients/ms_sigsegv.h b/clients/ms_sigsegv.h
deleted file mode 100644 (file)
index 7990ff6..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * File:   ms_sigsegv.h
- * Author: Mingqiang Zhuang
- *
- * Created on March 15, 2009
- *
- * (c) Copyright 2009, Schooner Information Technology, Inc.
- * http://www.schoonerinfotech.com/
- *
- */
-#ifndef MS_SIGSEGV_H
-#define MS_SIGSEGV_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* redirect signal seg */
-int ms_setup_sigsegv(void);
-
-
-/* redirect signal pipe */
-int ms_setup_sigpipe(void);
-
-
-/* redirect signal int */
-int ms_setup_sigint(void);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* end of MS_SIGSEGV_H */
diff --git a/clients/ms_stats.c b/clients/ms_stats.c
deleted file mode 100644 (file)
index 086fb3e..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * File:   ms_stats.h
- * Author: Mingqiang Zhuang
- *
- * Created on March 25, 2009
- *
- * (c) Copyright 2009, Schooner Information Technology, Inc.
- * http://www.schoonerinfotech.com/
- *
- */
-
-#include "mem_config.h"
-
-#include <inttypes.h>
-#include "ms_stats.h"
-
-#define array_size(x)    (sizeof(x) / sizeof((x)[0]))
-
-static int ms_local_log2(uint64_t value);
-static uint64_t ms_get_events(ms_stat_t *stat);
-
-
-/**
- * get the index of local log2 array
- *
- * @param value
- *
- * @return return the index of local log2 array
- */
-static int ms_local_log2(uint64_t value)
-{
-  int result= 0;
-
-  while (result <= 63 && ((uint64_t)1 << result) < value)
-  {
-    result++;
-  }
-
-  return result;
-} /* ms_local_log2 */
-
-
-/**
- * initialize statistic structure
- *
- * @param stat, pointer of the statistic structure
- * @param name, name of the statistic
- */
-void ms_init_stats(ms_stat_t *stat, const char *name)
-{
-  memset(stat, 0, sizeof(*stat));
-
-  stat->name= (char *)name;
-  stat->min_time= (uint64_t)-1;
-  stat->max_time= 0;
-  stat->period_min_time= (uint64_t)-1;
-  stat->period_max_time= 0;
-  stat->log_product= 0;
-  stat->total_time= 0;
-  stat->pre_total_time= 0;
-  stat->squares= 0;
-  stat->pre_squares= 0;
-  stat->pre_events= 0;
-  stat->pre_log_product= 0;
-  stat->get_miss= 0;
-  stat->pre_get_miss= 0;
-} /* ms_init_stats */
-
-
-/**
- * record one event
- *
- * @param stat, pointer of the statistic structure
- * @param total_time, response time of the command
- * @param get_miss, whether it gets miss
- */
-void ms_record_event(ms_stat_t *stat, uint64_t total_time, int get_miss)
-{
-  stat->total_time+= total_time;
-
-  if (total_time < stat->min_time)
-  {
-    stat->min_time= total_time;
-  }
-
-  if (total_time > stat->max_time)
-  {
-    stat->max_time= total_time;
-  }
-
-  if (total_time < stat->period_min_time)
-  {
-    stat->period_min_time= total_time;
-  }
-
-  if (total_time > stat->period_max_time)
-  {
-    stat->period_max_time= total_time;
-  }
-
-  if (get_miss)
-  {
-    stat->get_miss++;
-  }
-
-  stat->dist[ms_local_log2(total_time)]++;
-  stat->squares+= (double)(total_time * total_time);
-
-  if (total_time != 0)
-  {
-    stat->log_product+= log((double)total_time);
-  }
-} /* ms_record_event */
-
-
-/**
- * get the events count
- *
- * @param stat, pointer of the statistic structure
- *
- * @return total events recorded
- */
-static uint64_t ms_get_events(ms_stat_t *stat)
-{
-  uint64_t events= 0;
-
-  for (uint32_t i= 0; i < array_size(stat->dist); i++)
-  {
-    events+= stat->dist[i];
-  }
-
-  return events;
-} /* ms_get_events */
-
-
-/**
- * dump the statistics
- *
- * @param stat, pointer of the statistic structure
- */
-void ms_dump_stats(ms_stat_t *stat)
-{
-  uint64_t events= 0;
-  int max_non_zero= 0;
-  int min_non_zero= 0;
-  double average= 0;
-
-  for (uint32_t i= 0; i < array_size(stat->dist); i++)
-  {
-    events+= stat->dist[i];
-    if (stat->dist[i] != 0)
-    {
-      max_non_zero= (int)i;
-    }
-  }
-
-  if (events == 0)
-  {
-    return;
-  }
-  average= (double)(stat->total_time / events);
-
-  printf("%s Statistics (%lld events)\n", stat->name, (long long)events);
-  printf("   Min:  %8lld\n", (long long)stat->min_time);
-  printf("   Max:  %8lld\n", (long long)stat->max_time);
-  printf("   Avg:  %8lld\n", (long long)(stat->total_time / events));
-  printf("   Geo:  %8.2lf\n", exp(stat->log_product / (double)events));
-
-  if (events > 1)
-  {
-    printf("   Std:  %8.2lf\n",
-           sqrt((stat->squares - (double)events * average
-                 * average) / ((double)events - 1)));
-  }
-  printf("   Log2 Dist:");
-
-  for (int i= 0; i <= max_non_zero - 4; i+= 4)
-  {
-    if ((stat->dist[i + 0] != 0)
-        || (stat->dist[i + 1] != 0)
-        || (stat->dist[i + 2] != 0)
-        || (stat->dist[i + 3] != 0))
-    {
-      min_non_zero= i;
-      break;
-    }
-  }
-
-  for (int i= min_non_zero; i <= max_non_zero; i++)
-  {
-    if ((i % 4) == 0)
-    {
-      printf("\n      %2d:", (int)i);
-    }
-    printf("   %6" PRIu64 , stat->dist[i]);
-  }
-
-  printf("\n\n");
-} /* ms_dump_stats */
-
-
-/**
- * dump the format statistics
- *
- * @param stat, pointer of the statistic structure
- * @param run_time, the total run time
- * @param freq, statistic frequency
- * @param obj_size, average object size
- */
-void ms_dump_format_stats(ms_stat_t *stat,
-                          int run_time,
-                          int freq,
-                          int obj_size)
-{
-  uint64_t events= 0;
-  double global_average= 0;
-  uint64_t global_tps= 0;
-  double global_rate= 0;
-  double global_std= 0;
-  double global_log= 0;
-
-  double period_average= 0;
-  uint64_t period_tps= 0;
-  double period_rate= 0;
-  double period_std= 0;
-  double period_log= 0;
-
-  if ((events= ms_get_events(stat)) == 0)
-  {
-    return;
-  }
-
-  global_average= (double)(stat->total_time / events);
-  global_tps= events / (uint64_t)run_time;
-  global_rate= (double)events * obj_size / 1024 / 1024 / run_time;
-  global_std= sqrt((stat->squares - (double)events * global_average
-                    * global_average) / (double)(events - 1));
-  global_log= exp(stat->log_product / (double)events);
-
-  uint64_t diff_time= stat->total_time - stat->pre_total_time;
-  uint64_t diff_events= events - stat->pre_events;
-  if (diff_events >= 1)
-  {
-    period_average= (double)(diff_time / diff_events);
-    period_tps= diff_events / (uint64_t)freq;
-    period_rate= (double)diff_events * obj_size / 1024 / 1024 / freq;
-    double diff_squares= (double)stat->squares - (double)stat->pre_squares;
-    period_std= sqrt((diff_squares - (double)diff_events * period_average
-                      * period_average) / (double)(diff_events - 1));
-    double diff_log_product= stat->log_product - stat->pre_log_product;
-    period_log= exp(diff_log_product / (double)diff_events);
-  }
-
-  printf("%s Statistics\n", stat->name);
-  printf("%-8s %-8s %-12s %-12s %-10s %-10s %-8s %-10s %-10s %-10s %-10s\n",
-         "Type",
-         "Time(s)",
-         "Ops",
-         "TPS(ops/s)",
-         "Net(M/s)",
-         "Get_miss",
-         "Min(us)",
-         "Max(us)",
-         "Avg(us)",
-         "Std_dev",
-         "Geo_dist");
-
-  printf(
-    "%-8s %-8d %-12llu %-12lld %-10.1f %-10lld %-8lld %-10lld %-10lld %-10.2f %.2f\n",
-    "Period",
-    freq,
-    (long long)diff_events,
-    (long long)period_tps,
-    global_rate,
-    (long long)(stat->get_miss - stat->pre_get_miss),
-    (long long)stat->period_min_time,
-    (long long)stat->period_max_time,
-    (long long)period_average,
-    period_std,
-    period_log);
-
-  printf(
-    "%-8s %-8d %-12llu %-12lld %-10.1f %-10lld %-8lld %-10lld %-10lld %-10.2f %.2f\n\n",
-    "Global",
-    run_time,
-    (long long)events,
-    (long long)global_tps,
-    period_rate,
-    (long long)stat->get_miss,
-    (long long)stat->min_time,
-    (long long)stat->max_time,
-    (long long)global_average,
-    global_std,
-    global_log);
-
-  stat->pre_events= events;
-  stat->pre_squares= (uint64_t)stat->squares;
-  stat->pre_total_time= stat->total_time;
-  stat->pre_log_product= stat->log_product;
-  stat->period_min_time= (uint64_t)-1;
-  stat->period_max_time= 0;
-  stat->pre_get_miss= stat->get_miss;
-} /* ms_dump_format_stats */
diff --git a/clients/ms_stats.h b/clients/ms_stats.h
deleted file mode 100644 (file)
index 5ac88b3..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * File:   ms_stats.h
- * Author: Mingqiang Zhuang
- *
- * Created on March 25, 2009
- *
- * (c) Copyright 2009, Schooner Information Technology, Inc.
- * http://www.schoonerinfotech.com/
- *
- */
-#ifndef MS_STAT_H
-#define MS_STAT_H
-
-#include <math.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* statistic structure of response time */
-typedef struct
-{
-  char *name;
-  uint64_t total_time;
-  uint64_t min_time;
-  uint64_t max_time;
-  uint64_t get_miss;
-  uint64_t dist[65];
-  double squares;
-  double log_product;
-
-  uint64_t period_min_time;
-  uint64_t period_max_time;
-  uint64_t pre_get_miss;
-  uint64_t pre_events;
-  uint64_t pre_total_time;
-  uint64_t pre_squares;
-  double pre_log_product;
-} ms_stat_t;
-
-/* initialize statistic */
-void ms_init_stats(ms_stat_t *stat, const char *name);
-
-
-/* record one event */
-void ms_record_event(ms_stat_t *stat, uint64_t time, int get_miss);
-
-
-/* dump the statistics */
-void ms_dump_stats(ms_stat_t *stat);
-
-
-/* dump the format statistics */
-void ms_dump_format_stats(ms_stat_t *stat,
-                          int run_time,
-                          int freq,
-                          int obj_size);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif  /* MS_STAT_H */
diff --git a/clients/ms_task.c b/clients/ms_task.c
deleted file mode 100644 (file)
index f2cb865..0000000
+++ /dev/null
@@ -1,1110 +0,0 @@
-/*
- * File:   ms_task.c
- * Author: Mingqiang Zhuang
- *
- * Created on February 10, 2009
- *
- * (c) Copyright 2009, Schooner Information Technology, Inc.
- * http://www.schoonerinfotech.com/
- *
- */
-
-#include "mem_config.h"
-
-#if defined(HAVE_SYS_TIME_H)
-# include <sys/time.h>
-#endif
-
-#if defined(HAVE_TIME_H)
-# include <time.h>
-#endif
-
-#include "ms_thread.h"
-#include "ms_setting.h"
-#include "ms_atomic.h"
-
-/* command distribution adjustment cycle */
-#define CMD_DISTR_ADJUST_CYCLE    1000
-#define DISADJUST_FACTOR          0.03 /**
-                                 * In one adjustment cycle, if undo set or get
-                                 * operations proportion is more than 3% , means
-                                 * there are too many new item or need more new
-                                 * item in the window. This factor shows it.
-                                 */
-
-/* get item from task window */
-static ms_task_item_t *ms_get_cur_opt_item(ms_conn_t *c);
-static ms_task_item_t *ms_get_next_get_item(ms_conn_t *c);
-static ms_task_item_t *ms_get_next_set_item(ms_conn_t *c);
-static ms_task_item_t *ms_get_random_overwrite_item(ms_conn_t *c);
-
-
-/* select next operation to do */
-static void ms_select_opt(ms_conn_t *c, ms_task_t *task);
-
-
-/* set and get speed estimate for controlling and adjustment */
-static bool ms_is_set_too_fast(ms_task_t *task);
-static bool ms_is_get_too_fast(ms_task_t *task);
-static void ms_kick_out_item(ms_task_item_t *item);
-
-
-/* miss rate adjustment */
-static bool ms_need_overwrite_item(ms_task_t *task);
-static bool ms_adjust_opt(ms_conn_t *c, ms_task_t *task);
-
-
-/* deal with data verification initialization */
-static void ms_task_data_verify_init(ms_task_t *task);
-static void ms_task_expire_verify_init(ms_task_t *task);
-
-
-/* select a new task to do */
-static ms_task_t *ms_get_task(ms_conn_t *c, bool warmup);
-
-
-/* run the selected task */
-static void ms_update_set_result(ms_conn_t *c, ms_task_item_t *item);
-static void ms_update_stat_result(ms_conn_t *c);
-static void ms_update_multi_get_result(ms_conn_t *c);
-static void ms_update_single_get_result(ms_conn_t *c, ms_task_item_t *item);
-static void ms_update_task_result(ms_conn_t *c);
-static void ms_single_getset_task_sch(ms_conn_t *c);
-static void ms_multi_getset_task_sch(ms_conn_t *c);
-static void ms_send_signal(ms_sync_lock_t *sync_lock);
-static void ms_warmup_server(ms_conn_t *c);
-static int ms_run_getset_task(ms_conn_t *c);
-
-
-/**
- * used to get the current operation item(object)
- *
- * @param c, pointer of the concurrency
- *
- * @return ms_task_item_t*, current operating item
- */
-static ms_task_item_t *ms_get_cur_opt_item(ms_conn_t *c)
-{
-  return c->curr_task.item;
-}
-
-
-/**
- * used to get the next item to do get operation
- *
- * @param c, pointer of the concurrency
- *
- * @return ms_task_item_t*, the pointer of the next item to do
- *         get operation
- */
-static ms_task_item_t *ms_get_next_get_item(ms_conn_t *c)
-{
-  ms_task_item_t *item= NULL;
-
-  if (c->set_cursor <= 0)
-  {
-    /* the first item in the window */
-    item= &c->item_win[0];
-  }
-  else if (c->set_cursor > 0 && c->set_cursor < (uint32_t)c->win_size)
-  {
-    /* random get one item set before */
-    item= &c->item_win[random() % (int64_t)c->set_cursor];
-  }
-  else
-  {
-    /* random get one item from the window */
-    item= &c->item_win[random() % c->win_size];
-  }
-
-  return item;
-} /* ms_get_next_get_item */
-
-
-/**
- * used to get the next item to do set operation
- *
- * @param c, pointer of the concurrency
- *
- * @return ms_task_item_t*, the pointer of the next item to do
- *         set operation
- */
-static ms_task_item_t *ms_get_next_set_item(ms_conn_t *c)
-{
-  /**
-   *  when a set command successes, the cursor will plus 1. If set
-   *  fails, the cursor doesn't change. it isn't necessary to
-   *  increase the cursor here.
-   */
-  return &c->item_win[(int64_t)c->set_cursor % c->win_size];
-}
-
-
-/**
- * If we need do overwrite, we could select a item set before.
- * This function is used to get a item set before to do
- * overwrite.
- *
- * @param c, pointer of the concurrency
- *
- * @return ms_task_item_t*, the pointer of the previous item of
- *         set operation
- */
-static ms_task_item_t *ms_get_random_overwrite_item(ms_conn_t *c)
-{
-    return ms_get_next_get_item(c);
-} /* ms_get_random_overwrite_item */
-
-/**
- * According to the proportion of operations(get or set), select
- * an operation to do.
- *
- * @param c, pointer of the concurrency
- * @param task, pointer of current task in the concurrency
- */
-static void ms_select_opt(ms_conn_t *c, ms_task_t *task)
-{
-  double get_prop= ms_setting.cmd_distr[CMD_GET].cmd_prop;
-  double set_prop= ms_setting.cmd_distr[CMD_SET].cmd_prop;
-
-  /* update cycle operation number if necessary */
-  if ((task->cycle_undo_get == 0) || (task->cycle_undo_set == 0))
-  {
-    task->cycle_undo_get+= (int)(CMD_DISTR_ADJUST_CYCLE * get_prop);
-    task->cycle_undo_set+= (int)(CMD_DISTR_ADJUST_CYCLE * set_prop);
-  }
-
-  /**
-   *  According to operation distribution to choose doing which
-   *  operation. If it can't set new object to sever, just change
-   *  to do get operation.
-   */
-  if ((set_prop > PROP_ERROR)
-      && ((double)task->get_opt * set_prop >= (double)task->set_opt
-          * get_prop))
-  {
-    task->cmd= CMD_SET;
-    task->item= ms_get_next_set_item(c);
-  }
-  else
-  {
-    task->cmd= CMD_GET;
-    task->item= ms_get_next_get_item(c);
-  }
-} /* ms_select_opt */
-
-
-/**
- * used to judge whether the number of get operations done is
- * more than expected number of get operations to do right now.
- *
- * @param task, pointer of current task in the concurrency
- *
- * @return bool, if get too fast, return true, else return false
- */
-static bool ms_is_get_too_fast(ms_task_t *task)
-{
-  double get_prop= ms_setting.cmd_distr[CMD_GET].cmd_prop;
-  double set_prop= ms_setting.cmd_distr[CMD_SET].cmd_prop;
-
-  /* no get operation */
-  if (get_prop < PROP_ERROR)
-  {
-    return false;
-  }
-
-  int max_undo_set= (int)(set_prop / get_prop * (1.0 + DISADJUST_FACTOR))
-                    * task->cycle_undo_get;
-
-  if (((double)task->get_opt * set_prop > (double)task->set_opt * get_prop)
-      && (task->cycle_undo_set > max_undo_set))
-  {
-    return true;
-  }
-
-  return false;
-} /* ms_is_get_too_fast */
-
-
-/**
- * used to judge whether the number of set operations done is
- * more than expected number of set operations to do right now.
- *
- * @param task, pointer of current task in the concurrency
- *
- * @return bool, if set too fast, return true, else return false
- */
-static bool ms_is_set_too_fast(ms_task_t *task)
-{
-  double get_prop= ms_setting.cmd_distr[CMD_GET].cmd_prop;
-  double set_prop= ms_setting.cmd_distr[CMD_SET].cmd_prop;
-
-  /* no set operation */
-  if (set_prop < PROP_ERROR)
-  {
-    return false;
-  }
-
-  /* If it does set operation too fast, skip some */
-  int max_undo_get= (int)((get_prop / set_prop * (1.0 + DISADJUST_FACTOR))
-                          * (double)task->cycle_undo_set);
-
-  if (((double)task->get_opt * set_prop < (double)task->set_opt * get_prop)
-      && (task->cycle_undo_get > max_undo_get))
-  {
-    return true;
-  }
-
-  return false;
-} /* ms_is_set_too_fast */
-
-
-/**
- * kick out the old item in the window, and add a new item to
- * overwrite the old item. When we don't want to do overwrite
- * object, and the current item to do set operation is an old
- * item, we could kick out the old item and add a new item. Then
- * we can ensure we set new object every time.
- *
- * @param item, pointer of task item which includes the object
- *            information
- */
-static void ms_kick_out_item(ms_task_item_t *item)
-{
-  /* allocate a new item */
-  item->key_prefix= ms_get_key_prefix();
-
-  item->key_suffix_offset++;
-  item->value_offset= INVALID_OFFSET;       /* new item use invalid value offset */
-  item->client_time= 0;
-} /* ms_kick_out_item */
-
-
-/**
- *  used to judge whether we need overwrite object based on the
- *  options user specified
- *
- * @param task, pointer of current task in the concurrency
- *
- * @return bool, if need overwrite, return true, else return
- *         false
- */
-static bool ms_need_overwrite_item(ms_task_t *task)
-{
-  ms_task_item_t *item= task->item;
-
-  assert(item != NULL);
-  assert(task->cmd == CMD_SET);
-
-  /**
-   *  according to data overwrite percent to determine if do data
-   *  overwrite.
-   */
-  if (task->overwrite_set < (double)task->set_opt
-      * ms_setting.overwrite_percent)
-  {
-    return true;
-  }
-
-  return false;
-} /* ms_need_overwirte_item */
-
-
-/**
- * used to adjust operation. the function must be called after
- * select operation. the function change get operation to set
- * operation, or set operation to get operation based on the
- * current case.
- *
- * @param c, pointer of the concurrency
- * @param task, pointer of current task in the concurrency
- *
- * @return bool, if success, return true, else return false
- */
-static bool ms_adjust_opt(ms_conn_t *c, ms_task_t *task)
-{
-  ms_task_item_t *item= task->item;
-
-  assert(item != NULL);
-
-  if (task->cmd == CMD_SET)
-  {
-    /* If did set operation too fast, skip some */
-    if (ms_is_set_too_fast(task))
-    {
-      /* get the item instead */
-      if (item->value_offset != INVALID_OFFSET)
-      {
-        task->cmd= CMD_GET;
-        return true;
-      }
-    }
-
-    /* If the current item is not a new item, kick it out */
-    if (item->value_offset != INVALID_OFFSET)
-    {
-      if (ms_need_overwrite_item(task))
-      {
-        /* overwrite */
-        task->overwrite_set++;
-      }
-      else
-      {
-        /* kick out the current item to do set operation */
-        ms_kick_out_item(item);
-      }
-    }
-    else            /* it's a new item */
-    {
-      /* need overwrite */
-      if (ms_need_overwrite_item(task))
-      {
-        /**
-         *  overwrite not use the item with current set cursor, revert
-         *  set cursor.
-         */
-        c->set_cursor--;
-
-        item= ms_get_random_overwrite_item(c);
-        if (item->value_offset != INVALID_OFFSET)
-        {
-          task->item= item;
-          task->overwrite_set++;
-        }
-        else                /* item is a new item */
-        {
-          /* select the item to run, and cancel overwrite */
-          task->item= item;
-        }
-      }
-    }
-    task->cmd= CMD_SET;
-    return true;
-  }
-  else
-  {
-    if (item->value_offset == INVALID_OFFSET)
-    {
-      task->cmd= CMD_SET;
-      return true;
-    }
-
-    /**
-     *  If It does get operation too fast, it will change the
-     *  operation to set.
-     */
-    if (ms_is_get_too_fast(task))
-    {
-      /* don't kick out the first item in the window */
-      if (! ms_is_set_too_fast(task))
-      {
-        ms_kick_out_item(item);
-        task->cmd= CMD_SET;
-        return true;
-      }
-      else
-      {
-        return false;
-      }
-    }
-
-    assert(item->value_offset != INVALID_OFFSET);
-
-    task->cmd= CMD_GET;
-    return true;
-  }
-} /* ms_adjust_opt */
-
-
-/**
- * used to initialize the task which need verify data.
- *
- * @param task, pointer of current task in the concurrency
- */
-static void ms_task_data_verify_init(ms_task_t *task)
-{
-  ms_task_item_t *item= task->item;
-
-  assert(item != NULL);
-  assert(task->cmd == CMD_GET);
-
-  /**
-   *  according to data verification percent to determine if do
-   *  data verification.
-   */
-  if (task->verified_get < (double)task->get_opt
-      * ms_setting.verify_percent)
-  {
-    /**
-     *  currently it doesn't do verify, just increase the counter,
-     *  and do verification next proper get command
-     */
-    if ((task->item->value_offset != INVALID_OFFSET)
-        && (item->exp_time == 0))
-    {
-      task->verify= true;
-      task->finish_verify= false;
-      task->verified_get++;
-    }
-  }
-} /* ms_task_data_verify_init */
-
-
-/**
- * used to initialize the task which need verify expire time.
- *
- * @param task, pointer of current task in the concurrency
- */
-static void ms_task_expire_verify_init(ms_task_t *task)
-{
-  ms_task_item_t *item= task->item;
-
-  assert(item != NULL);
-  assert(task->cmd == CMD_GET);
-  assert(item->exp_time > 0);
-
-  task->verify= true;
-  task->finish_verify= false;
-} /* ms_task_expire_verify_init */
-
-
-/**
- * used to get one task, the function initializes the task
- * structure.
- *
- * @param c, pointer of the concurrency
- * @param warmup, whether it need warmup
- *
- * @return ms_task_t*, pointer of current task in the
- *         concurrency
- */
-static ms_task_t *ms_get_task(ms_conn_t *c, bool warmup)
-{
-  ms_task_t *task= &c->curr_task;
-
-  while (1)
-  {
-    task->verify= false;
-    task->finish_verify= true;
-    task->get_miss= true;
-
-    if (warmup)
-    {
-      task->cmd= CMD_SET;
-      task->item= ms_get_next_set_item(c);
-
-      return task;
-    }
-
-    /* according to operation distribution to choose doing which operation */
-    ms_select_opt(c, task);
-
-    if (! ms_adjust_opt(c, task))
-    {
-      continue;
-    }
-
-    if ((ms_setting.verify_percent > 0) && (task->cmd == CMD_GET))
-    {
-      ms_task_data_verify_init(task);
-    }
-
-    if ((ms_setting.exp_ver_per > 0) && (task->cmd == CMD_GET)
-        && (task->item->exp_time > 0))
-    {
-      ms_task_expire_verify_init(task);
-    }
-
-    break;
-  }
-
-  /**
-   *  Only update get and delete counter, set counter will be
-   *  updated after set operation successes.
-   */
-  if (task->cmd == CMD_GET)
-  {
-    task->get_opt++;
-    task->cycle_undo_get--;
-  }
-
-  return task;
-} /* ms_get_task */
-
-
-/**
- * send a signal to the main monitor thread
- *
- * @param sync_lock, pointer of the lock
- */
-static void ms_send_signal(ms_sync_lock_t *sync_lock)
-{
-  pthread_mutex_lock(&sync_lock->lock);
-  sync_lock->count++;
-  pthread_cond_signal(&sync_lock->cond);
-  pthread_mutex_unlock(&sync_lock->lock);
-} /* ms_send_signal */
-
-
-/**
- * If user only want to do get operation, but there is no object
- * in server , so we use this function to warmup the server, and
- * set some objects to server. It runs at the beginning of task.
- *
- * @param c, pointer of the concurrency
- */
-static void ms_warmup_server(ms_conn_t *c)
-{
-  ms_task_t *task;
-  ms_task_item_t *item;
-
-  /**
-   * Extra one loop to get the last command returned state.
-   * Normally it gets the previous command returned state.
-   */
-  if ((c->remain_warmup_num >= 0)
-      && (c->remain_warmup_num != c->warmup_num))
-  {
-    item= ms_get_cur_opt_item(c);
-    /* only update the set command result state for data verification */
-    if ((c->precmd.cmd == CMD_SET) && (c->precmd.retstat == MCD_STORED))
-    {
-      item->value_offset= item->key_suffix_offset;
-      /* set success, update counter */
-      c->set_cursor++;
-    }
-    else if (c->precmd.cmd == CMD_SET && c->precmd.retstat != MCD_STORED)
-    {
-      printf("key: %" PRIx64 " didn't set success\n", item->key_prefix);
-    }
-  }
-
-  /* the last time don't run a task */
-  if (c->remain_warmup_num-- > 0)
-  {
-    /* operate next task item */
-    task= ms_get_task(c, true);
-    item= task->item;
-    ms_mcd_set(c, item);
-  }
-
-  /**
-   *  finish warming up server, wait all connects initialize
-   *  complete. Then all connects can start do task at the same
-   *  time.
-   */
-  if (c->remain_warmup_num == -1)
-  {
-    ms_send_signal(&ms_global.warmup_lock);
-    c->remain_warmup_num--;       /* never run the if branch */
-  }
-} /* ms_warmup_server */
-
-
-/**
- * dispatch single get and set task
- *
- * @param c, pointer of the concurrency
- */
-static void ms_single_getset_task_sch(ms_conn_t *c)
-{
-  ms_task_t *task;
-  ms_task_item_t *item;
-
-  /* the last time don't run a task */
-  if (c->remain_exec_num-- > 0)
-  {
-    task= ms_get_task(c, false);
-    item= task->item;
-    if (task->cmd == CMD_SET)
-    {
-      ms_mcd_set(c, item);
-    }
-    else if (task->cmd == CMD_GET)
-    {
-      assert(task->cmd == CMD_GET);
-      ms_mcd_get(c, item);
-    }
-  }
-} /* ms_single_getset_task_sch */
-
-
-/**
- * dispatch multi-get and set task
- *
- * @param c, pointer of the concurrency
- */
-static void ms_multi_getset_task_sch(ms_conn_t *c)
-{
-  ms_task_t *task;
-  ms_mlget_task_item_t *mlget_item;
-
-  while (1)
-  {
-    if (c->remain_exec_num-- > 0)
-    {
-      task= ms_get_task(c, false);
-      if (task->cmd == CMD_SET)             /* just do it */
-      {
-        ms_mcd_set(c, task->item);
-        break;
-      }
-      else
-      {
-        assert(task->cmd == CMD_GET);
-        mlget_item= &c->mlget_task.mlget_item[c->mlget_task.mlget_num];
-        mlget_item->item= task->item;
-        mlget_item->verify= task->verify;
-        mlget_item->finish_verify= task->finish_verify;
-        mlget_item->get_miss= task->get_miss;
-        c->mlget_task.mlget_num++;
-
-        /* enough multi-get task items can be done */
-        if ((c->mlget_task.mlget_num >= ms_setting.mult_key_num)
-            || ((c->remain_exec_num == 0) && (c->mlget_task.mlget_num > 0)))
-        {
-          ms_mcd_mlget(c);
-          break;
-        }
-      }
-    }
-    else
-    {
-      if ((c->remain_exec_num <= 0) && (c->mlget_task.mlget_num > 0))
-      {
-        ms_mcd_mlget(c);
-      }
-      break;
-    }
-  }
-} /* ms_multi_getset_task_sch */
-
-
-/**
- * calculate the difference value of two time points
- *
- * @param start_time, the start time
- * @param end_time, the end time
- *
- * @return uint64_t, the difference value between start_time and end_time in us
- */
-int64_t ms_time_diff(struct timeval *start_time, struct timeval *end_time)
-{
-  int64_t endtime= end_time->tv_sec * 1000000 + end_time->tv_usec;
-  int64_t starttime= start_time->tv_sec * 1000000 + start_time->tv_usec;
-
-  assert(endtime >= starttime);
-
-  return endtime - starttime;
-} /* ms_time_diff */
-
-
-/**
- * after get the response from server for multi-get, the
- * function update the state of the task and do data verify if
- * necessary.
- *
- * @param c, pointer of the concurrency
- */
-static void ms_update_multi_get_result(ms_conn_t *c)
-{
-  ms_mlget_task_item_t *mlget_item;
-  ms_task_item_t *item;
-  char *orignval= NULL;
-  char *orignkey= NULL;
-
-  if (c == NULL)
-  {
-    return;
-  }
-  assert(c != NULL);
-
-  for (int i= 0; i < c->mlget_task.mlget_num; i++)
-  {
-    mlget_item= &c->mlget_task.mlget_item[i];
-    item= mlget_item->item;
-    orignval= &ms_setting.char_block[item->value_offset];
-    orignkey= &ms_setting.char_block[item->key_suffix_offset];
-
-    /* update get miss counter */
-    if (mlget_item->get_miss)
-    {
-      atomic_add_size(&ms_stats.get_misses, 1);
-    }
-
-    /* get nothing from server for this task item */
-    if (mlget_item->verify && ! mlget_item->finish_verify)
-    {
-      /* verify expire time if necessary */
-      if (item->exp_time > 0)
-      {
-        struct timeval curr_time;
-        gettimeofday(&curr_time, NULL);
-
-        /* object doesn't expire but can't get it now */
-        if (curr_time.tv_sec - item->client_time
-            < item->exp_time - EXPIRE_TIME_ERROR)
-        {
-          atomic_add_size(&ms_stats.unexp_unget, 1);
-
-          if (ms_setting.verbose)
-          {
-            char set_time[64];
-            char cur_time[64];
-            strftime(set_time, 64, "%Y-%m-%d %H:%M:%S",
-                     localtime(&item->client_time));
-            strftime(cur_time, 64, "%Y-%m-%d %H:%M:%S",
-                     localtime(&curr_time.tv_sec));
-            fprintf(stderr,
-                    "\n\t<%d expire time verification failed, object "
-                    "doesn't expire but can't get it now\n"
-                    "\tkey len: %d\n"
-                    "\tkey: %" PRIx64 " %.*s\n"
-                    "\tset time: %s current time: %s "
-                    "diff time: %d expire time: %d\n"
-                    "\texpected data len: %d\n"
-                    "\texpected data: %.*s\n"
-                    "\treceived data: \n",
-                    c->sfd,
-                    item->key_size,
-                    item->key_prefix,
-                    item->key_size - (int)KEY_PREFIX_SIZE,
-                    orignkey,
-                    set_time,
-                    cur_time,
-                    (int)(curr_time.tv_sec - item->client_time),
-                    item->exp_time,
-                    item->value_size,
-                    item->value_size,
-                    orignval);
-            fflush(stderr);
-          }
-        }
-      }
-      else
-      {
-        atomic_add_size(&ms_stats.vef_miss, 1);
-
-        if (ms_setting.verbose)
-        {
-          fprintf(stderr, "\n<%d data verification failed\n"
-                          "\tkey len: %d\n"
-                          "\tkey: %" PRIx64 " %.*s\n"
-                          "\texpected data len: %d\n"
-                          "\texpected data: %.*s\n"
-                          "\treceived data: \n",
-                  c->sfd, item->key_size, item->key_prefix,
-                  item->key_size - (int)KEY_PREFIX_SIZE,
-                  orignkey, item->value_size, item->value_size, orignval);
-          fflush(stderr);
-        }
-      }
-    }
-  }
-  c->mlget_task.mlget_num= 0;
-  c->mlget_task.value_index= INVALID_OFFSET;
-} /* ms_update_multi_get_result */
-
-
-/**
- * after get the response from server for single get, the
- * function update the state of the task and do data verify if
- * necessary.
- *
- * @param c, pointer of the concurrency
- * @param item, pointer of task item which includes the object
- *            information
- */
-static void ms_update_single_get_result(ms_conn_t *c, ms_task_item_t *item)
-{
-  char *orignval= NULL;
-  char *orignkey= NULL;
-
-  if ((c == NULL) || (item == NULL))
-  {
-    return;
-  }
-  assert(c != NULL);
-  assert(item != NULL);
-
-  orignval= &ms_setting.char_block[item->value_offset];
-  orignkey= &ms_setting.char_block[item->key_suffix_offset];
-
-  /* update get miss counter */
-  if ((c->precmd.cmd == CMD_GET) && c->curr_task.get_miss)
-  {
-    atomic_add_size(&ms_stats.get_misses, 1);
-  }
-
-  /* get nothing from server for this task item */
-  if ((c->precmd.cmd == CMD_GET) && c->curr_task.verify
-      && ! c->curr_task.finish_verify)
-  {
-    /* verify expire time if necessary */
-    if (item->exp_time > 0)
-    {
-      struct timeval curr_time;
-      gettimeofday(&curr_time, NULL);
-
-      /* object doesn't expire but can't get it now */
-      if (curr_time.tv_sec - item->client_time
-          < item->exp_time - EXPIRE_TIME_ERROR)
-      {
-        atomic_add_size(&ms_stats.unexp_unget, 1);
-
-        if (ms_setting.verbose)
-        {
-          char set_time[64];
-          char cur_time[64];
-          strftime(set_time, 64, "%Y-%m-%d %H:%M:%S",
-                   localtime(&item->client_time));
-          strftime(cur_time, 64, "%Y-%m-%d %H:%M:%S",
-                   localtime(&curr_time.tv_sec));
-          fprintf(stderr,
-                  "\n\t<%d expire time verification failed, object "
-                  "doesn't expire but can't get it now\n"
-                  "\tkey len: %d\n"
-                  "\tkey: %" PRIx64 " %.*s\n"
-                  "\tset time: %s current time: %s "
-                  "diff time: %d expire time: %d\n"
-                  "\texpected data len: %d\n"
-                  "\texpected data: %.*s\n"
-                  "\treceived data: \n",
-                  c->sfd,
-                  item->key_size,
-                  item->key_prefix,
-                  item->key_size - (int)KEY_PREFIX_SIZE,
-                  orignkey,
-                  set_time,
-                  cur_time,
-                  (int)(curr_time.tv_sec - item->client_time),
-                  item->exp_time,
-                  item->value_size,
-                  item->value_size,
-                  orignval);
-          fflush(stderr);
-        }
-      }
-    }
-    else
-    {
-      atomic_add_size(&ms_stats.vef_miss, 1);
-
-      if (ms_setting.verbose)
-      {
-        fprintf(stderr, "\n<%d data verification failed\n"
-                        "\tkey len: %d\n"
-                        "\tkey: %" PRIx64 " %.*s\n"
-                        "\texpected data len: %d\n"
-                        "\texpected data: %.*s\n"
-                        "\treceived data: \n",
-                c->sfd, item->key_size, item->key_prefix,
-                item->key_size - (int)KEY_PREFIX_SIZE,
-                orignkey, item->value_size, item->value_size, orignval);
-        fflush(stderr);
-      }
-    }
-  }
-} /* ms_update_single_get_result */
-
-
-/**
- * after get the response from server for set the function
- * update the state of the task and do data verify if necessary.
- *
- * @param c, pointer of the concurrency
- * @param item, pointer of task item which includes the object
- *            information
- */
-static void ms_update_set_result(ms_conn_t *c, ms_task_item_t *item)
-{
-  if ((c == NULL) || (item == NULL))
-  {
-    return;
-  }
-  assert(c != NULL);
-  assert(item != NULL);
-
-  if (c->precmd.cmd == CMD_SET)
-  {
-    switch (c->precmd.retstat)
-    {
-    case MCD_STORED:
-      if (item->value_offset == INVALID_OFFSET)
-      {
-        /* first set with the same offset of key suffix */
-        item->value_offset= item->key_suffix_offset;
-      }
-      else
-      {
-        /* not first set, just increase the value offset */
-        item->value_offset+= 1;
-      }
-
-      /* set successes, update counter */
-      c->set_cursor++;
-      c->curr_task.set_opt++;
-      c->curr_task.cycle_undo_set--;
-      break;
-
-    case MCD_SERVER_ERROR:
-    default:
-      break;
-    } /* switch */
-  }
-} /* ms_update_set_result */
-
-
-/**
- * update the response time result
- *
- * @param c, pointer of the concurrency
- */
-static void ms_update_stat_result(ms_conn_t *c)
-{
-  bool get_miss= false;
-
-  if (c == NULL)
-  {
-    return;
-  }
-  assert(c != NULL);
-
-  gettimeofday(&c->end_time, NULL);
-  uint64_t time_diff= (uint64_t)ms_time_diff(&c->start_time, &c->end_time);
-
-  pthread_mutex_lock(&ms_statistic.stat_mutex);
-
-  switch (c->precmd.cmd)
-  {
-  case CMD_SET:
-    ms_record_event(&ms_statistic.set_stat, time_diff, false);
-    break;
-
-  case CMD_GET:
-    if (c->curr_task.get_miss)
-    {
-      get_miss= true;
-    }
-    ms_record_event(&ms_statistic.get_stat, time_diff, get_miss);
-    break;
-
-  default:
-    break;
-  } /* switch */
-
-  ms_record_event(&ms_statistic.total_stat, time_diff, get_miss);
-  pthread_mutex_unlock(&ms_statistic.stat_mutex);
-} /* ms_update_stat_result */
-
-
-/**
- * after get response from server for the current operation, and
- * before doing the next operation, update the state of the
- * current operation.
- *
- * @param c, pointer of the concurrency
- */
-static void ms_update_task_result(ms_conn_t *c)
-{
-  ms_task_item_t *item;
-
-  if (c == NULL)
-  {
-    return;
-  }
-  assert(c != NULL);
-
-  item= ms_get_cur_opt_item(c);
-  if (item == NULL)
-  {
-    return;
-  }
-  assert(item != NULL);
-
-  ms_update_set_result(c, item);
-
-  if ((ms_setting.stat_freq > 0)
-      && ((c->precmd.cmd == CMD_SET) || (c->precmd.cmd == CMD_GET)))
-  {
-    ms_update_stat_result(c);
-  }
-
-  /* update multi-get task item */
-  if (((ms_setting.mult_key_num > 1)
-       && (c->mlget_task.mlget_num >= ms_setting.mult_key_num))
-      || ((c->remain_exec_num == 0) && (c->mlget_task.mlget_num > 0)))
-  {
-    ms_update_multi_get_result(c);
-  }
-  else
-  {
-    ms_update_single_get_result(c, item);
-  }
-} /* ms_update_task_result */
-
-
-/**
- * run get and set operation
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_run_getset_task(ms_conn_t *c)
-{
-  /**
-   * extra one loop to get the last command return state. get the
-   * last command return state.
-   */
-  if ((c->remain_exec_num >= 0)
-      && (c->remain_exec_num != c->exec_num))
-  {
-    ms_update_task_result(c);
-  }
-
-  /* multi-get */
-  if (ms_setting.mult_key_num > 1)
-  {
-    /* operate next task item */
-    ms_multi_getset_task_sch(c);
-  }
-  else
-  {
-    /* operate next task item */
-    ms_single_getset_task_sch(c);
-  }
-
-  /* no task to do, exit */
-  if ((c->remain_exec_num == -1) || ms_global.time_out)
-  {
-    return -1;
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_run_getset_task */
-
-
-/**
- * the state machine call the function to execute task.
- *
- * @param c, pointer of the concurrency
- *
- * @return int, if success, return EXIT_SUCCESS, else return -1
- */
-int ms_exec_task(struct conn *c)
-{
-  if (! ms_global.finish_warmup)
-  {
-    ms_warmup_server(c);
-  }
-  else
-  {
-    if (ms_run_getset_task(c) != 0)
-    {
-      return -1;
-    }
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_exec_task */
diff --git a/clients/ms_task.h b/clients/ms_task.h
deleted file mode 100644 (file)
index c4917d1..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * File:   ms_task.h
- * Author: Mingqiang Zhuang
- *
- * Created on February 10, 2009
- *
- * (c) Copyright 2009, Schooner Information Technology, Inc.
- * http://www.schoonerinfotech.com/
- *
- */
-#ifndef MS_TASK_H
-#define MS_TASK_H
-
-#include <sys/types.h>
-#include <stdint.h>
-#if !defined(__cplusplus)
-# include <stdbool.h>
-#endif
-#include <time.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define UNIT_ITEMS_COUNT     1024               /* each window unit has 1024 items */
-#define KEY_PREFIX_SIZE      (sizeof(uint64_t)) /* key prefix length: 8 bytes */
-#define INVALID_OFFSET       (-1)               /* invalid offset in the character table */
-#define FIXED_EXPIRE_TIME    60                 /* default expire time is 60s */
-#define EXPIRE_TIME_ERROR    5                  /* default expire time error is 5s */
-
-/* information of a task item(object) */
-typedef struct task_item
-{
-  uint64_t key_prefix;                  /* prefix of the key, 8 bytes, binary */
-  int key_size;                         /* key size */
-  int key_suffix_offset;                /* suffix offset in the global character table */
-
-  int value_size;                       /* data size */
-  int value_offset;                     /* data offset in the global character table */
-
-  time_t client_time;                   /* the current client time */
-  int exp_time;                         /* expire time */
-} ms_task_item_t;
-
-/* task item for multi-get */
-typedef struct mlget_task_item
-{
-  ms_task_item_t *item;                 /* task item */
-  bool verify;                          /* whether verify data or not */
-  bool finish_verify;                   /* whether finish data verify or not */
-  bool get_miss;                        /* whether get miss or not */
-} ms_mlget_task_item_t;
-
-/* information of multi-get task */
-typedef struct mlget_task
-{
-  ms_mlget_task_item_t *mlget_item;        /* multi-get task array */
-  int mlget_num;                           /* how many tasks in mlget_task array */
-  int value_index;                         /* the nth value received by the connect, for multi-get */
-} ms_mlget_task_t;
-
-/* structure used to store the state of the running task */
-typedef struct task
-{
-  int cmd;                              /* command name */
-  bool verify;                          /* whether verify data or not */
-  bool finish_verify;                   /* whether finish data verify or not */
-  bool get_miss;                        /* whether get miss or not */
-  ms_task_item_t *item;                 /* task item */
-
-  /* counter for command distribution adjustment */
-  uint64_t get_opt;                     /* number of total get operations */
-  uint64_t set_opt;                     /* number of total set operations, no including warmup set count */
-  int cycle_undo_get;                   /* number of undo get in an adjustment cycle */
-  int cycle_undo_set;                   /* number of undo set in an adjustment cycle */
-  uint64_t verified_get;                /* number of total verified get operations */
-  uint64_t overwrite_set;               /* number of total overwrite set operations */
-} ms_task_t;
-
-struct conn;
-
-/* the state machine call the function to execute task.*/
-int ms_exec_task(struct conn *c);
-
-
-/* calculate the difference value of two time points */
-int64_t ms_time_diff(struct timeval *start_time, struct timeval *end_time);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* end of MS_TASK_H */
diff --git a/clients/ms_thread.c b/clients/ms_thread.c
deleted file mode 100644 (file)
index f9f52bf..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * File:   ms_thread.c
- * Author: Mingqiang Zhuang
- *
- * Created on February 10, 2009
- *
- * (c) Copyright 2009, Schooner Information Technology, Inc.
- * http://www.schoonerinfotech.com/
- *
- */
-
-#include "mem_config.h"
-
-#if defined(HAVE_SYS_TIME_H)
-# include <sys/time.h>
-#endif
-
-#if defined(HAVE_TIME_H)
-# include <time.h>
-#endif
-
-#include "ms_thread.h"
-#include "ms_setting.h"
-#include "ms_atomic.h"
-
-/* global variable */
-pthread_key_t ms_thread_key;
-
-/* array of thread context structure, each thread has a thread context structure */
-static ms_thread_ctx_t *ms_thread_ctx;
-
-/* functions */
-static void ms_set_current_time(void);
-static void ms_check_sock_timeout(void);
-static void ms_clock_handler(const int fd, const short which, void *arg);
-static uint32_t ms_set_thread_cpu_affinity(uint32_t cpu);
-static int ms_setup_thread(ms_thread_ctx_t *thread_ctx);
-static void *ms_worker_libevent(void *arg);
-static void ms_create_worker(void *(*func)(void *), void *arg);
-
-
-/**
- *  time-sensitive callers can call it by hand with this,
- *  outside the normal ever-1-second timer
- */
-static void ms_set_current_time()
-{
-  struct timeval timer;
-  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
-
-  gettimeofday(&timer, NULL);
-  ms_thread->curr_time= (rel_time_t)timer.tv_sec;
-} /* ms_set_current_time */
-
-
-/**
- *  used to check whether UDP of command are waiting timeout
- *  by the ever-1-second timer
- */
-static void ms_check_sock_timeout(void)
-{
-  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
-  ms_conn_t *c= NULL;
-  int time_diff= 0;
-
-  for (uint32_t i= 0; i < ms_thread->thread_ctx->nconns; i++)
-  {
-    c= &ms_thread->conn[i];
-
-    if (c->udp)
-    {
-      time_diff= (int)(ms_thread->curr_time - (rel_time_t)c->start_time.tv_sec);
-
-      /* wait time out */
-      if (time_diff > SOCK_WAIT_TIMEOUT)
-      {
-        /* calculate dropped packets count */
-        if (c->recvpkt > 0)
-        {
-          atomic_add_size(&ms_stats.pkt_drop, c->packets - c->recvpkt);
-        }
-
-        atomic_add_size(&ms_stats.udp_timeout, 1);
-        ms_reset_conn(c, true);
-      }
-    }
-  }
-} /* ms_check_sock_timeout */
-
-
-/* if disconnect, the ever-1-second timer will call this function to reconnect */
-static void ms_reconn_thread_socks(void)
-{
-  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
-  for (uint32_t i= 0; i < ms_thread->thread_ctx->nconns; i++)
-  {
-    ms_reconn_socks(&ms_thread->conn[i]);
-  }
-} /* ms_reconn_thread_socks */
-
-
-/**
- * the handler of the ever-1-second timer
- *
- * @param fd, the descriptors of the socket
- * @param which, event flags
- * @param arg, argument
- */
-static void ms_clock_handler(const int fd, const short which, void *arg)
-{
-  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
-  struct timeval t=
-  {
-    .tv_sec= 1, .tv_usec= 0
-  };
-
-  UNUSED_ARGUMENT(fd);
-  UNUSED_ARGUMENT(which);
-  UNUSED_ARGUMENT(arg);
-
-  ms_set_current_time();
-
-  if (ms_thread->initialized)
-  {
-    /* only delete the event if it's actually there. */
-    evtimer_del(&ms_thread->clock_event);
-    ms_check_sock_timeout();
-  }
-  else
-  {
-    ms_thread->initialized= true;
-  }
-
-  ms_reconn_thread_socks();
-
-  evtimer_set(&ms_thread->clock_event, ms_clock_handler, 0);
-  event_base_set(ms_thread->base, &ms_thread->clock_event);
-  evtimer_add(&ms_thread->clock_event, &t);
-} /* ms_clock_handler */
-
-
-/**
- * used to bind thread to CPU if the system supports
- *
- * @param cpu, cpu index
- *
- * @return if success, return EXIT_SUCCESS, else return -1
- */
-static uint32_t ms_set_thread_cpu_affinity(uint32_t cpu)
-{
-  uint32_t ret= 0;
-
-#ifdef HAVE_CPU_SET_T
-  cpu_set_t cpu_set;
-  CPU_ZERO(&cpu_set);
-  CPU_SET(cpu, &cpu_set);
-
-  if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) == -1)
-  {
-    fprintf(stderr, "WARNING: Could not set CPU Affinity, continuing...\n");
-    ret= 1;
-  }
-#else
-  UNUSED_ARGUMENT(cpu);
-#endif
-
-  return ret;
-} /* ms_set_thread_cpu_affinity */
-
-
-/**
- * Set up a thread's information.
- *
- * @param thread_ctx, pointer of the thread context structure
- *
- * @return if success, return EXIT_SUCCESS, else return -1
- */
-static int ms_setup_thread(ms_thread_ctx_t *thread_ctx)
-{
-
-  ms_thread_t *ms_thread= (ms_thread_t *)calloc(sizeof(*ms_thread), 1);
-  pthread_setspecific(ms_thread_key, (void *)ms_thread);
-
-  ms_thread->thread_ctx= thread_ctx;
-  ms_thread->nactive_conn= thread_ctx->nconns;
-  ms_thread->initialized= false;
-  static ATOMIC uint32_t cnt= 0;
-
-  gettimeofday(&ms_thread->startup_time, NULL);
-
-  ms_thread->base= event_init();
-  if (ms_thread->base == NULL)
-  {
-    if (atomic_add_32_nv(&cnt, 1) == 0)
-    {
-      fprintf(stderr, "Can't allocate event base.\n");
-    }
-
-    return -1;
-  }
-
-  ms_thread->conn=
-    (ms_conn_t *)malloc((size_t)thread_ctx->nconns * sizeof(ms_conn_t));
-  if (ms_thread->conn == NULL)
-  {
-    if (atomic_add_32_nv(&cnt, 1) == 0)
-    {
-      fprintf(
-        stderr,
-        "Can't allocate concurrency structure for thread descriptors.");
-    }
-
-    return -1;
-  }
-  memset(ms_thread->conn, 0, (size_t)thread_ctx->nconns * sizeof(ms_conn_t));
-
-  for (uint32_t i= 0; i < thread_ctx->nconns; i++)
-  {
-    ms_thread->conn[i].conn_idx= i;
-    if (ms_setup_conn(&ms_thread->conn[i]) != 0)
-    {
-      /* only output this error once */
-      if (atomic_add_32_nv(&cnt, 1) == 0)
-      {
-        fprintf(stderr, "Initializing connection failed.\n");
-      }
-
-      return -1;
-    }
-  }
-
-  return EXIT_SUCCESS;
-} /* ms_setup_thread */
-
-
-/**
- * Worker thread: main event loop
- *
- * @param arg, the pointer of argument
- *
- * @return void*
- */
-static void *ms_worker_libevent(void *arg)
-{
-  ms_thread_t *ms_thread= NULL;
-  ms_thread_ctx_t *thread_ctx= (ms_thread_ctx_t *)arg;
-
-  /**
-   * If system has more than one cpu and supports set cpu
-   * affinity, try to bind each thread to a cpu core;
-   */
-  if (ms_setting.ncpu > 1)
-  {
-    ms_set_thread_cpu_affinity(thread_ctx->thd_idx % ms_setting.ncpu);
-  }
-
-  if (ms_setup_thread(thread_ctx) != 0)
-  {
-    exit(1);
-  }
-
-  /* each thread with a timer */
-  ms_clock_handler(0, 0, 0);
-
-  pthread_mutex_lock(&ms_global.init_lock.lock);
-  ms_global.init_lock.count++;
-  pthread_cond_signal(&ms_global.init_lock.cond);
-  pthread_mutex_unlock(&ms_global.init_lock.lock);
-
-  ms_thread= pthread_getspecific(ms_thread_key);
-  event_base_loop(ms_thread->base, 0);
-
-  return NULL;
-} /* ms_worker_libevent */
-
-
-/**
- * Creates a worker thread.
- *
- * @param func, the callback function
- * @param arg, the argument to pass to the callback function
- */
-static void ms_create_worker(void *(*func)(void *), void *arg)
-{
-  pthread_t thread;
-  pthread_attr_t attr;
-  int ret;
-
-  pthread_attr_init(&attr);
-
-  if ((ret= pthread_create(&thread, &attr, func, arg)) != 0)
-  {
-    fprintf(stderr, "Can't create thread: %s.\n", strerror(ret));
-    exit(1);
-  }
-} /* ms_create_worker */
-
-
-/* initialize threads */
-void ms_thread_init()
-{
-  ms_thread_ctx=
-    (ms_thread_ctx_t *)malloc(
-      sizeof(ms_thread_ctx_t) * (size_t)ms_setting.nthreads);
-  if (ms_thread_ctx == NULL)
-  {
-    fprintf(stderr, "Can't allocate thread descriptors.");
-    exit(1);
-  }
-
-  for (uint32_t i= 0; i < ms_setting.nthreads; i++)
-  {
-    ms_thread_ctx[i].thd_idx= i;
-    ms_thread_ctx[i].nconns= ms_setting.nconns / ms_setting.nthreads;
-
-    /**
-     *  If only one server, all the connections in all threads
-     *  connects the same server. For support multi-servers, simple
-     *  distribute thread to server.
-     */
-    ms_thread_ctx[i].srv_idx= i % ms_setting.srv_cnt;
-    ms_thread_ctx[i].tps_perconn= ms_setting.expected_tps
-                                  / (int)ms_setting.nconns;
-    ms_thread_ctx[i].exec_num_perconn= ms_setting.exec_num
-                                       / ms_setting.nconns;
-  }
-
-  if (pthread_key_create(&ms_thread_key, NULL))
-  {
-    fprintf(stderr, "Can't create pthread keys. Major malfunction!\n");
-    exit(1);
-  }
-  /* Create threads after we've done all the epoll setup. */
-  for (uint32_t i= 0; i < ms_setting.nthreads; i++)
-  {
-    ms_create_worker(ms_worker_libevent, (void *)&ms_thread_ctx[i]);
-  }
-} /* ms_thread_init */
-
-
-/* cleanup some resource of threads when all the threads exit */
-void ms_thread_cleanup()
-{
-  if (ms_thread_ctx != NULL)
-  {
-    free(ms_thread_ctx);
-  }
-  pthread_key_delete(ms_thread_key);
-} /* ms_thread_cleanup */
diff --git a/clients/ms_thread.h b/clients/ms_thread.h
deleted file mode 100644 (file)
index 8cb98bd..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * File:   ms_thread.h
- * Author: Mingqiang Zhuang
- *
- * Created on February 10, 2009
- *
- * (c) Copyright 2009, Schooner Information Technology, Inc.
- * http://www.schoonerinfotech.com/
- *
- */
-
-/**
- * Asynchronous memslap has the similar implementation of
- * multi-threads with memcached. Asynchronous memslap creates
- * one or more self-governed threads; each thread is bound with
- * one CPU core if the system supports setting CPU core
- * affinity. And every thread has private variables. There is
- * less communication or some shared resources among all the
- * threads. It can improve the performance because there are
- * fewer locks and competition. In addition, each thread has a
- * libevent to manage the events of network. Each thread has one
- * or more self-governed concurrencies; each concurrency has one
- * or more socket connections. All the concurrencies don't
- * communicate with each other even though they are in the same
- * thread.
- */
-#ifndef MS_THREAD_H
-#define MS_THREAD_H
-
-#include <sched.h>
-#include "ms_conn.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** Time relative to server start. Smaller than time_t on 64-bit systems. */
-typedef unsigned int   rel_time_t;
-
-/* Used to store the context of each thread */
-typedef struct thread_ctx
-{
-  uint32_t thd_idx;                          /* the thread index */
-  uint32_t nconns;                           /* how many connections included by the thread */
-  uint32_t srv_idx;                          /* index of the thread */
-  int tps_perconn;                      /* expected throughput per connection */
-  int64_t exec_num_perconn;             /* execute number per connection */
-} ms_thread_ctx_t;
-
-/* Used to store the private variables of each thread */
-typedef struct thread
-{
-  ms_conn_t *conn;                      /* conn array to store all the conn in the thread */
-  uint32_t nactive_conn;                     /* how many connects are active */
-
-  ms_thread_ctx_t *thread_ctx;          /* thread context from the caller */
-  struct event_base *base;              /* libevent handler created by this thread */
-
-  rel_time_t curr_time;                 /* current time */
-  struct event clock_event;             /* clock event to time each one second */
-  bool initialized;                     /* whether clock_event has been initialized */
-
-  struct timeval startup_time;          /* start time of the thread */
-} ms_thread_t;
-
-/* initialize threads */
-void ms_thread_init(void);
-
-
-/* cleanup some resource of threads when all the threads exit */
-void ms_thread_cleanup(void);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* end of MS_THREAD_H */
diff --git a/clients/utilities.cc b/clients/utilities.cc
deleted file mode 100644 (file)
index 268b790..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-#include <mem_config.h>
-
-#include <clients/utilities.h>
-
-#include <cstdio>
-#include <cassert>
-#include <cstdlib>
-#include <cstring>
-#include <ctype.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-
-long int timedif(struct timeval a, struct timeval b)
-{
-  long us, s;
-
-  us = (int)(a.tv_usec - b.tv_usec);
-  us /= 1000;
-  s = (int)(a.tv_sec - b.tv_sec);
-  s *= 1000;
-  return s + us;
-}
-
-void version_command(const char *command_name)
-{
-  printf("%s v%u.%u\n", command_name, 1U, 0U);
-  exit(EXIT_SUCCESS);
-}
-
-void close_stdio(void)
-{
-  int fd;
-  if ((fd = open("/dev/null", O_RDWR, 0)) < 0)
-  {
-    return;
-  }
-  else
-  {
-    if (dup2(fd, STDIN_FILENO) < 0)
-    {
-      return;
-    }
-
-    if (dup2(fd, STDOUT_FILENO) < 0)
-    {
-      return;
-    }
-
-    if (dup2(fd, STDERR_FILENO) < 0)
-    {
-      return;
-    }
-
-    if (fd > STDERR_FILENO)
-    {
-      close(fd);
-    }
-  }
-}
-
-
-static const char *lookup_help(memcached_options option)
-{
-  switch (option)
-  {
-  case OPT_SERVERS: return("List which servers you wish to connect to.");
-  case OPT_VERSION: return("Display the version of the application and then exit.");
-  case OPT_HELP: return("Display this message and then exit.");
-  case OPT_VERBOSE: return("Give more details on the progression of the application.");
-  case OPT_QUIET: return("stderr and stdin will be closed at application startup.");
-  case OPT_DEBUG: return("Provide output only useful for debugging.");
-  case OPT_FLAG: return("Provide flag information for storage operation.");
-  case OPT_EXPIRE: return("Set the expire option for the object.");
-  case OPT_SET: return("Use set command with memcached when storing.");
-  case OPT_REPLACE: return("Use replace command with memcached when storing.");
-  case OPT_ADD: return("Use add command with memcached when storing.");
-  case OPT_SLAP_EXECUTE_NUMBER: return("Number of times to execute the given test.");
-  case OPT_SLAP_INITIAL_LOAD: return("Number of key pairs to load before executing tests.");
-  case OPT_SLAP_TEST: return("Test to run (currently \"get\" or \"set\").");
-  case OPT_SLAP_CONCURRENCY: return("Number of users to simulate with load.");
-  case OPT_SLAP_NON_BLOCK: return("Set TCP up to use non-blocking IO.");
-  case OPT_SLAP_TCP_NODELAY: return("Set TCP socket up to use nodelay.");
-  case OPT_FLUSH: return("Flush servers before running tests.");
-  case OPT_HASH: return("Select hash type.");
-  case OPT_BINARY: return("Switch to binary protocol.");
-  case OPT_ANALYZE: return("Analyze the provided servers.");
-  case OPT_UDP: return("Use UDP protocol when communicating with server.");
-  case OPT_BUFFER: return("Enable request buffering.");
-  case OPT_USERNAME: return "Username to use for SASL authentication";
-  case OPT_PASSWD: return "Password to use for SASL authentication";
-  case OPT_FILE: return "Path to file in which to save result";
-  case OPT_STAT_ARGS: return "Argument for statistics";
-  case OPT_SERVER_VERSION: return "Memcached daemon software version";
-  default:
-                      break;
-  };
-
-  assert(0);
-  return "forgot to document this function :)";
-}
-
-void help_command(const char *command_name, const char *description,
-                  const struct option *long_options,
-                  memcached_programs_help_st *options)
-{
-  unsigned int x;
-  (void)options;
-
-  printf("%s v%u.%u\n\n", command_name, 1U, 0U);
-  printf("\t%s\n\n", description);
-  printf("Current options. A '=' means the option takes a value.\n\n");
-
-  for (x= 0; long_options[x].name; x++)
-  {
-    const char *help_message;
-
-    printf("\t --%s%c\n", long_options[x].name,
-           long_options[x].has_arg ? '=' : ' ');
-    if ((help_message= lookup_help(memcached_options(long_options[x].val))))
-      printf("\t\t%s\n", help_message);
-  }
-
-  printf("\n");
-  exit(EXIT_SUCCESS);
-}
-
-void process_hash_option(memcached_st *memc, char *opt_hash)
-{
-  uint64_t set;
-  memcached_return_t rc;
-
-  if (opt_hash == NULL)
-  {
-    return;
-  }
-
-  set= MEMCACHED_HASH_DEFAULT; /* Just here to solve warning */
-  if (!strcasecmp(opt_hash, "CRC"))
-  {
-    set= MEMCACHED_HASH_CRC;
-  }
-  else if (!strcasecmp(opt_hash, "FNV1_64"))
-  {
-    set= MEMCACHED_HASH_FNV1_64;
-  }
-  else if (!strcasecmp(opt_hash, "FNV1A_64"))
-  {
-    set= MEMCACHED_HASH_FNV1A_64;
-  }
-  else if (!strcasecmp(opt_hash, "FNV1_32"))
-  {
-    set= MEMCACHED_HASH_FNV1_32;
-  }
-  else if (!strcasecmp(opt_hash, "FNV1A_32"))
-  {
-    set= MEMCACHED_HASH_FNV1A_32;
-  }
-  else
-  {
-    fprintf(stderr, "hash: type not recognized %s\n", opt_hash);
-    exit(EXIT_FAILURE);
-  }
-
-  rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, set);
-  if (rc != MEMCACHED_SUCCESS)
-  {
-    fprintf(stderr, "hash: memcache error %s\n", memcached_strerror(memc, rc));
-    exit(EXIT_FAILURE);
-  }
-}
-
-void initialize_sockets(void)
-{
-  /* Define the function for all platforms to avoid #ifdefs in each program */
-#if defined(_WIN32)
-  WSADATA wsaData;
-  if (WSAStartup(MAKEWORD(2,0), &wsaData) != 0)
-  {
-    fprintf(stderr, "Socket Initialization Error. Program aborted\n");
-    exit(EXIT_FAILURE);
-  }
-#endif // #if defined(_WIN32)
-}
diff --git a/clients/utilities.h b/clients/utilities.h
deleted file mode 100644 (file)
index a9f199d..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-#pragma once
-
-#include <getopt.h>
-#include <libmemcached-1.0/memcached.h>
-#include "clients/client_options.h"
-
-#if defined(HAVE_SYS_TIME_H)
-# include <sys/time.h>
-#endif
-
-#if defined(HAVE_TIME_H)
-# include <time.h>
-#endif
-
-
-#ifdef __sun
-  /* For some odd reason the option struct on solaris defines the argument
-   * as char* and not const char*
-   */
-#define OPTIONSTRING char*
-#else
-#define OPTIONSTRING const char*
-#endif
-
-typedef struct memcached_programs_help_st memcached_programs_help_st;
-
-struct memcached_programs_help_st
-{
-  char *not_used_yet;
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-char *strdup_cleanup(const char *str);
-void cleanup(void);
-long int timedif(struct timeval a, struct timeval b);
-void version_command(const char *command_name) __attribute__ ((noreturn));
-void help_command(const char *command_name, const char *description,
-                  const struct option *long_options,
-                  memcached_programs_help_st *options) __attribute__ ((noreturn));
-void process_hash_option(memcached_st *memc, char *opt_hash);
-bool initialize_sasl(memcached_st *memc, char *user, char *password);
-void shutdown_sasl(void);
-void initialize_sockets(void);
-void close_stdio(void);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/docs/gh-pages/publish.sh b/docs/gh-pages/publish.sh
new file mode 100755 (executable)
index 0000000..b87f8ef
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/bash
+
+set -eu
+cd "$(dirname $0)"
+
+if test -d source/.git
+then
+  cd source
+  git pull -r
+  cd ..
+else
+  git clone -b gh-pages github.com:m6w6/libmemcached source
+fi
+
+mkdir -p build
+cd build
+cmake ../..
+make html
+rsync -va --delete --exclude=.git/ docs/html/ ../source/
+
+cd ../source
+touch .nojekyll
+git add -A
+git ci -m "update docs"
+git push
+
diff --git a/gh-pages.sh b/gh-pages.sh
deleted file mode 100755 (executable)
index 4184737..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/bash
-
-set -eu
-cd "$(dirname $0)"
-
-if test -d gh-pages/.git
-then
-  cd gh-pages
-  git pull -r
-  cd ..
-else
-  git clone -b gh-pages github.com:m6w6/libmemcached gh-pages
-fi
-
-mkdir -p gh-pages-build
-cd gh-pages-build
-cmake ..
-make html
-rsync -va --delete --exclude=.git/ docs/html/ ../gh-pages/
-
-cd ../gh-pages
-touch .nojekyll
-git add -A
-git ci -m "update docs"
-git push
-
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9082509
--- /dev/null
@@ -0,0 +1,4 @@
+
+add_subdirectory(libhashkit-1.0)
+add_subdirectory(libmemcached-1.0)
+add_subdirectory(libmemcachedutil-1.0)
diff --git a/include/libhashkit-1.0/CMakeLists.txt b/include/libhashkit-1.0/CMakeLists.txt
new file mode 100644 (file)
index 0000000..ee96731
--- /dev/null
@@ -0,0 +1,7 @@
+
+configure_file(configure.h.in configure.h @ONLY)
+
+install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+        FILES_MATCHING REGEX "\\.h(pp)?$"
+        )
diff --git a/include/libhashkit-1.0/algorithm.h b/include/libhashkit-1.0/algorithm.h
new file mode 100644 (file)
index 0000000..72005aa
--- /dev/null
@@ -0,0 +1,88 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+/**
+ * @file
+ * @brief HashKit Header
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+uint32_t libhashkit_one_at_a_time(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_fnv1_64(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_fnv1a_64(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_fnv1_32(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_fnv1a_32(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_crc32(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_hsieh(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_murmur(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_murmur3(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_jenkins(const char *key, size_t key_length);
+
+HASHKIT_API
+uint32_t libhashkit_md5(const char *key, size_t key_length);
+
+HASHKIT_API
+void libhashkit_md5_signature(const unsigned char *key, size_t length, unsigned char *result);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libhashkit-1.0/basic_string.h b/include/libhashkit-1.0/basic_string.h
new file mode 100644 (file)
index 0000000..1cb17e3
--- /dev/null
@@ -0,0 +1,52 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+#pragma once
+
+// No assumptions of NULL should be made
+
+#define hashkit_size(X) (X).size;
+#define hashkit_c_str(X) (X).c_str;
+#define hashkit_string_param(X) (X).c_str, (X).size
+
+#ifdef __cplusplus
+#define hashkit_string_printf(X) int((X).size), (X).c_str
+#else
+#define hashkit_string_printf(X) (int)((X).size), (X).c_str
+#endif
+
diff --git a/include/libhashkit-1.0/behavior.h b/include/libhashkit-1.0/behavior.h
new file mode 100644 (file)
index 0000000..8cc5709
--- /dev/null
@@ -0,0 +1,56 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+
+
+/**
+ * @file
+ * @brief HashKit Header
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libhashkit-1.0/configure.h.in b/include/libhashkit-1.0/configure.h.in
new file mode 100644 (file)
index 0000000..508ff7b
--- /dev/null
@@ -0,0 +1,53 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+
+
+#pragma once
+
+#define LIBHASHKIT_VERSION_STRING "@LIBHASHKIT_VERSION@"
+#define LIBHASHKIT_VERSION_HEX @LIBHASHKIT_VERSION_HEX@
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libhashkit-1.0/digest.h b/include/libhashkit-1.0/digest.h
new file mode 100644 (file)
index 0000000..c34dc8a
--- /dev/null
@@ -0,0 +1,60 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+uint32_t hashkit_digest(const hashkit_st *self, const char *key, size_t key_length);
+
+/**
+  This is a utilitly function provided so that you can directly access hashes with a hashkit_st.
+*/
+
+HASHKIT_API
+uint32_t libhashkit_digest(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libhashkit-1.0/function.h b/include/libhashkit-1.0/function.h
new file mode 100644 (file)
index 0000000..664a008
--- /dev/null
@@ -0,0 +1,73 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+  This sets/gets the default function we will be using.
+*/
+HASHKIT_API
+hashkit_return_t hashkit_set_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm);
+
+HASHKIT_API
+hashkit_return_t hashkit_set_custom_function(hashkit_st *hash, hashkit_hash_fn function, void *context);
+
+HASHKIT_API
+hashkit_hash_algorithm_t hashkit_get_function(const hashkit_st *hash);
+
+/**
+  This sets/gets the function we use for distribution.
+*/
+HASHKIT_API
+hashkit_return_t hashkit_set_distribution_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm);
+
+HASHKIT_API
+hashkit_return_t hashkit_set_custom_distribution_function(hashkit_st *self, hashkit_hash_fn function, void *context);
+
+HASHKIT_API
+hashkit_hash_algorithm_t hashkit_get_distribution_function(const hashkit_st *self);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libhashkit-1.0/has.h b/include/libhashkit-1.0/has.h
new file mode 100644 (file)
index 0000000..35e8616
--- /dev/null
@@ -0,0 +1,52 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+bool libhashkit_has_algorithm(const hashkit_hash_algorithm_t);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libhashkit-1.0/hashkit.h b/include/libhashkit-1.0/hashkit.h
new file mode 100644 (file)
index 0000000..da9bd36
--- /dev/null
@@ -0,0 +1,110 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+
+
+#pragma once
+
+
+#if !defined(__cplusplus)
+# include <stdbool.h>
+#endif
+#include <inttypes.h>
+#include <sys/types.h>
+
+#include <libhashkit-1.0/visibility.h>
+#include <libhashkit-1.0/configure.h>
+#include <libhashkit-1.0/types.h>
+#include <libhashkit-1.0/has.h>
+#include <libhashkit-1.0/algorithm.h>
+#include <libhashkit-1.0/behavior.h>
+#include <libhashkit-1.0/digest.h>
+#include <libhashkit-1.0/function.h>
+#include <libhashkit-1.0/str_algorithm.h>
+#include <libhashkit-1.0/strerror.h>
+#include <libhashkit-1.0/string.h>
+
+struct hashkit_st
+{
+  struct hashkit_function_st {
+    hashkit_hash_fn function;
+    void *context;
+  } base_hash, distribution_hash;
+
+  struct {
+    bool is_base_same_distributed:1;
+  } flags;
+
+  struct {
+    bool is_allocated:1;
+  } options;
+
+  void *_key;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+  hashkit_st *hashkit_create(hashkit_st *hash);
+
+HASHKIT_API
+  hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *ptr);
+
+HASHKIT_API
+  bool hashkit_compare(const hashkit_st *first, const hashkit_st *second);
+
+HASHKIT_API
+  void hashkit_free(hashkit_st *hash);
+
+HASHKIT_API
+  hashkit_string_st *hashkit_encrypt(hashkit_st *,
+                                     const char* source, size_t source_length);
+
+HASHKIT_API
+  hashkit_string_st *hashkit_decrypt(hashkit_st *,
+                                     const char* source, size_t source_length);
+
+HASHKIT_API
+  bool hashkit_key(hashkit_st *, const char *key, const size_t key_length);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/include/libhashkit-1.0/hashkit.hpp b/include/libhashkit-1.0/hashkit.hpp
new file mode 100644 (file)
index 0000000..a953d72
--- /dev/null
@@ -0,0 +1,98 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#include <libhashkit-1.0/hashkit.h>
+#include <string>
+
+class Hashkit {
+
+public:
+
+  Hashkit()
+  {
+    hashkit_create(&self);
+  }
+
+  Hashkit(const Hashkit& source)
+  {
+    hashkit_clone(&self, &source.self);
+  }
+
+  Hashkit& operator=(const Hashkit& source)
+  {
+    hashkit_free(&self);
+    hashkit_clone(&self, &source.self);
+
+    return *this;
+  }
+
+  friend bool operator==(const Hashkit &left, const Hashkit &right)
+  {
+    return hashkit_compare(&left.self, &right.self);
+  }
+
+  uint32_t digest(std::string& str)
+  {
+    return hashkit_digest(&self, str.c_str(), str.length());
+  }
+
+  uint32_t digest(const char *key, size_t key_length)
+  {
+    return hashkit_digest(&self, key, key_length);
+  }
+
+  hashkit_return_t set_function(hashkit_hash_algorithm_t hash_algorithm)
+  {
+    return hashkit_set_function(&self, hash_algorithm);
+  }
+
+  hashkit_return_t set_distribution_function(hashkit_hash_algorithm_t hash_algorithm)
+  {
+    return hashkit_set_function(&self, hash_algorithm);
+  }
+
+  ~Hashkit()
+  {
+    hashkit_free(&self);
+  }
+private:
+
+  hashkit_st self;
+};
diff --git a/include/libhashkit-1.0/str_algorithm.h b/include/libhashkit-1.0/str_algorithm.h
new file mode 100644 (file)
index 0000000..bb05eb5
--- /dev/null
@@ -0,0 +1,48 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+const char *libhashkit_string_hash(hashkit_hash_algorithm_t type);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libhashkit-1.0/strerror.h b/include/libhashkit-1.0/strerror.h
new file mode 100644 (file)
index 0000000..79eb145
--- /dev/null
@@ -0,0 +1,50 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+  const char *hashkit_strerror(hashkit_st *ptr, hashkit_return_t rc);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libhashkit-1.0/string.h b/include/libhashkit-1.0/string.h
new file mode 100644 (file)
index 0000000..90cb3ae
--- /dev/null
@@ -0,0 +1,63 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifdef __cplusplus
+struct hashkit_string_st;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+HASHKIT_API
+void hashkit_string_free(hashkit_string_st *ptr);
+
+
+HASHKIT_API
+size_t hashkit_string_length(const hashkit_string_st *self);
+
+HASHKIT_API
+const char *hashkit_string_c_str(const hashkit_string_st* self);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
diff --git a/include/libhashkit-1.0/types.h b/include/libhashkit-1.0/types.h
new file mode 100644 (file)
index 0000000..37c33ee
--- /dev/null
@@ -0,0 +1,98 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+typedef enum {
+  HASHKIT_SUCCESS,
+  HASHKIT_FAILURE,
+  HASHKIT_MEMORY_ALLOCATION_FAILURE,
+  HASHKIT_INVALID_HASH,
+  HASHKIT_INVALID_ARGUMENT,
+  HASHKIT_MAXIMUM_RETURN /* Always add new error code before */
+} hashkit_return_t;
+
+static inline bool hashkit_success(const hashkit_return_t rc)
+{
+  return (rc == HASHKIT_SUCCESS);
+}
+
+static inline bool hashkit_failed(const hashkit_return_t rc)
+{
+  return (rc != HASHKIT_SUCCESS);
+}
+
+typedef enum {
+  HASHKIT_HASH_DEFAULT= 0, // hashkit_one_at_a_time()
+  HASHKIT_HASH_MD5,
+  HASHKIT_HASH_CRC,
+  HASHKIT_HASH_FNV1_64,
+  HASHKIT_HASH_FNV1A_64,
+  HASHKIT_HASH_FNV1_32,
+  HASHKIT_HASH_FNV1A_32,
+  HASHKIT_HASH_HSIEH,
+  HASHKIT_HASH_MURMUR,
+  HASHKIT_HASH_JENKINS,
+  HASHKIT_HASH_MURMUR3,
+  HASHKIT_HASH_CUSTOM,
+  HASHKIT_HASH_MAX
+} hashkit_hash_algorithm_t;
+
+/**
+ * Hash distributions that are available to use.
+ */
+typedef enum
+{
+  HASHKIT_DISTRIBUTION_MODULA,
+  HASHKIT_DISTRIBUTION_RANDOM,
+  HASHKIT_DISTRIBUTION_KETAMA,
+  HASHKIT_DISTRIBUTION_MAX /* Always add new values before this. */
+} hashkit_distribution_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct hashkit_st hashkit_st;
+typedef struct hashkit_string_st hashkit_string_st;
+
+typedef uint32_t (*hashkit_hash_fn)(const char *key, size_t key_length, void *context);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libhashkit-1.0/visibility.h b/include/libhashkit-1.0/visibility.h
new file mode 100644 (file)
index 0000000..b8f194c
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Summary: interface for HashKit functions
+ * Description: visibitliy macros for HashKit library
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in this directory for full text.
+ * 
+ * Author: Monty Taylor
+ */
+
+/**
+ * @file
+ * @brief Visibility control macros
+ */
+
+#pragma once
+
+/**
+ *
+ * HASHKIT_API is used for the public API symbols. It either DLL imports or
+ * DLL exports (or does nothing for static build).
+ *
+ * HASHKIT_LOCAL is used for non-api symbols.
+ */
+
+#if defined(BUILDING_HASHKIT)
+# if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
+#  define HASHKIT_API __attribute__ ((visibility("default")))
+#  define HASHKIT_LOCAL  __attribute__ ((visibility("hidden")))
+# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+#  define HASHKIT_API __global
+#  define HASHKIT_LOCAL __hidden
+# elif defined(_MSC_VER)
+#  define HASHKIT_API extern __declspec(dllexport) 
+#  define HASHKIT_LOCAL
+# else
+#  define HASHKIT_API
+#  define HASHKIT_LOCAL
+# endif /* defined(HAVE_VISIBILITY) */
+#else  /* defined(BUILDING_HASHKIT) */
+# if defined(_MSC_VER)
+#  define HASHKIT_API extern __declspec(dllimport) 
+#  define HASHKIT_LOCAL
+# else
+#  define HASHKIT_API
+#  define HASHKIT_LOCAL
+# endif /* defined(_MSC_VER) */
+#endif /* defined(BUILDING_HASHKIT) */
diff --git a/include/libmemcached-1.0/CMakeLists.txt b/include/libmemcached-1.0/CMakeLists.txt
new file mode 100644 (file)
index 0000000..061c6f7
--- /dev/null
@@ -0,0 +1,8 @@
+
+configure_file(configure.h.in configure.h @ONLY)
+
+install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+        FILES_MATCHING REGEX "\\.h(pp)?$"
+        PATTERN t EXCLUDE
+        )
diff --git a/include/libmemcached-1.0/alloc.h b/include/libmemcached-1.0/alloc.h
new file mode 100644 (file)
index 0000000..bc65b95
--- /dev/null
@@ -0,0 +1,54 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+  Memory allocation functions.
+*/
+typedef void (*memcached_free_fn)(const memcached_st *ptr, void *mem, void *context);
+typedef void *(*memcached_malloc_fn)(const memcached_st *ptr, const size_t size, void *context);
+typedef void *(*memcached_realloc_fn)(const memcached_st *ptr, void *mem, const size_t size, void *context);
+typedef void *(*memcached_calloc_fn)(const memcached_st *ptr, size_t nelem, const size_t elsize, void *context);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/allocators.h b/include/libmemcached-1.0/allocators.h
new file mode 100644 (file)
index 0000000..86f05a0
--- /dev/null
@@ -0,0 +1,64 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_set_memory_allocators(memcached_st *ptr,
+                                                   memcached_malloc_fn mem_malloc,
+                                                   memcached_free_fn mem_free,
+                                                   memcached_realloc_fn mem_realloc,
+                                                   memcached_calloc_fn mem_calloc,
+                                                   void *context);
+
+LIBMEMCACHED_API
+void memcached_get_memory_allocators(const memcached_st *ptr,
+                                     memcached_malloc_fn *mem_malloc,
+                                     memcached_free_fn *mem_free,
+                                     memcached_realloc_fn *mem_realloc,
+                                     memcached_calloc_fn *mem_calloc);
+
+LIBMEMCACHED_API
+void *memcached_get_memory_allocators_context(const memcached_st *ptr);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/analyze.h b/include/libmemcached-1.0/analyze.h
new file mode 100644 (file)
index 0000000..0da3814
--- /dev/null
@@ -0,0 +1,56 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached-1.0/struct/analysis.h>
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_analysis_st *memcached_analyze(memcached_st *memc,
+                                         memcached_stat_st *memc_stat,
+                                         memcached_return_t *error);
+
+LIBMEMCACHED_API
+void memcached_analyze_free(memcached_analysis_st *);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/auto.h b/include/libmemcached-1.0/auto.h
new file mode 100644 (file)
index 0000000..f37d50f
--- /dev/null
@@ -0,0 +1,111 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_increment(memcached_st *ptr,
+                                         const char *key, size_t key_length,
+                                         uint32_t offset,
+                                         uint64_t *value);
+LIBMEMCACHED_API
+  memcached_return_t memcached_decrement(memcached_st *ptr,
+                                         const char *key, size_t key_length,
+                                         uint32_t offset,
+                                         uint64_t *value);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_increment_by_key(memcached_st *ptr,
+                                                const char *group_key, size_t group_key_length,
+                                                const char *key, size_t key_length,
+                                                uint64_t offset,
+                                                uint64_t *value);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_decrement_by_key(memcached_st *ptr,
+                                                const char *group_key, size_t group_key_length,
+                                                const char *key, size_t key_length,
+                                                uint64_t offset,
+                                                uint64_t *value);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_increment_with_initial(memcached_st *ptr,
+                                                      const char *key,
+                                                      size_t key_length,
+                                                      uint64_t offset,
+                                                      uint64_t initial,
+                                                      time_t expiration,
+                                                      uint64_t *value);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_decrement_with_initial(memcached_st *ptr,
+                                                      const char *key,
+                                                      size_t key_length,
+                                                      uint64_t offset,
+                                                      uint64_t initial,
+                                                      time_t expiration,
+                                                      uint64_t *value);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr,
+                                                             const char *group_key,
+                                                             size_t group_key_length,
+                                                             const char *key,
+                                                             size_t key_length,
+                                                             uint64_t offset,
+                                                             uint64_t initial,
+                                                             time_t expiration,
+                                                             uint64_t *value);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr,
+                                                             const char *group_key,
+                                                             size_t group_key_length,
+                                                             const char *key,
+                                                             size_t key_length,
+                                                             uint64_t offset,
+                                                             uint64_t initial,
+                                                             time_t expiration,
+                                                             uint64_t *value);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/basic_string.h b/include/libmemcached-1.0/basic_string.h
new file mode 100644 (file)
index 0000000..de8d3d5
--- /dev/null
@@ -0,0 +1,55 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+// No assumptions of NULL should be made
+
+struct memcached_string_t {
+  const char *c_str;
+  size_t size;
+};
+
+#define memcached_size(X) (X).size;
+#define memcached_c_str(X) (X).c_str;
+#define memcached_string_param(X) (X).c_str, (X).size
+
+#ifdef __cplusplus
+#define memcached_string_printf(X) int((X).size), (X).c_str
+#else
+#define memcached_string_printf(X) (int)((X).size), (X).c_str
+#endif
+
diff --git a/include/libmemcached-1.0/behavior.h b/include/libmemcached-1.0/behavior.h
new file mode 100644 (file)
index 0000000..c663353
--- /dev/null
@@ -0,0 +1,83 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_behavior_set(memcached_st *ptr, const memcached_behavior_t flag, uint64_t data);
+
+LIBMEMCACHED_API
+uint64_t memcached_behavior_get(memcached_st *ptr, const memcached_behavior_t flag);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_behavior_set_distribution(memcached_st *ptr, memcached_server_distribution_t type);
+
+LIBMEMCACHED_API
+memcached_server_distribution_t memcached_behavior_get_distribution(memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_behavior_set_key_hash(memcached_st *ptr, memcached_hash_t type);
+
+LIBMEMCACHED_API
+memcached_hash_t memcached_behavior_get_key_hash(memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_behavior_set_distribution_hash(memcached_st *ptr, memcached_hash_t type);
+
+LIBMEMCACHED_API
+memcached_hash_t memcached_behavior_get_distribution_hash(memcached_st *ptr);
+
+LIBMEMCACHED_API
+  const char *libmemcached_string_behavior(const memcached_behavior_t flag);
+
+LIBMEMCACHED_API
+  const char *libmemcached_string_distribution(const memcached_server_distribution_t flag);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_bucket_set(memcached_st *self,
+                                          const uint32_t *host_map,
+                                          const uint32_t *forward_map,
+                                          const uint32_t buckets,
+                                          const uint32_t replicas);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/callback.h b/include/libmemcached-1.0/callback.h
new file mode 100644 (file)
index 0000000..a62e9aa
--- /dev/null
@@ -0,0 +1,55 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_callback_set(memcached_st *ptr,
+                                          const memcached_callback_t flag,
+                                          const void *data);
+LIBMEMCACHED_API
+void *memcached_callback_get(memcached_st *ptr,
+                             const memcached_callback_t flag,
+                             memcached_return_t *error);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/callbacks.h b/include/libmemcached-1.0/callbacks.h
new file mode 100644 (file)
index 0000000..7ab8cb1
--- /dev/null
@@ -0,0 +1,53 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef memcached_return_t (*memcached_execute_fn)(const memcached_st *ptr, memcached_result_st *result, void *context);
+typedef memcached_return_t (*memcached_server_fn)(const memcached_st *ptr, const memcached_instance_st * server, void *context);
+typedef memcached_return_t (*memcached_stat_fn)(const memcached_instance_st * server,
+                                                const char *key, size_t key_length,
+                                                const char *value, size_t value_length,
+                                                void *context);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/configure.h.in b/include/libmemcached-1.0/configure.h.in
new file mode 100644 (file)
index 0000000..07d8442
--- /dev/null
@@ -0,0 +1,52 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker, Trond Norbye All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#cmakedefine01 LIBMEMCACHED_ENABLE_DEPRECATED
+#cmakedefine01 LIBMEMCACHED_WITH_SASL_SUPPORT
+
+#define LIBMEMCACHED_VERSION_STRING "@LIBMEMCACHED_VERSION@"
+#define LIBMEMCACHED_VERSION_HEX @LIBMEMCACHED_VERSION_HEX@
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/defaults.h b/include/libmemcached-1.0/defaults.h
new file mode 100644 (file)
index 0000000..d440f8c
--- /dev/null
@@ -0,0 +1,56 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+/* Public defines */
+#define MEMCACHED_DEFAULT_PORT 11211
+#define MEMCACHED_DEFAULT_PORT_STRING "11211"
+#define MEMCACHED_POINTS_PER_SERVER 100
+#define MEMCACHED_POINTS_PER_SERVER_KETAMA 160
+#define MEMCACHED_CONTINUUM_SIZE MEMCACHED_POINTS_PER_SERVER*100 /* This would then set max hosts to 100 */
+#define MEMCACHED_STRIDE 4
+#define MEMCACHED_DEFAULT_TIMEOUT 5000
+#define MEMCACHED_DEFAULT_CONNECT_TIMEOUT 4000
+#define MEMCACHED_CONTINUUM_ADDITION 10 /* How many extra slots we should build for in the continuum */
+#define MEMCACHED_EXPIRATION_NOT_ADD 0xffffffffU
+#define MEMCACHED_SERVER_FAILURE_LIMIT 5
+#define MEMCACHED_SERVER_FAILURE_RETRY_TIMEOUT 2
+#define MEMCACHED_SERVER_FAILURE_DEAD_TIMEOUT 0
+#define MEMCACHED_SERVER_TIMEOUT_LIMIT 0
+
diff --git a/include/libmemcached-1.0/delete.h b/include/libmemcached-1.0/delete.h
new file mode 100644 (file)
index 0000000..617d585
--- /dev/null
@@ -0,0 +1,57 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_delete(memcached_st *ptr, const char *key, size_t key_length,
+                                    time_t expiration);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_delete_by_key(memcached_st *ptr,
+                                           const char *group_key, size_t group_key_length,
+                                           const char *key, size_t key_length,
+                                           time_t expiration);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/deprecated_types.h b/include/libmemcached-1.0/deprecated_types.h
new file mode 100644 (file)
index 0000000..0a6df65
--- /dev/null
@@ -0,0 +1,61 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Warning, none of these should ever be used.
+ */
+
+#pragma once
+
+/**
+  @note The following definitions are just here for backwards compatibility.
+*/
+typedef memcached_return_t memcached_return;
+typedef memcached_server_distribution_t memcached_server_distribution;
+typedef memcached_behavior_t memcached_behavior;
+typedef memcached_callback_t memcached_callback;
+typedef memcached_hash_t memcached_hash;
+typedef memcached_connection_t memcached_connection;
+typedef memcached_clone_fn memcached_clone_func;
+typedef memcached_cleanup_fn memcached_cleanup_func;
+typedef memcached_execute_fn memcached_execute_function;
+typedef memcached_server_fn memcached_server_function;
+typedef memcached_trigger_key_fn memcached_trigger_key;
+typedef memcached_trigger_delete_key_fn memcached_trigger_delete_key;
+typedef memcached_dump_fn memcached_dump_func;
+typedef memcached_instance_st *memcached_server_instance_st;
+
diff --git a/include/libmemcached-1.0/dump.h b/include/libmemcached-1.0/dump.h
new file mode 100644 (file)
index 0000000..b6e639e
--- /dev/null
@@ -0,0 +1,51 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_dump(memcached_st *ptr, memcached_dump_fn *function, void *context, uint32_t number_of_callbacks);
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/encoding_key.h b/include/libmemcached-1.0/encoding_key.h
new file mode 100644 (file)
index 0000000..3adbcb6
--- /dev/null
@@ -0,0 +1,49 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_set_encoding_key(memcached_st*, const char *str, size_t length);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/error.h b/include/libmemcached-1.0/error.h
new file mode 100644 (file)
index 0000000..9346bb0
--- /dev/null
@@ -0,0 +1,67 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+  const char *memcached_error(const memcached_st *);
+
+LIBMEMCACHED_API
+  const char *memcached_last_error_message(const memcached_st *);
+
+LIBMEMCACHED_API
+  void memcached_error_print(const memcached_st *);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_last_error(const memcached_st *);
+
+LIBMEMCACHED_API
+  int memcached_last_error_errno(const memcached_st *);
+
+LIBMEMCACHED_API
+  const char *memcached_server_error(const memcached_instance_st * ptr);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_server_error_return(const memcached_instance_st * ptr);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/include/libmemcached-1.0/exception.hpp b/include/libmemcached-1.0/exception.hpp
new file mode 100644 (file)
index 0000000..4759072
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Summary: Exceptions for the C++ interface
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ */
+
+/**
+ * @file
+ * @brief Exception declarations
+ */
+
+#pragma once
+
+#include <stdexcept>
+#include <string>
+
+namespace memcache 
+{
+  class Exception : public std::runtime_error
+  {
+  public:
+    Exception(const std::string& msg, int in_errno)
+      : 
+        std::runtime_error(msg), 
+        _errno(in_errno) 
+    {}
+
+    Exception(const char *msg, int in_errno)
+      : 
+        std::runtime_error(std::string(msg)), 
+        _errno(in_errno) {}
+
+    virtual ~Exception() throw() {}
+
+    int getErrno() const 
+    { 
+      return _errno; 
+    }
+
+  private:
+    int _errno;
+  };
+
+  class Warning : public Exception
+  {
+  public:
+    Warning(const std::string& msg, int in_errno) : Exception(msg, in_errno) {}
+    Warning(const char *msg, int in_errno) : Exception(msg, in_errno) {}
+  };
+
+  class Error : public Exception
+  {
+  public:
+    Error(const std::string& msg, int in_errno) : Exception(msg, in_errno) {}
+    Error(const char *msg, int in_errno) : Exception(msg, in_errno) {}
+    virtual ~Error() throw() {}
+  };
+
+} /* namespace libmemcached */
diff --git a/include/libmemcached-1.0/exist.h b/include/libmemcached-1.0/exist.h
new file mode 100644 (file)
index 0000000..ef60a81
--- /dev/null
@@ -0,0 +1,52 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_exist(memcached_st *memc, const char *key, size_t key_length);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_exist_by_key(memcached_st *memc,
+                                          const char *group_key, size_t group_key_length,
+                                          const char *key, size_t key_length);
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/fetch.h b/include/libmemcached-1.0/fetch.h
new file mode 100644 (file)
index 0000000..bff186a
--- /dev/null
@@ -0,0 +1,53 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_fetch_execute(memcached_st *ptr,
+                                           memcached_execute_fn *callback,
+                                           void *context,
+                                           uint32_t number_of_callbacks);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/flush.h b/include/libmemcached-1.0/flush.h
new file mode 100644 (file)
index 0000000..820a98e
--- /dev/null
@@ -0,0 +1,49 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_flush(memcached_st *ptr, time_t expiration);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/flush_buffers.h b/include/libmemcached-1.0/flush_buffers.h
new file mode 100644 (file)
index 0000000..31b5868
--- /dev/null
@@ -0,0 +1,49 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_flush_buffers(memcached_st *mem);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/get.h b/include/libmemcached-1.0/get.h
new file mode 100644 (file)
index 0000000..32e4c5f
--- /dev/null
@@ -0,0 +1,110 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Public defines */
+LIBMEMCACHED_API
+char *memcached_get(memcached_st *ptr,
+                    const char *key, size_t key_length,
+                    size_t *value_length,
+                    uint32_t *flags,
+                    memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_mget(memcached_st *ptr,
+                                  const char * const *keys,
+                                  const size_t *key_length,
+                                  size_t number_of_keys);
+
+LIBMEMCACHED_API
+char *memcached_get_by_key(memcached_st *ptr,
+                           const char *group_key, size_t group_key_length,
+                           const char *key, size_t key_length,
+                           size_t *value_length,
+                           uint32_t *flags,
+                           memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_mget_by_key(memcached_st *ptr,
+                                         const char *group_key,
+                                         size_t group_key_length,
+                                         const char * const *keys,
+                                         const size_t *key_length,
+                                         const size_t number_of_keys);
+
+LIBMEMCACHED_API
+char *memcached_fetch(memcached_st *ptr,
+                      char *key,
+                      size_t *key_length,
+                      size_t *value_length,
+                      uint32_t *flags,
+                      memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_result_st *memcached_fetch_result(memcached_st *ptr,
+                                            memcached_result_st *result,
+                                            memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_mget_execute(memcached_st *ptr,
+                                          const char * const *keys,
+                                          const size_t *key_length,
+                                          const size_t number_of_keys,
+                                          memcached_execute_fn *callback,
+                                          void *context,
+                                          const uint32_t number_of_callbacks);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_mget_execute_by_key(memcached_st *ptr,
+                                                 const char *group_key,
+                                                 size_t group_key_length,
+                                                 const char * const *keys,
+                                                 const size_t *key_length,
+                                                 size_t number_of_keys,
+                                                 memcached_execute_fn *callback,
+                                                 void *context,
+                                                 const uint32_t number_of_callbacks);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/hash.h b/include/libmemcached-1.0/hash.h
new file mode 100644 (file)
index 0000000..9fdb7d6
--- /dev/null
@@ -0,0 +1,65 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The two public hash bits */
+LIBMEMCACHED_API
+uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash_t hash_algorithm);
+
+LIBMEMCACHED_API
+const hashkit_st *memcached_get_hashkit(const memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_set_hashkit(memcached_st *ptr, hashkit_st *hashk);
+
+LIBMEMCACHED_API
+uint32_t memcached_generate_hash(const memcached_st *ptr, const char *key, size_t key_length);
+
+LIBMEMCACHED_API
+void memcached_autoeject(memcached_st *ptr);
+
+LIBMEMCACHED_API
+  const char * libmemcached_string_hash(memcached_hash_t type);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/limits.h b/include/libmemcached-1.0/limits.h
new file mode 100644 (file)
index 0000000..076df40
--- /dev/null
@@ -0,0 +1,46 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#define MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH 20
+#define MEMCACHED_MAX_BUFFER 8196
+#define MEMCACHED_MAX_HOST_SORT_LENGTH 86 /* Used for Ketama */
+#define MEMCACHED_MAX_KEY 251 /* We add one to have it null terminated */
+#define MEMCACHED_PREFIX_KEY_MAX_SIZE 128
+#define MEMCACHED_VERSION_STRING_LENGTH 24
diff --git a/include/libmemcached-1.0/memcached.h b/include/libmemcached-1.0/memcached.h
new file mode 100644 (file)
index 0000000..1ee54bb
--- /dev/null
@@ -0,0 +1,173 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+/* This seems to be required for older compilers @note http://stackoverflow.com/questions/8132399/how-to-printf-uint64-t  */
+#ifndef __STDC_FORMAT_MACROS
+#  define __STDC_FORMAT_MACROS
+#endif
+
+#ifdef __cplusplus
+#  if __cplusplus >= 201103L
+#    include <cinttypes>
+#  else
+#    include <inttypes.h>
+#  endif
+#  include <cstddef>
+#  include <cstdlib>
+#else
+#  include <inttypes.h>
+#  include <stddef.h>
+#  include <stdlib.h>
+#  include <stdbool.h>
+#endif
+
+#include <sys/types.h>
+
+#include <libmemcached-1.0/visibility.h>
+#include <libmemcached-1.0/configure.h>
+#include <libmemcached-1.0/platform.h>
+
+#include <libmemcached-1.0/limits.h>
+#include <libmemcached-1.0/defaults.h>
+
+#include <libmemcached-1.0/types/behavior.h>
+#include <libmemcached-1.0/types/callback.h>
+#include <libmemcached-1.0/types/connection.h>
+#include <libmemcached-1.0/types/hash.h>
+#include <libmemcached-1.0/types/return.h>
+#include <libmemcached-1.0/types/server_distribution.h>
+
+#include <libmemcached-1.0/return.h>
+
+#include <libmemcached-1.0/types.h>
+#include <libmemcached-1.0/callbacks.h>
+#include <libmemcached-1.0/alloc.h>
+#include <libmemcached-1.0/triggers.h>
+
+#include <libhashkit-1.0/hashkit.h>
+
+#include <libmemcached-1.0/struct/callback.h>
+#include <libmemcached-1.0/struct/string.h>
+#include <libmemcached-1.0/struct/result.h>
+#include <libmemcached-1.0/struct/allocator.h>
+#include <libmemcached-1.0/struct/sasl.h>
+#include <libmemcached-1.0/struct/memcached.h>
+#include <libmemcached-1.0/struct/server.h>
+#include <libmemcached-1.0/struct/stat.h>
+
+#include <libmemcached-1.0/basic_string.h>
+#include <libmemcached-1.0/error.h>
+#include <libmemcached-1.0/stats.h>
+
+// Everything above this line must be in the order specified.
+#include <libmemcached-1.0/allocators.h>
+#include <libmemcached-1.0/analyze.h>
+#include <libmemcached-1.0/auto.h>
+#include <libmemcached-1.0/behavior.h>
+#include <libmemcached-1.0/callback.h>
+#include <libmemcached-1.0/delete.h>
+#include <libmemcached-1.0/dump.h>
+#include <libmemcached-1.0/encoding_key.h>
+#include <libmemcached-1.0/exist.h>
+#include <libmemcached-1.0/fetch.h>
+#include <libmemcached-1.0/flush.h>
+#include <libmemcached-1.0/flush_buffers.h>
+#include <libmemcached-1.0/get.h>
+#include <libmemcached-1.0/hash.h>
+#include <libmemcached-1.0/options.h>
+#include <libmemcached-1.0/parse.h>
+#include <libmemcached-1.0/quit.h>
+#include <libmemcached-1.0/result.h>
+#include <libmemcached-1.0/server.h>
+#include <libmemcached-1.0/server_list.h>
+#include <libmemcached-1.0/storage.h>
+#include <libmemcached-1.0/strerror.h>
+#include <libmemcached-1.0/touch.h>
+#include <libmemcached-1.0/verbosity.h>
+#include <libmemcached-1.0/version.h>
+#include <libmemcached-1.0/sasl.h>
+
+#include <libmemcached-1.0/deprecated_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+void memcached_servers_reset(memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_st *memcached_create(memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_st *memcached(const char *string, size_t string_length);
+
+LIBMEMCACHED_API
+void memcached_free(memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_reset(memcached_st *ptr);
+
+LIBMEMCACHED_API
+void memcached_reset_last_disconnected_server(memcached_st *ptr);
+
+LIBMEMCACHED_API
+memcached_st *memcached_clone(memcached_st *clone, const memcached_st *ptr);
+
+LIBMEMCACHED_API
+void *memcached_get_user_data(const memcached_st *ptr);
+
+LIBMEMCACHED_API
+void *memcached_set_user_data(memcached_st *ptr, void *data);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_push(memcached_st *destination, const memcached_st *source);
+
+LIBMEMCACHED_API
+const memcached_instance_st * memcached_server_instance_by_position(const memcached_st *ptr, uint32_t server_key);
+
+LIBMEMCACHED_API
+uint32_t memcached_server_count(const memcached_st *);
+
+LIBMEMCACHED_API
+uint64_t memcached_query_id(const memcached_st *);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/include/libmemcached-1.0/memcached.hpp b/include/libmemcached-1.0/memcached.hpp
new file mode 100644 (file)
index 0000000..af12f30
--- /dev/null
@@ -0,0 +1,876 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Summary: C++ interface for memcached server
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Authors: Padraig O'Sullivan <osullivan.padraig@gmail.com>
+ *          Patrick Galbraith <patg@patg.net>
+ */
+
+/**
+ * @file memcached.hpp
+ * @brief Libmemcached C++ interface
+ */
+
+#pragma once
+
+#include <libmemcached-1.0/memcached.h>
+#if 0
+#include <libmemcached/exception.hpp>
+#endif
+
+#include <string.h>
+
+#include <sstream>
+#include <string>
+#include <vector>
+#include <map>
+
+namespace memcache
+{
+
+/**
+ * This is the core memcached library (if later, other objects
+ * are needed, they will be created from this class).
+ */
+class Memcache
+{
+public:
+
+  Memcache()
+  {
+    memc_= memcached(NULL, 0);
+  }
+
+  Memcache(const std::string &config)
+  {
+    memc_= memcached(config.c_str(), config.size());
+  }
+
+  Memcache(const std::string &hostname, in_port_t port)
+  {
+    memc_= memcached(NULL, 0);
+    if (memc_)
+    {
+      memcached_server_add(memc_, hostname.c_str(), port);
+    }
+  }
+
+  Memcache(memcached_st *clone)
+  {
+    memc_= memcached_clone(NULL, clone);
+  }
+
+  Memcache(const Memcache &rhs)
+  {
+    memc_= memcached_clone(NULL, rhs.getImpl());
+  }
+
+  Memcache &operator=(const Memcache &rhs)
+  {
+    if (this != &rhs)
+    {
+      memcached_free(memc_);
+      memc_= memcached_clone(NULL, rhs.getImpl());
+    }
+
+    return *this;
+  }
+
+  ~Memcache()
+  {
+    memcached_free(memc_);
+  }
+
+  /**
+   * Get the internal memcached_st *
+   */
+  const memcached_st *getImpl() const
+  {
+    return memc_;
+  }
+
+  /**
+   * Return an error string for the given return structure.
+   *
+   * @param[in] rc a memcached_return_t structure
+   * @return error string corresponding to given return code in the library.
+   */
+  const std::string getError(memcached_return_t rc) const
+  {
+    /* first parameter to strerror is unused */
+    return memcached_strerror(NULL, rc);
+  }
+
+  bool error(std::string& error_message) const
+  {
+    if (memcached_failed(memcached_last_error(memc_)))
+    {
+      error_message+= memcached_last_error_message(memc_);
+      return true;
+    }
+
+    return false;
+  }
+
+  bool error() const
+  {
+    if (memcached_failed(memcached_last_error(memc_)))
+    {
+      return true;
+    }
+
+    return false;
+  }
+
+  bool error(memcached_return_t& arg) const
+  {
+    arg= memcached_last_error(memc_);
+    return memcached_failed(arg);
+  }
+
+  bool setBehavior(memcached_behavior_t flag, uint64_t data)
+  {
+    return (memcached_success(memcached_behavior_set(memc_, flag, data)));
+  }
+
+  uint64_t getBehavior(memcached_behavior_t flag)
+  {
+    return memcached_behavior_get(memc_, flag);
+  }
+
+  /**
+   * Configure the memcache object
+   *
+   * @param[in] in_config configuration
+   * @return true on success; false otherwise
+   */
+  bool configure(const std::string &configuration)
+  {
+    memcached_st *new_memc= memcached(configuration.c_str(), configuration.size());
+
+    if (new_memc)
+    {
+      memcached_free(memc_);
+      memc_= new_memc;
+
+      return true;
+    }
+
+    return false;
+  }
+
+  /**
+   * Add a server to the list of memcached servers to use.
+   *
+   * @param[in] server_name name of the server to add
+   * @param[in] port port number of server to add
+   * @return true on success; false otherwise
+   */
+  bool addServer(const std::string &server_name, in_port_t port)
+  {
+    return memcached_success(memcached_server_add(memc_, server_name.c_str(), port));
+  }
+
+  /**
+   * Remove a server from the list of memcached servers to use.
+   *
+   * @param[in] server_name name of the server to remove
+   * @param[in] port port number of server to remove
+   * @return true on success; false otherwise
+   */
+  bool removeServer(const std::string &server_name, in_port_t port)
+  {
+    std::string tmp_str;
+    std::ostringstream strstm;
+    tmp_str.append(",");
+    tmp_str.append(server_name);
+    tmp_str.append(":");
+    strstm << port;
+    tmp_str.append(strstm.str());
+
+    //memcached_return_t rc= memcached_server_remove(server);
+    
+    return false;
+  }
+
+  /**
+   * Fetches an individual value from the server. mget() must always
+   * be called before using this method.
+   *
+   * @param[in] key key of object to fetch
+   * @param[out] ret_val store returned object in this vector
+   * @return a memcached return structure
+   */
+  memcached_return_t fetch(std::string &key,
+                           std::vector<char> &ret_val,
+                           uint32_t &flags,
+                           uint64_t &cas_value)
+  {
+    memcached_return_t rc;
+
+    memcached_result_st *result;
+    if ((result= memcached_fetch_result(memc_, NULL, &rc)))
+    {
+      // Key
+      key.assign(memcached_result_key_value(result), memcached_result_key_length(result));
+
+      // Actual value, null terminated
+      ret_val.reserve(memcached_result_length(result) +1);
+      ret_val.assign(memcached_result_value(result),
+                     memcached_result_value(result) +memcached_result_length(result) +1);
+      ret_val.resize(memcached_result_length(result));
+
+      // Misc
+      flags= memcached_result_flags(result);
+      cas_value= memcached_result_cas(result);
+    }
+    memcached_result_free(result);
+
+    return rc;
+  }
+
+  memcached_return_t fetch(std::string &key,
+                           std::vector<char> &ret_val)
+  {
+    uint32_t flags= 0;
+    uint64_t cas_value= 0;
+
+    return fetch(key, ret_val, flags, cas_value);
+  }
+
+  /**
+   * Fetches an individual value from the server.
+   *
+   * @param[in] key key of object whose value to get
+   * @param[out] ret_val object that is retrieved is stored in
+   *                     this vector
+   * @return true on success; false otherwise
+   */
+  bool get(const std::string &key, std::vector<char> &ret_val)
+  {
+    uint32_t flags= 0;
+    memcached_return_t rc;
+    size_t value_length= 0;
+
+    char *value= memcached_get(memc_, key.c_str(), key.length(),
+                               &value_length, &flags, &rc);
+    if (value != NULL && ret_val.empty())
+    {
+      ret_val.reserve(value_length +1); // Always provide null
+      ret_val.assign(value, value +value_length +1);
+      ret_val.resize(value_length);
+      free(value);
+
+      return true;
+    }
+
+    return false;
+  }
+
+  /**
+   * Fetches an individual from a server which is specified by
+   * the master_key parameter that is used for determining which
+   * server an object was stored in if key partitioning was
+   * used for storage.
+   *
+   * @param[in] master_key key that specifies server object is stored on
+   * @param[in] key key of object whose value to get
+   * @param[out] ret_val object that is retrieved is stored in
+   *                     this vector
+   * @return true on success; false otherwise
+   */
+  bool getByKey(const std::string &master_key,
+                const std::string &key,
+                std::vector<char> &ret_val)
+  {
+    uint32_t flags= 0;
+    memcached_return_t rc;
+    size_t value_length= 0;
+
+    char *value= memcached_get_by_key(memc_,
+                                      master_key.c_str(), master_key.length(),
+                                      key.c_str(), key.length(),
+                                      &value_length, &flags, &rc);
+    if (value)
+    {
+      ret_val.reserve(value_length +1); // Always provide null
+      ret_val.assign(value, value +value_length +1);
+      ret_val.resize(value_length);
+      free(value);
+
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Selects multiple keys at once. This method always
+   * works asynchronously.
+   *
+   * @param[in] keys vector of keys to select
+   * @return true if all keys are found
+   */
+  bool mget(const std::vector<std::string>& keys)
+  {
+    std::vector<const char *> real_keys;
+    std::vector<size_t> key_len;
+    /*
+     * Construct an array which will contain the length
+     * of each of the strings in the input vector. Also, to
+     * interface with the memcached C API, we need to convert
+     * the vector of std::string's to a vector of char *.
+     */
+    real_keys.reserve(keys.size());
+    key_len.reserve(keys.size());
+
+    std::vector<std::string>::const_iterator it= keys.begin();
+
+    while (it != keys.end())
+    {
+      real_keys.push_back(const_cast<char *>((*it).c_str()));
+      key_len.push_back((*it).length());
+      ++it;
+    }
+
+    /*
+     * If the std::vector of keys is empty then we cannot
+     * call memcached_mget as we will get undefined behavior.
+     */
+    if (not real_keys.empty())
+    {
+      return memcached_success(memcached_mget(memc_, &real_keys[0], &key_len[0], real_keys.size()));
+    }
+
+    return false;
+  }
+
+  /**
+   * Writes an object to the server. If the object already exists, it will
+   * overwrite the existing object. This method always returns true
+   * when using non-blocking mode unless a network error occurs.
+   *
+   * @param[in] key key of object to write to server
+   * @param[in] value value of object to write to server
+   * @param[in] expiration time to keep the object stored in the server for
+   * @param[in] flags flags to store with the object
+   * @return true on succcess; false otherwise
+   */
+  bool set(const std::string &key,
+           const std::vector<char> &value,
+           time_t expiration,
+           uint32_t flags)
+  {
+    memcached_return_t rc= memcached_set(memc_,
+                                         key.c_str(), key.length(),
+                                         value.data(), value.size(),
+                                         expiration, flags);
+    return memcached_success(rc);
+  }
+
+  bool set(const std::string &key,
+           const char* value, const size_t value_length,
+           time_t expiration,
+           uint32_t flags)
+  {
+    memcached_return_t rc= memcached_set(memc_,
+                                         key.c_str(), key.length(),
+                                         value, value_length,
+                                         expiration, flags);
+    return memcached_success(rc);
+  }
+
+  /**
+   * Writes an object to a server specified by the master_key parameter.
+   * If the object already exists, it will overwrite the existing object.
+   *
+   * @param[in] master_key key that specifies server to write to
+   * @param[in] key key of object to write to server
+   * @param[in] value value of object to write to server
+   * @param[in] expiration time to keep the object stored in the server for
+   * @param[in] flags flags to store with the object
+   * @return true on succcess; false otherwise
+   */
+  bool setByKey(const std::string& master_key,
+                const std::string& key,
+                const std::vector<char> &value,
+                time_t expiration,
+                uint32_t flags)
+  {
+    return memcached_success(memcached_set_by_key(memc_, master_key.c_str(),
+                                                  master_key.length(),
+                                                  key.c_str(), key.length(),
+                                                  &value[0], value.size(),
+                                                  expiration,
+                                                  flags));
+  }
+
+  /**
+   * Writes a list of objects to the server. Objects are specified by
+   * 2 vectors - 1 vector of keys and 1 vector of values.
+   *
+   * @param[in] keys vector of keys of objects to write to server
+   * @param[in] values vector of values of objects to write to server
+   * @param[in] expiration time to keep the objects stored in server for
+   * @param[in] flags flags to store with the objects
+   * @return true on success; false otherwise
+   */
+  bool setAll(const std::vector<std::string>& keys,
+              const std::vector< std::vector<char> *>& values,
+              time_t expiration,
+              uint32_t flags)
+  {
+    bool retval= true;
+    std::vector<std::string>::const_iterator key_it= keys.begin();
+    std::vector< std::vector<char> *>::const_iterator val_it= values.begin();
+    while (key_it != keys.end())
+    {
+      retval= set((*key_it), *(*val_it), expiration, flags);
+      if (retval == false)
+      {
+        return retval;
+      }
+      ++key_it;
+      ++val_it;
+    }
+    return retval;
+  }
+
+  /**
+   * Writes a list of objects to the server. Objects are specified by
+   * a map of keys to values.
+   *
+   * @param[in] key_value_map map of keys and values to store in server
+   * @param[in] expiration time to keep the objects stored in server for
+   * @param[in] flags flags to store with the objects
+   * @return true on success; false otherwise
+   */
+  bool setAll(const std::map<const std::string, std::vector<char> >& key_value_map,
+              time_t expiration,
+              uint32_t flags)
+  {
+    std::map<const std::string, std::vector<char> >::const_iterator it= key_value_map.begin();
+
+    while (it != key_value_map.end())
+    {
+      if (!set(it->first, it->second, expiration, flags))
+      {
+        // We should tell the user what the key that failed was
+        return false;
+      }
+      ++it;
+    }
+
+    return true;
+  }
+
+  /**
+   * Increment the value of the object associated with the specified
+   * key by the offset given. The resulting value is saved in the value
+   * parameter.
+   *
+   * @param[in] key key of object in server whose value to increment
+   * @param[in] offset amount to increment object's value by
+   * @param[out] value store the result of the increment here
+   * @return true on success; false otherwise
+   */
+  bool increment(const std::string& key, uint32_t offset, uint64_t *value)
+  {
+    return memcached_success(memcached_increment(memc_, key.c_str(), key.length(), offset, value));
+  }
+
+  /**
+   * Decrement the value of the object associated with the specified
+   * key by the offset given. The resulting value is saved in the value
+   * parameter.
+   *
+   * @param[in] key key of object in server whose value to decrement
+   * @param[in] offset amount to increment object's value by
+   * @param[out] value store the result of the decrement here
+   * @return true on success; false otherwise
+   */
+  bool decrement(const std::string& key, uint32_t offset, uint64_t *value)
+  {
+    return memcached_success(memcached_decrement(memc_, key.c_str(),
+                                                 key.length(),
+                                                 offset, value));
+  }
+
+
+  /**
+   * Add an object with the specified key and value to the server. This
+   * function returns false if the object already exists on the server.
+   *
+   * @param[in] key key of object to add
+   * @param[in] value of object to add
+   * @return true on success; false otherwise
+   */
+  bool add(const std::string& key, const std::vector<char>& value)
+  {
+    return memcached_success(memcached_add(memc_, key.c_str(), key.length(),
+                                           &value[0], value.size(), 0, 0));
+  }
+
+  /**
+   * Add an object with the specified key and value to the server. This
+   * function returns false if the object already exists on the server. The
+   * server to add the object to is specified by the master_key parameter.
+   *
+   * @param[in[ master_key key of server to add object to
+   * @param[in] key key of object to add
+   * @param[in] value of object to add
+   * @return true on success; false otherwise
+   */
+  bool addByKey(const std::string& master_key,
+                const std::string& key,
+                const std::vector<char>& value)
+  {
+    return memcached_success(memcached_add_by_key(memc_,
+                                                  master_key.c_str(),
+                                                  master_key.length(),
+                                                  key.c_str(),
+                                                  key.length(),
+                                                  &value[0],
+                                                  value.size(),
+                                                  0, 0));
+  }
+
+  /**
+   * Replaces an object on the server. This method only succeeds
+   * if the object is already present on the server.
+   *
+   * @param[in] key key of object to replace
+   * @param[in[ value value to replace object with
+   * @return true on success; false otherwise
+   */
+  bool replace(const std::string& key, const std::vector<char>& value)
+  {
+    return memcached_success(memcached_replace(memc_, key.c_str(), key.length(),
+                                               &value[0], value.size(),
+                                               0, 0));
+  }
+
+  /**
+   * Replaces an object on the server. This method only succeeds
+   * if the object is already present on the server. The server
+   * to replace the object on is specified by the master_key param.
+   *
+   * @param[in] master_key key of server to replace object on
+   * @param[in] key key of object to replace
+   * @param[in[ value value to replace object with
+   * @return true on success; false otherwise
+   */
+  bool replaceByKey(const std::string& master_key,
+                    const std::string& key,
+                    const std::vector<char>& value)
+  {
+    return memcached_success(memcached_replace_by_key(memc_,
+                                                      master_key.c_str(),
+                                                      master_key.length(),
+                                                      key.c_str(),
+                                                      key.length(),
+                                                      &value[0],
+                                                      value.size(),
+                                                      0, 0));
+  }
+
+  /**
+   * Places a segment of data before the last piece of data stored.
+   *
+   * @param[in] key key of object whose value we will prepend data to
+   * @param[in] value data to prepend to object's value
+   * @return true on success; false otherwise
+   */
+  bool prepend(const std::string& key, const std::vector<char>& value)
+  {
+    return memcached_success(memcached_prepend(memc_, key.c_str(), key.length(),
+                                               &value[0], value.size(), 0, 0));
+  }
+
+  /**
+   * Places a segment of data before the last piece of data stored. The
+   * server on which the object where we will be prepending data is stored
+   * on is specified by the master_key parameter.
+   *
+   * @param[in] master_key key of server where object is stored
+   * @param[in] key key of object whose value we will prepend data to
+   * @param[in] value data to prepend to object's value
+   * @return true on success; false otherwise
+   */
+  bool prependByKey(const std::string& master_key,
+                    const std::string& key,
+                    const std::vector<char>& value)
+  {
+    return memcached_success(memcached_prepend_by_key(memc_,
+                                                      master_key.c_str(),
+                                                      master_key.length(),
+                                                      key.c_str(),
+                                                      key.length(),
+                                                      &value[0],
+                                                      value.size(),
+                                                      0,
+                                                      0));
+  }
+
+  /**
+   * Places a segment of data at the end of the last piece of data stored.
+   *
+   * @param[in] key key of object whose value we will append data to
+   * @param[in] value data to append to object's value
+   * @return true on success; false otherwise
+   */
+  bool append(const std::string& key, const std::vector<char>& value)
+  {
+    return memcached_success(memcached_append(memc_,
+                                              key.c_str(),
+                                              key.length(),
+                                              &value[0],
+                                              value.size(),
+                                              0, 0));
+  }
+
+  /**
+   * Places a segment of data at the end of the last piece of data stored. The
+   * server on which the object where we will be appending data is stored
+   * on is specified by the master_key parameter.
+   *
+   * @param[in] master_key key of server where object is stored
+   * @param[in] key key of object whose value we will append data to
+   * @param[in] value data to append to object's value
+   * @return true on success; false otherwise
+   */
+  bool appendByKey(const std::string& master_key,
+                   const std::string& key,
+                   const std::vector<char> &value)
+  {
+    return memcached_success(memcached_append_by_key(memc_,
+                                                     master_key.c_str(),
+                                                     master_key.length(),
+                                                     key.c_str(),
+                                                     key.length(),
+                                                     &value[0],
+                                                     value.size(),
+                                                     0, 0));
+  }
+
+  /**
+   * Overwrite data in the server as long as the cas_arg value
+   * is still the same in the server.
+   *
+   * @param[in] key key of object in server
+   * @param[in] value value to store for object in server
+   * @param[in] cas_arg "cas" value
+   */
+  bool cas(const std::string& key,
+           const std::vector<char>& value,
+           uint64_t cas_arg)
+  {
+    return memcached_success(memcached_cas(memc_, key.c_str(), key.length(),
+                                           &value[0], value.size(),
+                                           0, 0, cas_arg));
+  }
+
+  /**
+   * Overwrite data in the server as long as the cas_arg value
+   * is still the same in the server. The server to use is
+   * specified by the master_key parameter.
+   *
+   * @param[in] master_key specifies server to operate on
+   * @param[in] key key of object in server
+   * @param[in] value value to store for object in server
+   * @param[in] cas_arg "cas" value
+   */
+  bool casByKey(const std::string& master_key,
+                const std::string& key,
+                const std::vector<char> &value,
+                uint64_t cas_arg)
+  {
+    return memcached_success(memcached_cas_by_key(memc_,
+                                                  master_key.c_str(),
+                                                  master_key.length(),
+                                                  key.c_str(),
+                                                  key.length(),
+                                                  &value[0],
+                                                  value.size(),
+                                                  0, 0, cas_arg));
+  }
+
+  /**
+   * Delete an object from the server specified by the key given.
+   *
+   * @param[in] key key of object to delete
+   * @return true on success; false otherwise
+   */
+  bool remove(const std::string& key)
+  {
+    return memcached_success(memcached_delete(memc_, key.c_str(), key.length(), 0));
+  }
+
+  /**
+   * Delete an object from the server specified by the key given.
+   *
+   * @param[in] key key of object to delete
+   * @param[in] expiration time to delete the object after
+   * @return true on success; false otherwise
+   */
+  bool remove(const std::string& key, time_t expiration)
+  {
+    return memcached_success(memcached_delete(memc_,
+                                              key.c_str(),
+                                              key.length(),
+                                              expiration));
+  }
+
+  /**
+   * Delete an object from the server specified by the key given.
+   *
+   * @param[in] master_key specifies server to remove object from
+   * @param[in] key key of object to delete
+   * @return true on success; false otherwise
+   */
+  bool removeByKey(const std::string& master_key,
+                   const std::string& key)
+  {
+    return memcached_success(memcached_delete_by_key(memc_,
+                                                     master_key.c_str(),
+                                                     master_key.length(),
+                                                     key.c_str(),
+                                                     key.length(),
+                                                     0));
+  }
+
+  /**
+   * Delete an object from the server specified by the key given.
+   *
+   * @param[in] master_key specifies server to remove object from
+   * @param[in] key key of object to delete
+   * @param[in] expiration time to delete the object after
+   * @return true on success; false otherwise
+   */
+  bool removeByKey(const std::string& master_key,
+                   const std::string& key,
+                   time_t expiration)
+  {
+    return memcached_success(memcached_delete_by_key(memc_,
+                                                     master_key.c_str(),
+                                                     master_key.length(),
+                                                     key.c_str(),
+                                                     key.length(),
+                                                     expiration));
+  }
+
+  /**
+   * Wipe the contents of memcached servers.
+   *
+   * @param[in] expiration time to wait until wiping contents of
+   *                       memcached servers
+   * @return true on success; false otherwise
+   */
+  bool flush(time_t expiration= 0)
+  {
+    return memcached_success(memcached_flush(memc_, expiration));
+  }
+
+  /**
+   * Get the library version string.
+   * @return std::string containing a copy of the library version string.
+   */
+  const std::string libVersion() const
+  {
+    const char *ver= memcached_lib_version();
+    const std::string version(ver);
+    return version;
+  }
+
+  /**
+   * Retrieve memcached statistics. Populate a std::map with the retrieved
+   * stats. Each server will map to another std::map of the key:value stats.
+   *
+   * @param[out] stats_map a std::map to be populated with the memcached
+   *                       stats
+   * @return true on success; false otherwise
+   */
+  bool getStats(std::map< std::string, std::map<std::string, std::string> >& stats_map)
+  {
+    memcached_return_t rc;
+    memcached_stat_st *stats= memcached_stat(memc_, NULL, &rc);
+
+    if (rc != MEMCACHED_SUCCESS &&
+        rc != MEMCACHED_SOME_ERRORS)
+    {
+      return false;
+    }
+
+    uint32_t server_count= memcached_server_count(memc_);
+
+    /*
+     * For each memcached server, construct a std::map for its stats and add
+     * it to the std::map of overall stats.
+     */
+    for (uint32_t x= 0; x < server_count; x++)
+    {
+      const memcached_instance_st * instance= memcached_server_instance_by_position(memc_, x);
+      std::ostringstream strstm;
+      std::string server_name(memcached_server_name(instance));
+      server_name.append(":");
+      strstm << memcached_server_port(instance);
+      server_name.append(strstm.str());
+
+      std::map<std::string, std::string> server_stats;
+      char **list= memcached_stat_get_keys(memc_, &stats[x], &rc);
+      for (char** ptr= list; *ptr; ptr++)
+      {
+        char *value= memcached_stat_get_value(memc_, &stats[x], *ptr, &rc);
+        server_stats[*ptr]= value;
+        free(value);
+      }
+     
+      stats_map[server_name]= server_stats;
+      free(list);
+    }
+
+    memcached_stat_free(memc_, stats);
+    return true;
+  }
+
+private:
+  memcached_st *memc_;
+};
+
+}
diff --git a/include/libmemcached-1.0/options.h b/include/libmemcached-1.0/options.h
new file mode 100644 (file)
index 0000000..f5a6e06
--- /dev/null
@@ -0,0 +1,49 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+  memcached_return_t libmemcached_check_configuration(const char *option_string, size_t length, char *error_buffer, size_t error_buffer_size);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/parse.h b/include/libmemcached-1.0/parse.h
new file mode 100644 (file)
index 0000000..a91f769
--- /dev/null
@@ -0,0 +1,23 @@
+/* LibMemcached
+ * Copyright (C) 2010 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Work with fetching results
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_server_list_st memcached_servers_parse(const char *server_strings);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/platform.h b/include/libmemcached-1.0/platform.h
new file mode 100644 (file)
index 0000000..efdf53f
--- /dev/null
@@ -0,0 +1,62 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#if defined(_WIN32)
+# include <winsock2.h>
+# include <ws2tcpip.h>
+
+#ifndef HAVE_IN_PORT_T
+typedef int in_port_t;
+# define HAVE_IN_PORT_T 1
+#endif
+
+typedef SOCKET memcached_socket_t;
+
+#else
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+# include <sys/un.h>
+# include <netinet/tcp.h>
+
+typedef int memcached_socket_t;
+
+#endif /* _WIN32 */
diff --git a/include/libmemcached-1.0/quit.h b/include/libmemcached-1.0/quit.h
new file mode 100644 (file)
index 0000000..90ff3ff
--- /dev/null
@@ -0,0 +1,49 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+void memcached_quit(memcached_st *ptr);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/result.h b/include/libmemcached-1.0/result.h
new file mode 100644 (file)
index 0000000..615957f
--- /dev/null
@@ -0,0 +1,89 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached-1.0/struct/result.h>
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Result Struct */
+LIBMEMCACHED_API
+void memcached_result_free(memcached_result_st *result);
+
+LIBMEMCACHED_API
+void memcached_result_reset(memcached_result_st *ptr);
+
+LIBMEMCACHED_API
+memcached_result_st *memcached_result_create(const memcached_st *ptr,
+                                             memcached_result_st *result);
+
+LIBMEMCACHED_API
+const char *memcached_result_key_value(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+size_t memcached_result_key_length(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+const char *memcached_result_value(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+char *memcached_result_take_value(memcached_result_st *self);
+
+LIBMEMCACHED_API
+size_t memcached_result_length(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+uint32_t memcached_result_flags(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+uint64_t memcached_result_cas(const memcached_result_st *self);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_result_set_value(memcached_result_st *ptr, const char *value, size_t length);
+
+LIBMEMCACHED_API
+void memcached_result_set_flags(memcached_result_st *self, uint32_t flags);
+
+LIBMEMCACHED_API
+void memcached_result_set_expiration(memcached_result_st *self, time_t expiration);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/include/libmemcached-1.0/return.h b/include/libmemcached-1.0/return.h
new file mode 100644 (file)
index 0000000..e2b4104
--- /dev/null
@@ -0,0 +1,84 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+static inline bool memcached_success(memcached_return_t rc)
+{
+  return (rc == MEMCACHED_BUFFERED ||
+          rc == MEMCACHED_DELETED ||
+          rc == MEMCACHED_END || 
+          rc == MEMCACHED_ITEM || 
+          rc == MEMCACHED_STAT || 
+          rc == MEMCACHED_STORED || 
+          rc == MEMCACHED_SUCCESS || 
+          rc == MEMCACHED_VALUE);
+}
+
+static inline bool memcached_failed(memcached_return_t rc)
+{
+  return (rc != MEMCACHED_AUTH_CONTINUE &&
+          rc != MEMCACHED_BUFFERED &&
+          rc != MEMCACHED_DELETED &&
+          rc != MEMCACHED_END && 
+          rc != MEMCACHED_ITEM &&
+          rc != MEMCACHED_STAT &&
+          rc != MEMCACHED_STORED && 
+          rc != MEMCACHED_SUCCESS &&
+          rc != MEMCACHED_VALUE);
+}
+
+static inline bool memcached_fatal(memcached_return_t rc)
+{
+  return (rc != MEMCACHED_AUTH_CONTINUE &&
+          rc != MEMCACHED_BUFFERED &&
+          rc != MEMCACHED_CLIENT_ERROR &&
+          rc != MEMCACHED_DATA_EXISTS &&
+          rc != MEMCACHED_DELETED &&
+          rc != MEMCACHED_E2BIG && 
+          rc != MEMCACHED_END && 
+          rc != MEMCACHED_ITEM &&
+          rc != MEMCACHED_ERROR &&
+          rc != MEMCACHED_NOTFOUND && 
+          rc != MEMCACHED_NOTSTORED && 
+          rc != MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE && 
+          rc != MEMCACHED_STAT && 
+          rc != MEMCACHED_STORED && 
+          rc != MEMCACHED_SUCCESS && 
+          rc != MEMCACHED_VALUE);
+}
+
+#define memcached_continue(__memcached_return_t) ((__memcached_return_t) == MEMCACHED_IN_PROGRESS)
diff --git a/include/libmemcached-1.0/sasl.h b/include/libmemcached-1.0/sasl.h
new file mode 100644 (file)
index 0000000..c308421
--- /dev/null
@@ -0,0 +1,70 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
+#include <sasl/sasl.h>
+#else
+#define sasl_callback_t void
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+void memcached_set_sasl_callbacks(memcached_st *ptr,
+                                  const sasl_callback_t *callbacks);
+
+LIBMEMCACHED_API
+memcached_return_t  memcached_set_sasl_auth_data(memcached_st *ptr,
+                                                 const char *username,
+                                                 const char *password);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *ptr);
+
+
+LIBMEMCACHED_API
+sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *ptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <libmemcached-1.0/struct/sasl.h>
diff --git a/include/libmemcached-1.0/server.h b/include/libmemcached-1.0/server.h
new file mode 100644 (file)
index 0000000..abd0bfb
--- /dev/null
@@ -0,0 +1,126 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#include <libmemcached-1.0/struct/server.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_server_cursor(const memcached_st *ptr,
+                                           const memcached_server_fn *callback,
+                                           void *context,
+                                           uint32_t number_of_callbacks);
+
+LIBMEMCACHED_API
+  const memcached_instance_st * memcached_server_by_key(memcached_st *ptr,
+                                                       const char *key,
+                                                       size_t key_length,
+                                                       memcached_return_t *error);
+
+LIBMEMCACHED_API
+void memcached_server_error_reset(memcached_server_st *ptr);
+
+LIBMEMCACHED_API
+void memcached_server_free(memcached_server_st *ptr);
+
+LIBMEMCACHED_API
+const memcached_instance_st * memcached_server_get_last_disconnect(const memcached_st *ptr);
+
+
+LIBMEMCACHED_API
+memcached_return_t memcached_server_add_udp(memcached_st *ptr,
+                                            const char *hostname,
+                                            in_port_t port);
+LIBMEMCACHED_API
+memcached_return_t memcached_server_add_unix_socket(memcached_st *ptr,
+                                                    const char *filename);
+LIBMEMCACHED_API
+memcached_return_t memcached_server_add(memcached_st *ptr,
+                                        const char *hostname, in_port_t port);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_server_add_udp_with_weight(memcached_st *ptr,
+                                                        const char *hostname,
+                                                        in_port_t port,
+                                                        uint32_t weight);
+LIBMEMCACHED_API
+memcached_return_t memcached_server_add_unix_socket_with_weight(memcached_st *ptr,
+                                                                const char *filename,
+                                                                uint32_t weight);
+LIBMEMCACHED_API
+memcached_return_t memcached_server_add_with_weight(memcached_st *ptr, const char *hostname,
+                                                    in_port_t port,
+                                                    uint32_t weight);
+
+/**
+  Operations on Single Servers.
+*/
+LIBMEMCACHED_API
+uint32_t memcached_server_response_count(const memcached_instance_st * self);
+
+LIBMEMCACHED_API
+const char *memcached_server_name(const memcached_instance_st * self);
+
+LIBMEMCACHED_API
+in_port_t memcached_server_port(const memcached_instance_st * self);
+
+LIBMEMCACHED_API
+in_port_t memcached_server_srcport(const memcached_instance_st * self);
+
+LIBMEMCACHED_API
+void memcached_instance_next_retry(const memcached_instance_st * self, const time_t absolute_time);
+
+LIBMEMCACHED_API
+const char *memcached_server_type(const memcached_instance_st * ptr);
+
+LIBMEMCACHED_API
+uint8_t memcached_server_major_version(const memcached_instance_st * ptr);
+
+LIBMEMCACHED_API
+uint8_t memcached_server_minor_version(const memcached_instance_st * ptr);
+
+LIBMEMCACHED_API
+uint8_t memcached_server_micro_version(const memcached_instance_st * ptr);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/include/libmemcached-1.0/server_list.h b/include/libmemcached-1.0/server_list.h
new file mode 100644 (file)
index 0000000..04bebab
--- /dev/null
@@ -0,0 +1,68 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Server List Public functions */
+LIBMEMCACHED_API
+  void memcached_server_list_free(memcached_server_list_st ptr);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_server_list_st list);
+
+LIBMEMCACHED_API
+  memcached_server_list_st memcached_server_list_append(memcached_server_list_st ptr,
+                                                        const char *hostname,
+                                                        in_port_t port,
+                                                        memcached_return_t *error);
+LIBMEMCACHED_API
+  memcached_server_list_st memcached_server_list_append_with_weight(memcached_server_list_st ptr,
+                                                                    const char *hostname,
+                                                                    in_port_t port,
+                                                                    uint32_t weight,
+                                                                    memcached_return_t *error);
+LIBMEMCACHED_API
+  uint32_t memcached_server_list_count(const memcached_server_list_st ptr);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/include/libmemcached-1.0/stats.h b/include/libmemcached-1.0/stats.h
new file mode 100644 (file)
index 0000000..708064f
--- /dev/null
@@ -0,0 +1,69 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached-1.0/struct/stat.h>
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+void memcached_stat_free(const memcached_st *, memcached_stat_st *);
+
+LIBMEMCACHED_API
+memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_stat_servername(memcached_stat_st *memc_stat, char *args,
+                                             const char *hostname, in_port_t port);
+
+LIBMEMCACHED_API
+char *memcached_stat_get_value(const memcached_st *ptr, memcached_stat_st *memc_stat,
+                               const char *key, memcached_return_t *error);
+
+LIBMEMCACHED_API
+char ** memcached_stat_get_keys(memcached_st *ptr, memcached_stat_st *memc_stat,
+                                memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_stat_execute(memcached_st *memc, const char *args,  memcached_stat_fn func, void *context);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/include/libmemcached-1.0/storage.h b/include/libmemcached-1.0/storage.h
new file mode 100644 (file)
index 0000000..e634235
--- /dev/null
@@ -0,0 +1,131 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* All of the functions for adding data to the server */
+LIBMEMCACHED_API
+memcached_return_t memcached_set(memcached_st *ptr, const char *key, size_t key_length,
+                                 const char *value, size_t value_length,
+                                 time_t expiration,
+                                 uint32_t  flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_add(memcached_st *ptr, const char *key, size_t key_length,
+                                 const char *value, size_t value_length,
+                                 time_t expiration,
+                                 uint32_t  flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_replace(memcached_st *ptr, const char *key, size_t key_length,
+                                     const char *value, size_t value_length,
+                                     time_t expiration,
+                                     uint32_t  flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_append(memcached_st *ptr,
+                                    const char *key, size_t key_length,
+                                    const char *value, size_t value_length,
+                                    time_t expiration,
+                                    uint32_t flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_prepend(memcached_st *ptr,
+                                     const char *key, size_t key_length,
+                                     const char *value, size_t value_length,
+                                     time_t expiration,
+                                     uint32_t flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_cas(memcached_st *ptr,
+                                 const char *key, size_t key_length,
+                                 const char *value, size_t value_length,
+                                 time_t expiration,
+                                 uint32_t flags,
+                                 uint64_t cas);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_set_by_key(memcached_st *ptr,
+                                        const char *group_key, size_t group_key_length,
+                                        const char *key, size_t key_length,
+                                        const char *value, size_t value_length,
+                                        time_t expiration,
+                                        uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_add_by_key(memcached_st *ptr,
+                                        const char *group_key, size_t group_key_length,
+                                        const char *key, size_t key_length,
+                                        const char *value, size_t value_length,
+                                        time_t expiration,
+                                        uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_replace_by_key(memcached_st *ptr,
+                                            const char *group_key, size_t group_key_length,
+                                            const char *key, size_t key_length,
+                                            const char *value, size_t value_length,
+                                            time_t expiration,
+                                            uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_prepend_by_key(memcached_st *ptr,
+                                            const char *group_key, size_t group_key_length,
+                                            const char *key, size_t key_length,
+                                            const char *value, size_t value_length,
+                                            time_t expiration,
+                                            uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_append_by_key(memcached_st *ptr,
+                                           const char *group_key, size_t group_key_length,
+                                           const char *key, size_t key_length,
+                                           const char *value, size_t value_length,
+                                           time_t expiration,
+                                           uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_cas_by_key(memcached_st *ptr,
+                                        const char *group_key, size_t group_key_length,
+                                        const char *key, size_t key_length,
+                                        const char *value, size_t value_length,
+                                        time_t expiration,
+                                        uint32_t flags,
+                                        uint64_t cas);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/strerror.h b/include/libmemcached-1.0/strerror.h
new file mode 100644 (file)
index 0000000..16bf424
--- /dev/null
@@ -0,0 +1,50 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+const char *memcached_strerror(const memcached_st *ptr, memcached_return_t rc);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/struct/allocator.h b/include/libmemcached-1.0/struct/allocator.h
new file mode 100644 (file)
index 0000000..3ff6ade
--- /dev/null
@@ -0,0 +1,46 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+struct memcached_allocator_t {
+  memcached_calloc_fn calloc;
+  memcached_free_fn free;
+  memcached_malloc_fn malloc;
+  memcached_realloc_fn realloc;
+  void *context;
+};
diff --git a/include/libmemcached-1.0/struct/analysis.h b/include/libmemcached-1.0/struct/analysis.h
new file mode 100644 (file)
index 0000000..09ccced
--- /dev/null
@@ -0,0 +1,51 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+struct memcached_analysis_st {
+  memcached_st *root;
+  uint32_t average_item_size;
+  uint32_t longest_uptime;
+  uint32_t least_free_server;
+  uint32_t most_consumed_server;
+  uint32_t oldest_server;
+  double pool_hit_ratio;
+  uint64_t most_used_bytes;
+  uint64_t least_remaining_bytes;
+};
+
diff --git a/include/libmemcached-1.0/struct/callback.h b/include/libmemcached-1.0/struct/callback.h
new file mode 100644 (file)
index 0000000..21b9676
--- /dev/null
@@ -0,0 +1,44 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+struct memcached_callback_st {
+  memcached_execute_fn *callback;
+  void *context;
+  uint32_t number_of_callback;
+};
diff --git a/include/libmemcached-1.0/struct/memcached.h b/include/libmemcached-1.0/struct/memcached.h
new file mode 100644 (file)
index 0000000..a368bfe
--- /dev/null
@@ -0,0 +1,128 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+struct memcached_st {
+  /**
+    @note these are static and should not change without a call to behavior.
+  */
+  struct {
+    bool is_purging:1;
+    bool is_processing_input:1;
+    bool is_time_for_rebuild:1;
+    bool is_parsing:1;
+  } state;
+
+  struct {
+    // Everything below here is pretty static.
+    bool auto_eject_hosts:1;
+    bool binary_protocol:1;
+    bool buffer_requests:1;
+    bool hash_with_namespace:1;
+    bool no_block:1; // Don't block
+    bool reply:1;
+    bool randomize_replica_read:1;
+    bool support_cas:1;
+    bool tcp_nodelay:1;
+    bool use_sort_hosts:1;
+    bool use_udp:1;
+    bool verify_key:1;
+    bool tcp_keepalive:1;
+    bool is_aes:1;
+    bool is_fetching_version:1;
+    bool not_used:1;
+  } flags;
+
+  memcached_server_distribution_t distribution;
+  hashkit_st hashkit;
+  struct {
+    unsigned int version;
+  } server_info;
+  uint32_t number_of_hosts;
+  memcached_instance_st *servers;
+  memcached_instance_st *last_disconnected_server;
+  int32_t snd_timeout;
+  int32_t rcv_timeout;
+  uint32_t server_failure_limit;
+  uint32_t server_timeout_limit;
+  uint32_t io_msg_watermark;
+  uint32_t io_bytes_watermark;
+  uint32_t io_key_prefetch;
+  uint32_t tcp_keepidle;
+  int32_t poll_timeout;
+  int32_t connect_timeout; // How long we will wait on connect() before we will timeout
+  int32_t retry_timeout;
+  int32_t dead_timeout;
+  int send_size;
+  int recv_size;
+  void *user_data;
+  uint64_t query_id;
+  uint32_t number_of_replicas;
+  memcached_result_st result;
+
+  struct {
+    bool weighted_;
+    uint32_t continuum_count; // Ketama
+    uint32_t continuum_points_counter; // Ketama
+    time_t next_distribution_rebuild; // Ketama
+    struct memcached_continuum_item_st *continuum; // Ketama
+  } ketama;
+
+  struct memcached_virtual_bucket_t *virtual_bucket;
+
+  struct memcached_allocator_t allocators;
+
+  memcached_clone_fn on_clone;
+  memcached_cleanup_fn on_cleanup;
+  memcached_trigger_key_fn get_key_failure;
+  memcached_trigger_delete_key_fn delete_trigger;
+  memcached_callback_st *callbacks;
+  struct memcached_sasl_st sasl;
+  struct memcached_error_t *error_messages;
+  struct memcached_array_st *_namespace;
+  struct {
+    uint32_t initial_pool_size;
+    uint32_t max_pool_size;
+    int32_t version; // This is used by pool and others to determine if the memcached_st is out of date.
+    struct memcached_array_st *filename;
+  } configure;
+  struct {
+    bool is_allocated:1;
+  } options;
+
+};
diff --git a/include/libmemcached-1.0/struct/result.h b/include/libmemcached-1.0/struct/result.h
new file mode 100644 (file)
index 0000000..c3bfddb
--- /dev/null
@@ -0,0 +1,56 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+struct memcached_result_st {
+  uint32_t item_flags;
+  time_t item_expiration;
+  size_t key_length;
+  uint64_t item_cas;
+  struct memcached_st *root;
+  memcached_string_st value;
+  uint64_t numeric_value;
+  uint64_t count;
+  char item_key[MEMCACHED_MAX_KEY];
+  struct {
+    bool is_allocated:1;
+    bool is_initialized:1;
+  } options;
+  /* Add result callback function */
+};
+
diff --git a/include/libmemcached-1.0/struct/sasl.h b/include/libmemcached-1.0/struct/sasl.h
new file mode 100644 (file)
index 0000000..da9eed3
--- /dev/null
@@ -0,0 +1,54 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
+#include <sasl/sasl.h>
+#else
+#define sasl_callback_t void
+#endif
+
+#pragma once
+
+struct memcached_sasl_st {
+  sasl_callback_t *callbacks;
+  /*
+   ** Did we allocate data inside the callbacks, or did the user
+   ** supply that.
+ */
+  bool is_allocated;
+};
+
diff --git a/include/libmemcached-1.0/struct/server.h b/include/libmemcached-1.0/struct/server.h
new file mode 100644 (file)
index 0000000..9337938
--- /dev/null
@@ -0,0 +1,100 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifdef HAVE_NETDB_H
+# include <netdb.h>
+#endif
+
+#ifdef NI_MAXHOST
+# define MEMCACHED_NI_MAXHOST NI_MAXHOST
+#else
+# define MEMCACHED_NI_MAXHOST 1025
+#endif
+
+#ifdef NI_MAXSERV
+# define MEMCACHED_NI_MAXSERV NI_MAXSERV
+#else
+# define MEMCACHED_NI_MAXSERV 32
+#endif
+
+enum memcached_server_state_t {
+  MEMCACHED_SERVER_STATE_NEW, // fd == -1, no address lookup has been done
+  MEMCACHED_SERVER_STATE_ADDRINFO, // ADDRRESS information has been gathered
+  MEMCACHED_SERVER_STATE_IN_PROGRESS,
+  MEMCACHED_SERVER_STATE_CONNECTED,
+  MEMCACHED_SERVER_STATE_IN_TIMEOUT,
+  MEMCACHED_SERVER_STATE_DISABLED
+};
+
+struct memcached_server_st {
+  struct {
+    bool is_allocated:1;
+    bool is_initialized:1;
+    bool is_shutting_down:1;
+    bool is_dead:1;
+  } options;
+  uint32_t number_of_hosts;
+  uint32_t cursor_active;
+  in_port_t port;
+  uint32_t io_bytes_sent; /* # bytes sent since last read */
+  uint32_t request_id;
+  uint32_t server_failure_counter;
+  uint64_t server_failure_counter_query_id;
+  uint32_t server_timeout_counter;
+  uint64_t server_timeout_counter_query_id;
+  uint32_t weight;
+  uint32_t version;
+  enum memcached_server_state_t state;
+  struct {
+    uint32_t read;
+    uint32_t write;
+    uint32_t timeouts;
+    size_t _bytes_read;
+  } io_wait_count;
+  uint8_t major_version; // Default definition of UINT8_MAX means that it has not been set.
+  uint8_t micro_version; // ditto, and note that this is the third, not second version bit
+  uint8_t minor_version; // ditto
+  memcached_connection_t type;
+  time_t next_retry;
+  struct memcached_st *root;
+  uint64_t limit_maxbytes;
+  struct memcached_error_t *error_messages;
+  char hostname[MEMCACHED_NI_MAXHOST];
+};
diff --git a/include/libmemcached-1.0/struct/stat.h b/include/libmemcached-1.0/struct/stat.h
new file mode 100644 (file)
index 0000000..acd4e21
--- /dev/null
@@ -0,0 +1,68 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+struct memcached_stat_st {
+  unsigned long connection_structures;
+  unsigned long curr_connections;
+  unsigned long curr_items;
+  pid_t pid;
+  unsigned long pointer_size;
+  unsigned long rusage_system_microseconds;
+  unsigned long rusage_system_seconds;
+  unsigned long rusage_user_microseconds;
+  unsigned long rusage_user_seconds;
+  unsigned long threads;
+  unsigned long time;
+  unsigned long total_connections;
+  unsigned long total_items;
+  unsigned long uptime;
+  unsigned long long bytes;
+  unsigned long long bytes_read;
+  unsigned long long bytes_written;
+  unsigned long long cmd_get;
+  unsigned long long cmd_set;
+  unsigned long long evictions;
+  unsigned long long get_hits;
+  unsigned long long get_misses;
+  unsigned long long limit_maxbytes;
+  char version[MEMCACHED_VERSION_STRING_LENGTH];
+  void *__future; // @todo create a new structure to place here for future usage
+  memcached_st *root;
+};
+
diff --git a/include/libmemcached-1.0/struct/string.h b/include/libmemcached-1.0/struct/string.h
new file mode 100644 (file)
index 0000000..9edb637
--- /dev/null
@@ -0,0 +1,59 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+/**
+  Strings are always under our control so we make some assumptions
+  about them.
+
+  1) is_initialized is always valid.
+  2) A string once intialized will always be, until free where we
+     unset this flag.
+  3) A string always has a root.
+*/
+
+struct memcached_string_st {
+  char *end;
+  char *string;
+  size_t current_size;
+  struct memcached_st *root;
+  struct {
+    bool is_allocated:1;
+    bool is_initialized:1;
+  } options;
+};
diff --git a/include/libmemcached-1.0/t/c_sasl_test.c b/include/libmemcached-1.0/t/c_sasl_test.c
new file mode 100644 (file)
index 0000000..93f729d
--- /dev/null
@@ -0,0 +1,61 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached C sasl test app
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * @file @brief C dummy test, aka testing C linking, etc
+ */
+
+#include <stdlib.h>
+
+#ifdef HAVE_SASL_SASL_H
+#include <sasl/sasl.h>
+#endif
+
+#include <libmemcached-1.0/memcached.h>
+
+int main(void)
+{
+  memcached_st *memc= memcached_create(NULL);
+
+  if (memc == NULL)
+  {
+    return EXIT_FAILURE;
+  }
+  memcached_free(memc);
+
+  return EXIT_SUCCESS;
+}
+
diff --git a/include/libmemcached-1.0/t/c_test.c b/include/libmemcached-1.0/t/c_test.c
new file mode 100644 (file)
index 0000000..40935fa
--- /dev/null
@@ -0,0 +1,61 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached C test app
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * @file @brief C dummy test, aka testing C linking, etc
+ */
+
+#include <stdlib.h>
+
+#include <libmemcached-1.0/memcached.h>
+
+int main(void)
+{
+  (void)memcached_success(MEMCACHED_SUCCESS);
+  (void)memcached_failed(MEMCACHED_SUCCESS);
+  (void)memcached_continue(MEMCACHED_SUCCESS);
+
+  memcached_st *memc= memcached_create(NULL);
+  
+  if (memc == NULL)
+  {
+    return EXIT_FAILURE;
+  }
+  memcached_free(memc);
+
+  return EXIT_SUCCESS;
+}
+
diff --git a/include/libmemcached-1.0/t/cc_test.cc b/include/libmemcached-1.0/t/cc_test.cc
new file mode 100644 (file)
index 0000000..71ee8c3
--- /dev/null
@@ -0,0 +1,62 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached C++ test app
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * @file @brief C dummy test, aka testing C linking, etc
+ */
+
+#include <cstdlib>
+
+#include <libmemcached-1.0/memcached.h>
+
+int main(void)
+{
+  (void)memcached_success(MEMCACHED_SUCCESS);
+  (void)memcached_failed(MEMCACHED_SUCCESS);
+  (void)memcached_continue(MEMCACHED_SUCCESS);
+
+  memcached_st *memc= memcached_create(NULL);
+
+  if (memc == NULL)
+  {
+    return EXIT_FAILURE;
+  }
+
+  memcached_free(memc);
+
+  return EXIT_SUCCESS;
+}
+
diff --git a/include/libmemcached-1.0/touch.h b/include/libmemcached-1.0/touch.h
new file mode 100644 (file)
index 0000000..e143c03
--- /dev/null
@@ -0,0 +1,59 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+LIBMEMCACHED_API
+memcached_return_t memcached_touch(memcached_st *ptr,
+                                   const char *key, size_t key_length,
+                                   time_t expiration);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_touch_by_key(memcached_st *ptr,
+                                          const char *group_key, size_t group_key_length,
+                                          const char *key, size_t key_length,
+                                          time_t expiration);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/triggers.h b/include/libmemcached-1.0/triggers.h
new file mode 100644 (file)
index 0000000..b331429
--- /dev/null
@@ -0,0 +1,64 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef memcached_return_t (*memcached_clone_fn)(memcached_st *destination, const memcached_st *source);
+typedef memcached_return_t (*memcached_cleanup_fn)(const memcached_st *ptr);
+
+/**
+  Trigger functions.
+*/
+typedef memcached_return_t (*memcached_trigger_key_fn)(const memcached_st *ptr,
+                                                       const char *key, size_t key_length,
+                                                       memcached_result_st *result);
+typedef memcached_return_t (*memcached_trigger_delete_key_fn)(const memcached_st *ptr,
+                                                              const char *key, size_t key_length);
+
+typedef memcached_return_t (*memcached_dump_fn)(const memcached_st *ptr,
+                                                const char *key,
+                                                size_t key_length,
+                                                void *context);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/types.h b/include/libmemcached-1.0/types.h
new file mode 100644 (file)
index 0000000..2c3f87a
--- /dev/null
@@ -0,0 +1,83 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifdef __cplusplus
+
+struct memcached_st;
+struct memcached_stat_st;
+struct memcached_analysis_st;
+struct memcached_result_st;
+struct memcached_array_st;
+struct memcached_error_t;
+
+// All of the flavors of memcache_server_st
+struct memcached_server_st;
+struct memcached_instance_st;
+typedef struct memcached_instance_st memcached_instance_st;
+typedef struct memcached_server_st *memcached_server_list_st;
+
+struct memcached_callback_st;
+
+// The following two structures are internal, and never exposed to users.
+struct memcached_string_st;
+struct memcached_string_t;
+struct memcached_continuum_item_st;
+
+#else
+
+typedef struct memcached_st memcached_st;
+typedef struct memcached_stat_st memcached_stat_st;
+typedef struct memcached_analysis_st memcached_analysis_st;
+typedef struct memcached_result_st memcached_result_st;
+typedef struct memcached_array_st memcached_array_st;
+typedef struct memcached_error_t memcached_error_t;
+
+// All of the flavors of memcache_server_st
+typedef struct memcached_server_st memcached_server_st;
+typedef struct memcached_instance_st memcached_instance_st;
+typedef struct memcached_server_st *memcached_server_list_st;
+
+typedef struct memcached_callback_st memcached_callback_st;
+
+// The following two structures are internal, and never exposed to users.
+typedef struct memcached_string_st memcached_string_st;
+typedef struct memcached_string_t memcached_string_t;
+
+#endif
diff --git a/include/libmemcached-1.0/types/behavior.h b/include/libmemcached-1.0/types/behavior.h
new file mode 100644 (file)
index 0000000..a1bbfd2
--- /dev/null
@@ -0,0 +1,85 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+enum memcached_behavior_t {
+  MEMCACHED_BEHAVIOR_NO_BLOCK,
+  MEMCACHED_BEHAVIOR_TCP_NODELAY,
+  MEMCACHED_BEHAVIOR_HASH,
+  MEMCACHED_BEHAVIOR_KETAMA,
+  MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE,
+  MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE,
+  MEMCACHED_BEHAVIOR_CACHE_LOOKUPS,
+  MEMCACHED_BEHAVIOR_SUPPORT_CAS,
+  MEMCACHED_BEHAVIOR_POLL_TIMEOUT,
+  MEMCACHED_BEHAVIOR_DISTRIBUTION,
+  MEMCACHED_BEHAVIOR_BUFFER_REQUESTS,
+  MEMCACHED_BEHAVIOR_USER_DATA,
+  MEMCACHED_BEHAVIOR_SORT_HOSTS,
+  MEMCACHED_BEHAVIOR_VERIFY_KEY,
+  MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT,
+  MEMCACHED_BEHAVIOR_RETRY_TIMEOUT,
+  MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED,
+  MEMCACHED_BEHAVIOR_KETAMA_HASH,
+  MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
+  MEMCACHED_BEHAVIOR_SND_TIMEOUT,
+  MEMCACHED_BEHAVIOR_RCV_TIMEOUT,
+  MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT,
+  MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK,
+  MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK,
+  MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH,
+  MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY,
+  MEMCACHED_BEHAVIOR_NOREPLY,
+  MEMCACHED_BEHAVIOR_USE_UDP,
+  MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS,
+  MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS,
+  MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ,
+  MEMCACHED_BEHAVIOR_CORK,
+  MEMCACHED_BEHAVIOR_TCP_KEEPALIVE,
+  MEMCACHED_BEHAVIOR_TCP_KEEPIDLE,
+  MEMCACHED_BEHAVIOR_LOAD_FROM_FILE,
+  MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS,
+  MEMCACHED_BEHAVIOR_DEAD_TIMEOUT,
+  MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT,
+  MEMCACHED_BEHAVIOR_MAX
+};
+
+#ifndef __cplusplus
+typedef enum memcached_behavior_t memcached_behavior_t;
+#endif
diff --git a/include/libmemcached-1.0/types/callback.h b/include/libmemcached-1.0/types/callback.h
new file mode 100644 (file)
index 0000000..d5481f5
--- /dev/null
@@ -0,0 +1,54 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+enum memcached_callback_t {
+  MEMCACHED_CALLBACK_PREFIX_KEY = 0,
+  MEMCACHED_CALLBACK_USER_DATA = 1,
+  MEMCACHED_CALLBACK_CLEANUP_FUNCTION = 2,
+  MEMCACHED_CALLBACK_CLONE_FUNCTION = 3,
+  MEMCACHED_CALLBACK_GET_FAILURE = 7,
+  MEMCACHED_CALLBACK_DELETE_TRIGGER = 8,
+  MEMCACHED_CALLBACK_MAX,
+  MEMCACHED_CALLBACK_NAMESPACE= MEMCACHED_CALLBACK_PREFIX_KEY
+};
+
+#ifndef __cplusplus
+typedef enum memcached_callback_t memcached_callback_t;
+#endif
diff --git a/include/libmemcached-1.0/types/connection.h b/include/libmemcached-1.0/types/connection.h
new file mode 100644 (file)
index 0000000..d2a072b
--- /dev/null
@@ -0,0 +1,49 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+enum memcached_connection_t {
+  MEMCACHED_CONNECTION_TCP,
+  MEMCACHED_CONNECTION_UDP,
+  MEMCACHED_CONNECTION_UNIX_SOCKET
+};
+
+#ifndef __cplusplus
+typedef enum memcached_connection_t memcached_connection_t;
+#endif
diff --git a/include/libmemcached-1.0/types/hash.h b/include/libmemcached-1.0/types/hash.h
new file mode 100644 (file)
index 0000000..8eee4df
--- /dev/null
@@ -0,0 +1,59 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+enum memcached_hash_t {
+  MEMCACHED_HASH_DEFAULT= 0,
+  MEMCACHED_HASH_MD5,
+  MEMCACHED_HASH_CRC,
+  MEMCACHED_HASH_FNV1_64,
+  MEMCACHED_HASH_FNV1A_64,
+  MEMCACHED_HASH_FNV1_32,
+  MEMCACHED_HASH_FNV1A_32,
+  MEMCACHED_HASH_HSIEH,
+  MEMCACHED_HASH_MURMUR,
+  MEMCACHED_HASH_JENKINS,
+  MEMCACHED_HASH_MURMUR3,
+  MEMCACHED_HASH_CUSTOM,
+  MEMCACHED_HASH_MAX
+};
+
+#ifndef __cplusplus
+typedef enum memcached_hash_t memcached_hash_t;
+#endif
diff --git a/include/libmemcached-1.0/types/return.h b/include/libmemcached-1.0/types/return.h
new file mode 100644 (file)
index 0000000..80c9051
--- /dev/null
@@ -0,0 +1,96 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+enum memcached_return_t {
+  MEMCACHED_SUCCESS,
+  MEMCACHED_FAILURE,
+  MEMCACHED_HOST_LOOKUP_FAILURE, // getaddrinfo() and getnameinfo() only
+  MEMCACHED_CONNECTION_FAILURE,
+  MEMCACHED_CONNECTION_BIND_FAILURE,  // DEPRECATED, see MEMCACHED_HOST_LOOKUP_FAILURE
+  MEMCACHED_WRITE_FAILURE,
+  MEMCACHED_READ_FAILURE,
+  MEMCACHED_UNKNOWN_READ_FAILURE,
+  MEMCACHED_PROTOCOL_ERROR,
+  MEMCACHED_CLIENT_ERROR,
+  MEMCACHED_SERVER_ERROR, // Server returns "SERVER_ERROR"
+  MEMCACHED_ERROR, // Server returns "ERROR"
+  MEMCACHED_DATA_EXISTS,
+  MEMCACHED_DATA_DOES_NOT_EXIST,
+  MEMCACHED_NOTSTORED,
+  MEMCACHED_STORED,
+  MEMCACHED_NOTFOUND,
+  MEMCACHED_MEMORY_ALLOCATION_FAILURE,
+  MEMCACHED_PARTIAL_READ,
+  MEMCACHED_SOME_ERRORS,
+  MEMCACHED_NO_SERVERS,
+  MEMCACHED_END,
+  MEMCACHED_DELETED,
+  MEMCACHED_VALUE,
+  MEMCACHED_STAT,
+  MEMCACHED_ITEM,
+  MEMCACHED_ERRNO,
+  MEMCACHED_FAIL_UNIX_SOCKET, // DEPRECATED
+  MEMCACHED_NOT_SUPPORTED,
+  MEMCACHED_NO_KEY_PROVIDED, /* Deprecated. Use MEMCACHED_BAD_KEY_PROVIDED! */
+  MEMCACHED_FETCH_NOTFINISHED,
+  MEMCACHED_TIMEOUT,
+  MEMCACHED_BUFFERED,
+  MEMCACHED_BAD_KEY_PROVIDED,
+  MEMCACHED_INVALID_HOST_PROTOCOL,
+  MEMCACHED_SERVER_MARKED_DEAD,
+  MEMCACHED_UNKNOWN_STAT_KEY,
+  MEMCACHED_E2BIG,
+  MEMCACHED_INVALID_ARGUMENTS,
+  MEMCACHED_KEY_TOO_BIG,
+  MEMCACHED_AUTH_PROBLEM,
+  MEMCACHED_AUTH_FAILURE,
+  MEMCACHED_AUTH_CONTINUE,
+  MEMCACHED_PARSE_ERROR,
+  MEMCACHED_PARSE_USER_ERROR,
+  MEMCACHED_DEPRECATED,
+  MEMCACHED_IN_PROGRESS,
+  MEMCACHED_SERVER_TEMPORARILY_DISABLED,
+  MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE,
+  MEMCACHED_UNIX_SOCKET_PATH_TOO_BIG,
+  MEMCACHED_MAXIMUM_RETURN, /* Always add new error code before */
+  MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE= MEMCACHED_ERROR
+};
+
+#ifndef __cplusplus
+typedef enum memcached_return_t memcached_return_t;
+#endif
diff --git a/include/libmemcached-1.0/types/server_distribution.h b/include/libmemcached-1.0/types/server_distribution.h
new file mode 100644 (file)
index 0000000..95e129f
--- /dev/null
@@ -0,0 +1,54 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+enum memcached_server_distribution_t {
+  MEMCACHED_DISTRIBUTION_MODULA,
+  MEMCACHED_DISTRIBUTION_CONSISTENT,
+  MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA,
+  MEMCACHED_DISTRIBUTION_RANDOM,
+  MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY,
+  MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED,
+  MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET,
+  MEMCACHED_DISTRIBUTION_CONSISTENT_MAX
+};
+
+#ifndef __cplusplus
+typedef enum memcached_server_distribution_t memcached_server_distribution_t;
+#endif
diff --git a/include/libmemcached-1.0/verbosity.h b/include/libmemcached-1.0/verbosity.h
new file mode 100644 (file)
index 0000000..2994648
--- /dev/null
@@ -0,0 +1,50 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_verbosity(memcached_st *ptr, uint32_t verbosity);
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/version.h b/include/libmemcached-1.0/version.h
new file mode 100644 (file)
index 0000000..c443acc
--- /dev/null
@@ -0,0 +1,52 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_version(memcached_st *ptr);
+
+LIBMEMCACHED_API
+const char * memcached_lib_version(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcached-1.0/visibility.h b/include/libmemcached-1.0/visibility.h
new file mode 100644 (file)
index 0000000..d4e4eea
--- /dev/null
@@ -0,0 +1,67 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker 
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Interface for memcached server.
+ *
+ * Author: Trond Norbye
+ *
+ */
+
+/**
+ * @file
+ * @brief Visibility control macros
+ */
+
+#pragma once
+
+/**
+ *
+ * LIBMEMCACHED_API is used for the public API symbols. It either DLL imports or
+ * DLL exports (or does nothing for static build).
+ *
+ * LIBMEMCACHED_LOCAL is used for non-api symbols.
+ */
+
+#if defined(BUILDING_LIBMEMCACHEDINTERNAL)
+# if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
+#  define LIBMEMCACHED_API __attribute__ ((visibility("default")))
+#  define LIBMEMCACHED_LOCAL  __attribute__ ((visibility("default")))
+# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+#  define LIBMEMCACHED_API __global
+#  define LIBMEMCACHED_LOCAL __global
+# elif defined(_MSC_VER)
+#  define LIBMEMCACHED_API extern __declspec(dllexport) 
+#  define LIBMEMCACHED_LOCAL extern __declspec(dllexport)
+# else
+#  define LIBMEMCACHED_API
+#  define LIBMEMCACHED_LOCAL
+# endif
+#else
+# if defined(BUILDING_LIBMEMCACHED)
+#  if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
+#   define LIBMEMCACHED_API __attribute__ ((visibility("default")))
+#   define LIBMEMCACHED_LOCAL  __attribute__ ((visibility("hidden")))
+#  elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+#   define LIBMEMCACHED_API __global
+#   define LIBMEMCACHED_LOCAL __hidden
+#  elif defined(_MSC_VER)
+#   define LIBMEMCACHED_API extern __declspec(dllexport) 
+#   define LIBMEMCACHED_LOCAL
+#  else
+#   define LIBMEMCACHED_API
+#   define LIBMEMCACHED_LOCAL
+#  endif /* defined(HAVE_VISIBILITY) */
+# else  /* defined(BUILDING_LIBMEMCACHED) */
+#  if defined(_MSC_VER)
+#   define LIBMEMCACHED_API extern __declspec(dllimport) 
+#   define LIBMEMCACHED_LOCAL
+#  else
+#   define LIBMEMCACHED_API
+#   define LIBMEMCACHED_LOCAL
+#  endif /* defined(_MSC_VER) */
+# endif /* defined(BUILDING_LIBMEMCACHED) */
+#endif /* defined(BUILDING_LIBMEMCACHEDINTERNAL) */
diff --git a/include/libmemcachedprotocol-0.0/binary.h b/include/libmemcachedprotocol-0.0/binary.h
new file mode 100644 (file)
index 0000000..51e2c42
--- /dev/null
@@ -0,0 +1,728 @@
+/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (c) <2008>, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the  nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SUN MICROSYSTEMS, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Summary: Constants used by to implement the binary protocol.
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Trond Norbye <trond.norbye@sun.com>
+ */
+
+#ifndef PROTOCOL_BINARY_H
+#define PROTOCOL_BINARY_H
+
+#include <libmemcachedprotocol-0.0/vbucket.h>
+
+/**
+ * \addtogroup Protocol
+ * @{
+ */
+
+/**
+ * This file contains definitions of the constants and packet formats
+ * defined in the binary specification. Please note that you _MUST_ remember
+ * to convert each multibyte field to / from network byte order to / from
+ * host order.
+ */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    /**
+     * Definition of the legal "magic" values used in a packet.
+     * See section 3.1 Magic byte
+     */
+    typedef enum {
+        PROTOCOL_BINARY_REQ = 0x80,
+        PROTOCOL_BINARY_RES = 0x81
+    } protocol_binary_magic;
+
+    /**
+     * Definition of the valid response status numbers.
+     * See section 3.2 Response Status
+     */
+    typedef enum {
+        PROTOCOL_BINARY_RESPONSE_SUCCESS = 0x00,
+        PROTOCOL_BINARY_RESPONSE_KEY_ENOENT = 0x01,
+        PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS = 0x02,
+        PROTOCOL_BINARY_RESPONSE_E2BIG = 0x03,
+        PROTOCOL_BINARY_RESPONSE_EINVAL = 0x04,
+        PROTOCOL_BINARY_RESPONSE_NOT_STORED = 0x05,
+        PROTOCOL_BINARY_RESPONSE_DELTA_BADVAL = 0x06,
+        PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET = 0x07,
+        PROTOCOL_BINARY_RESPONSE_AUTH_ERROR = 0x20,
+        PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE = 0x21,
+        PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND = 0x81,
+        PROTOCOL_BINARY_RESPONSE_ENOMEM = 0x82,
+        PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED = 0x83,
+        PROTOCOL_BINARY_RESPONSE_EINTERNAL = 0x84,
+        PROTOCOL_BINARY_RESPONSE_EBUSY = 0x85,
+        PROTOCOL_BINARY_RESPONSE_ETMPFAIL = 0x86
+    } protocol_binary_response_status;
+
+    /**
+     * Defintion of the different command opcodes.
+     * See section 3.3 Command Opcodes
+     */
+    typedef enum {
+        PROTOCOL_BINARY_CMD_GET = 0x00,
+        PROTOCOL_BINARY_CMD_SET = 0x01,
+        PROTOCOL_BINARY_CMD_ADD = 0x02,
+        PROTOCOL_BINARY_CMD_REPLACE = 0x03,
+        PROTOCOL_BINARY_CMD_DELETE = 0x04,
+        PROTOCOL_BINARY_CMD_INCREMENT = 0x05,
+        PROTOCOL_BINARY_CMD_DECREMENT = 0x06,
+        PROTOCOL_BINARY_CMD_QUIT = 0x07,
+        PROTOCOL_BINARY_CMD_FLUSH = 0x08,
+        PROTOCOL_BINARY_CMD_GETQ = 0x09,
+        PROTOCOL_BINARY_CMD_NOOP = 0x0a,
+        PROTOCOL_BINARY_CMD_VERSION = 0x0b,
+        PROTOCOL_BINARY_CMD_GETK = 0x0c,
+        PROTOCOL_BINARY_CMD_GETKQ = 0x0d,
+        PROTOCOL_BINARY_CMD_APPEND = 0x0e,
+        PROTOCOL_BINARY_CMD_PREPEND = 0x0f,
+        PROTOCOL_BINARY_CMD_STAT = 0x10,
+        PROTOCOL_BINARY_CMD_SETQ = 0x11,
+        PROTOCOL_BINARY_CMD_ADDQ = 0x12,
+        PROTOCOL_BINARY_CMD_REPLACEQ = 0x13,
+        PROTOCOL_BINARY_CMD_DELETEQ = 0x14,
+        PROTOCOL_BINARY_CMD_INCREMENTQ = 0x15,
+        PROTOCOL_BINARY_CMD_DECREMENTQ = 0x16,
+        PROTOCOL_BINARY_CMD_QUITQ = 0x17,
+        PROTOCOL_BINARY_CMD_FLUSHQ = 0x18,
+        PROTOCOL_BINARY_CMD_APPENDQ = 0x19,
+        PROTOCOL_BINARY_CMD_PREPENDQ = 0x1a,
+        PROTOCOL_BINARY_CMD_VERBOSITY = 0x1b,
+        PROTOCOL_BINARY_CMD_TOUCH = 0x1c,
+        PROTOCOL_BINARY_CMD_GAT = 0x1d,
+        PROTOCOL_BINARY_CMD_GATQ = 0x1e,
+        PROTOCOL_BINARY_CMD_GATK = 0x23,
+        PROTOCOL_BINARY_CMD_GATKQ = 0x24,
+
+        PROTOCOL_BINARY_CMD_SASL_LIST_MECHS = 0x20,
+        PROTOCOL_BINARY_CMD_SASL_AUTH = 0x21,
+        PROTOCOL_BINARY_CMD_SASL_STEP = 0x22,
+
+        /* These commands are used for range operations and exist within
+         * this header for use in other projects.  Range operations are
+         * not expected to be implemented in the memcached server itself.
+         */
+        PROTOCOL_BINARY_CMD_RGET      = 0x30,
+        PROTOCOL_BINARY_CMD_RSET      = 0x31,
+        PROTOCOL_BINARY_CMD_RSETQ     = 0x32,
+        PROTOCOL_BINARY_CMD_RAPPEND   = 0x33,
+        PROTOCOL_BINARY_CMD_RAPPENDQ  = 0x34,
+        PROTOCOL_BINARY_CMD_RPREPEND  = 0x35,
+        PROTOCOL_BINARY_CMD_RPREPENDQ = 0x36,
+        PROTOCOL_BINARY_CMD_RDELETE   = 0x37,
+        PROTOCOL_BINARY_CMD_RDELETEQ  = 0x38,
+        PROTOCOL_BINARY_CMD_RINCR     = 0x39,
+        PROTOCOL_BINARY_CMD_RINCRQ    = 0x3a,
+        PROTOCOL_BINARY_CMD_RDECR     = 0x3b,
+        PROTOCOL_BINARY_CMD_RDECRQ    = 0x3c,
+        /* End Range operations */
+
+        /* VBucket commands */
+        PROTOCOL_BINARY_CMD_SET_VBUCKET = 0x3d,
+        PROTOCOL_BINARY_CMD_GET_VBUCKET = 0x3e,
+        PROTOCOL_BINARY_CMD_DEL_VBUCKET = 0x3f,
+        /* End VBucket commands */
+
+        /* TAP commands */
+        PROTOCOL_BINARY_CMD_TAP_CONNECT = 0x40,
+        PROTOCOL_BINARY_CMD_TAP_MUTATION = 0x41,
+        PROTOCOL_BINARY_CMD_TAP_DELETE = 0x42,
+        PROTOCOL_BINARY_CMD_TAP_FLUSH = 0x43,
+        PROTOCOL_BINARY_CMD_TAP_OPAQUE = 0x44,
+        PROTOCOL_BINARY_CMD_TAP_VBUCKET_SET = 0x45,
+        PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_START = 0x46,
+        PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_END = 0x47,
+        /* End TAP */
+
+        PROTOCOL_BINARY_CMD_LAST_RESERVED = 0xef,
+
+        /* Scrub the data */
+        PROTOCOL_BINARY_CMD_SCRUB = 0xf0
+    } protocol_binary_command;
+
+    /**
+     * Definition of the data types in the packet
+     * See section 3.4 Data Types
+     */
+    typedef enum {
+        PROTOCOL_BINARY_RAW_BYTES = 0x00
+    } protocol_binary_datatypes;
+
+    /**
+     * Definition of the header structure for a request packet.
+     * See section 2
+     */
+    typedef union {
+        struct {
+            uint8_t magic;
+            uint8_t opcode;
+            uint16_t keylen;
+            uint8_t extlen;
+            uint8_t datatype;
+            uint16_t vbucket;
+            uint32_t bodylen;
+            uint32_t opaque;
+            uint64_t cas;
+        } request;
+        uint8_t bytes[24];
+    } protocol_binary_request_header;
+
+    /**
+     * Definition of the header structure for a response packet.
+     * See section 2
+     */
+    typedef union {
+        struct {
+            uint8_t magic;
+            uint8_t opcode;
+            uint16_t keylen;
+            uint8_t extlen;
+            uint8_t datatype;
+            uint16_t status;
+            uint32_t bodylen;
+            uint32_t opaque;
+            uint64_t cas;
+        } response;
+        uint8_t bytes[24];
+    } protocol_binary_response_header;
+
+    /**
+     * Definition of a request-packet containing no extras
+     */
+    union protocol_binary_request_no_extras {
+        struct {
+            protocol_binary_request_header header;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header)];
+    };
+    typedef union protocol_binary_request_no_extras protocol_binary_request_no_extras;
+
+    /**
+     * Definition of a response-packet containing no extras
+     */
+    typedef union {
+        struct {
+            protocol_binary_response_header header;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_response_header)];
+    } protocol_binary_response_no_extras;
+
+    /**
+     * Definition of the packet used by the get, getq, getk and getkq command.
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_get;
+    typedef protocol_binary_request_no_extras protocol_binary_request_getq;
+    typedef protocol_binary_request_no_extras protocol_binary_request_getk;
+    typedef protocol_binary_request_no_extras protocol_binary_request_getkq;
+
+    /**
+     * Definition of the packet returned from a successful get, getq, getk and
+     * getkq.
+     * See section 4
+     */
+    typedef union {
+        struct {
+            protocol_binary_response_header header;
+            struct {
+                uint32_t flags;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_response_header) + 4];
+    } protocol_binary_response_get;
+
+    typedef protocol_binary_response_get protocol_binary_response_getq;
+    typedef protocol_binary_response_get protocol_binary_response_getk;
+    typedef protocol_binary_response_get protocol_binary_response_getkq;
+
+    /**
+     * Definition of the packet used by the delete command
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_delete;
+
+    /**
+     * Definition of the packet returned by the delete command
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_delete;
+
+    /**
+     * Definition of the packet used by the flush command
+     * See section 4
+     * Please note that the expiration field is optional, so remember to see
+     * check the header.bodysize to see if it is present.
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                uint32_t expiration;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+    } protocol_binary_request_flush;
+
+    /**
+     * Definition of the packet returned by the flush command
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_flush;
+
+    /**
+     * Definition of the packet used by set, add and replace
+     * See section 4
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                uint32_t flags;
+                uint32_t expiration;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
+    } protocol_binary_request_set;
+    typedef protocol_binary_request_set protocol_binary_request_add;
+    typedef protocol_binary_request_set protocol_binary_request_replace;
+
+    /**
+     * Definition of the packet returned by set, add and replace
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_set;
+    typedef protocol_binary_response_no_extras protocol_binary_response_add;
+    typedef protocol_binary_response_no_extras protocol_binary_response_replace;
+
+    /**
+     * Definition of the noop packet
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_noop;
+
+    /**
+     * Definition of the packet returned by the noop command
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_noop;
+
+    /**
+     * Definition of the structure used by the increment and decrement
+     * command.
+     * See section 4
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                uint64_t delta;
+                uint64_t initial;
+                uint32_t expiration;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 20];
+    } protocol_binary_request_incr;
+    typedef protocol_binary_request_incr protocol_binary_request_decr;
+
+    /**
+     * Definition of the response from an incr or decr command
+     * command.
+     * See section 4
+     */
+    typedef union {
+        struct {
+            protocol_binary_response_header header;
+            struct {
+                uint64_t value;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_response_header) + 8];
+    } protocol_binary_response_incr;
+    typedef protocol_binary_response_incr protocol_binary_response_decr;
+
+    /**
+     * Definition of the quit
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_quit;
+
+    /**
+     * Definition of the packet returned by the quit command
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_quit;
+
+    /**
+     * Definition of the packet used by append and prepend command
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_append;
+    typedef protocol_binary_request_no_extras protocol_binary_request_prepend;
+
+    /**
+     * Definition of the packet returned from a successful append or prepend
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_append;
+    typedef protocol_binary_response_no_extras protocol_binary_response_prepend;
+
+    /**
+     * Definition of the packet used by the version command
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_version;
+
+    /**
+     * Definition of the packet returned from a successful version command
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_version;
+
+
+    /**
+     * Definition of the packet used by the stats command.
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_stats;
+
+    /**
+     * Definition of the packet returned from a successful stats command
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_stats;
+
+    /**
+     * Definition of the packet used by the verbosity command
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                uint32_t level;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+    } protocol_binary_request_verbosity;
+
+    /**
+     * Definition of the packet returned from the verbosity command
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_verbosity;
+
+    /**
+     * Definition of the packet used by the touch command.
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                uint32_t expiration;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+    } protocol_binary_request_touch;
+
+    /**
+     * Definition of the packet returned from the touch command
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_touch;
+
+    /**
+     * Definition of the packet used by the GAT(Q) command.
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                uint32_t expiration;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+    } protocol_binary_request_gat;
+
+    typedef protocol_binary_request_gat protocol_binary_request_gatq;
+
+    /**
+     * Definition of the packet returned from the GAT(Q)
+     */
+    typedef protocol_binary_response_get protocol_binary_response_gat;
+    typedef protocol_binary_response_get protocol_binary_response_gatq;
+
+
+    /**
+     * Definition of a request for a range operation.
+     * See http://code.google.com/p/memcached/wiki/RangeOps
+     *
+     * These types are used for range operations and exist within
+     * this header for use in other projects.  Range operations are
+     * not expected to be implemented in the memcached server itself.
+     */
+    typedef union {
+        struct {
+            protocol_binary_response_header header;
+            struct {
+                uint16_t size;
+                uint8_t  reserved;
+                uint8_t  flags;
+                uint32_t max_results;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+    } protocol_binary_request_rangeop;
+
+    typedef protocol_binary_request_rangeop protocol_binary_request_rget;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rset;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rsetq;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rappend;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rappendq;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rprepend;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rprependq;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rdelete;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rdeleteq;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rincr;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rincrq;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rdecr;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rdecrq;
+
+
+    /**
+     * Definition of tap commands
+     * See To be written
+     *
+     */
+
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                /**
+                 * flags is a bitmask used to set properties for the
+                 * the connection. Please In order to be forward compatible
+                 * you should set all undefined bits to 0.
+                 *
+                 * If the bit require extra userdata, it will be stored
+                 * in the user-data field of the body (passed to the engine
+                 * as enginespeciffic). That means that when you parse the
+                 * flags and the engine-specific data, you have to work your
+                 * way from bit 0 and upwards to find the correct offset for
+                 * the data.
+                 *
+                 */
+                uint32_t flags;
+
+                /**
+                 * Backfill age
+                 *
+                 * By using this flag you can limit the amount of data being
+                 * transmitted. If you don't specify a backfill age, the
+                 * server will transmit everything it contains.
+                 *
+                 * The first 8 bytes in the engine specific data contains
+                 * the oldest entry (from epoc) you're interested in.
+                 * Specifying a time in the future (for the server you are
+                 * connecting to), will cause it to start streaming current
+                 * changes.
+                 */
+#define TAP_CONNECT_FLAG_BACKFILL 0x01
+                /**
+                 * Dump will cause the server to send the data stored on the
+                 * server, but disconnect when the keys stored in the server
+                 * are transmitted.
+                 */
+#define TAP_CONNECT_FLAG_DUMP 0x02
+                /**
+                 * The body contains a list of 16 bits words in network byte
+                 * order specifying the vbucket ids to monitor. The first 16
+                 * bit word contains the number of buckets. The number of 0
+                 * means "all buckets"
+                 */
+#define TAP_CONNECT_FLAG_LIST_VBUCKETS 0x04
+                /**
+                 * The responsibility of the vbuckets is to be transferred
+                 * over to the caller when all items are transferred.
+                 */
+#define TAP_CONNECT_FLAG_TAKEOVER_VBUCKETS 0x08
+                /**
+                 * The tap consumer supports ack'ing of tap messages
+                 */
+#define TAP_CONNECT_SUPPORT_ACK 0x10
+                /**
+                 * The tap consumer would prefer to just get the keys
+                 * back. If the engine supports this it will set
+                 * the TAP_FLAG_NO_VALUE flag in each of the
+                 * tap packets returned.
+                 */
+#define TAP_CONNECT_REQUEST_KEYS_ONLY 0x20
+                /**
+                 * The body contains a list of (vbucket_id, last_checkpoint_id)
+                 * pairs. This provides the checkpoint support in TAP streams.
+                 * The last checkpoint id represents the last checkpoint that
+                 * was successfully persisted.
+                 */
+#define TAP_CONNECT_CHECKPOINT 0x40
+                /**
+                 * The tap consumer is a registered tap client, which means that
+                 * the tap server will maintain its checkpoint cursor permanently.
+                 */
+#define TAP_CONNECT_REGISTERED_CLIENT 0x80
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+    } protocol_binary_request_tap_connect;
+
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                struct {
+                    uint16_t enginespecific_length;
+                    /*
+                     * The flag section support the following flags
+                     */
+                    /**
+                     * Request that the consumer send a response packet
+                     * for this packet. The opaque field must be preserved
+                     * in the response.
+                     */
+#define TAP_FLAG_ACK 0x01
+                    /**
+                     * The value for the key is not included in the packet
+                     */
+#define TAP_FLAG_NO_VALUE 0x02
+                    uint16_t flags;
+                    uint8_t  ttl;
+                    uint8_t  res1;
+                    uint8_t  res2;
+                    uint8_t  res3;
+                } tap;
+                struct {
+                    uint32_t flags;
+                    uint32_t expiration;
+                } item;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 16];
+    } protocol_binary_request_tap_mutation;
+
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                struct {
+                    uint16_t enginespecific_length;
+                    /**
+                     * See the definition of the flags for
+                     * protocol_binary_request_tap_mutation for a description
+                     * of the available flags.
+                     */
+                    uint16_t flags;
+                    uint8_t  ttl;
+                    uint8_t  res1;
+                    uint8_t  res2;
+                    uint8_t  res3;
+                } tap;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
+    } protocol_binary_request_tap_no_extras;
+
+    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_delete;
+    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_flush;
+    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_opaque;
+    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_vbucket_set;
+
+
+    /**
+     * Definition of the packet used by the scrub.
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_scrub;
+
+    /**
+     * Definition of the packet returned from scrub.
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_scrub;
+
+
+    /**
+     * Definition of the packet used by set vbucket
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                vbucket_state_t state;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + sizeof(vbucket_state_t)];
+    } protocol_binary_request_set_vbucket;
+    /**
+     * Definition of the packet returned from set vbucket
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_set_vbucket;
+    /**
+     * Definition of the packet used by del vbucket
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_del_vbucket;
+    /**
+     * Definition of the packet returned from del vbucket
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_del_vbucket;
+
+    /**
+     * Definition of the packet used by get vbucket
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_get_vbucket;
+
+    /**
+     * Definition of the packet returned from get vbucket
+     */
+    typedef union {
+        struct {
+            protocol_binary_response_header header;
+            struct {
+                vbucket_state_t state;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_response_header) + sizeof(vbucket_state_t)];
+    } protocol_binary_response_get_vbucket;
+
+
+    /**
+     * @}
+     */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* PROTOCOL_BINARY_H */
diff --git a/include/libmemcachedprotocol-0.0/callback.h b/include/libmemcachedprotocol-0.0/callback.h
new file mode 100644 (file)
index 0000000..638536c
--- /dev/null
@@ -0,0 +1,416 @@
+/*
+ * Summary: Definition of the callback interface
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Trond Norbye
+ */
+
+#pragma once
+
+/**
+ * Callback to send data back from a successful GET/GETQ/GETK/GETKQ command
+ *
+ * @param cookie Just pass along the cookie supplied in the callback
+ * @param key What to insert as key in the reply
+ * @param keylen The length of the key
+ * @param body What to store in the body of the package
+ * @param bodylen The number of bytes of the body
+ * @param flags The flags stored with the item
+ * @param cas The CAS value to insert into the response (should be 0
+ *            if you don't care)
+ */
+typedef protocol_binary_response_status
+(*memcached_binary_protocol_get_response_handler)(const void *cookie,
+                                                  const void *key,
+                                                  uint16_t keylen,
+                                                  const void *body,
+                                                  uint32_t bodylen,
+                                                  uint32_t flags,
+                                                  uint64_t cas);
+/**
+ * Callback to send data back from a STAT command
+ *
+ * @param cookie Just pass along the cookie supplied in the callback
+ * @param key What to insert as key in the reply
+ * @param keylen The length of the key
+ * @param body What to store in the body of the package
+ * @param bodylen The number of bytes of the body
+ */
+typedef protocol_binary_response_status
+(*memcached_binary_protocol_stat_response_handler)(const void *cookie,
+                                                   const void *key,
+                                                   uint16_t keylen,
+                                                   const void *body,
+                                                   uint32_t bodylen);
+/**
+ * Callback to send data back from a VERSION command
+ *
+ * @param cookie Just pass along the cookie supplied in the callback
+ * @param text The version string
+ * @param length The number of bytes in the version string
+ */
+typedef protocol_binary_response_status
+(*memcached_binary_protocol_version_response_handler)(const void *cookie,
+                                                      const void *text,
+                                                      uint32_t length);
+
+
+/**
+ * In the low level interface you need to format the response
+ * packet yourself (giving you complete freedom :-)
+ *
+ * @param cookie Just pass along the cookie supplied in the callback
+ * @param request Pointer to the request packet you are sending a reply to
+ * @param response Pointer to the response packet to send
+ *
+ */
+typedef protocol_binary_response_status (*memcached_binary_protocol_raw_response_handler)(const void *cookie,
+                                                               protocol_binary_request_header *request,
+                                                               protocol_binary_response_header *response);
+
+/**
+ * In the low lever interface you have to do most of the work by
+ * yourself, but it also gives you a lot of freedom :-)
+ * @param cookie identification for this connection, just pass it along to
+ *               the response handler
+ * @param header the command received over the wire. Never try to access
+ *               <u>anything</u> outside the command.
+ * @param resonse_handler call this function to send data back to the client
+ */
+typedef protocol_binary_response_status (*memcached_binary_protocol_command_handler)(const void *cookie,
+                                                   protocol_binary_request_header *header,
+                                                   memcached_binary_protocol_raw_response_handler response_handler);
+
+/**
+ * The raw interface to the packets is implemented in version 0. It contains
+ * just an array with command handlers. The inxed in the array is the
+ * com code.
+ */
+typedef struct {
+   memcached_binary_protocol_command_handler comcode[256];
+} memcached_binary_protocol_callback_v0_st;
+
+
+/**
+ * The first version of the callback struct containing all of the
+ * documented commands in the initial release of the binary protocol
+ * (aka. memcached 1.4.0).
+ *
+ * You might miss the Q commands (addq etc) but the response function
+ * knows how to deal with them so you don't need to worry about that :-)
+ */
+typedef struct {
+   /**
+    * Add an item to the cache
+    * @param cookie id of the client receiving the command
+    * @param key the key to add
+    * @param len the length of the key
+    * @param val the value to store for the key (may be NIL)
+    * @param vallen the length of the data
+    * @param flags the flags to store with the key
+    * @param exptime the expiry time for the key-value pair
+    * @param cas the resulting cas for the add operation (if success)
+    */
+   protocol_binary_response_status (*add)(const void *cookie,
+                                          const void *key,
+                                          uint16_t keylen,
+                                          const void* val,
+                                          uint32_t vallen,
+                                          uint32_t flags,
+                                          uint32_t exptime,
+                                          uint64_t *cas);
+
+   /**
+    * Append data to an <b>existing</b> key-value pair.
+    *
+    * @param cookie id of the client receiving the command
+    * @param key the key to add data to
+    * @param len the length of the key
+    * @param val the value to append to the value
+    * @param vallen the length of the data
+    * @param cas the CAS in the request
+    * @param result_cas the resulting cas for the append operation
+    *
+    */
+   protocol_binary_response_status (*append)(const void *cookie,
+                                             const void *key,
+                                             uint16_t keylen,
+                                             const void* val,
+                                             uint32_t vallen,
+                                             uint64_t cas,
+                                             uint64_t *result_cas);
+
+   /**
+    * Decrement the value for a key
+    *
+    * @param cookie id of the client receiving the command
+    * @param key the key to decrement the value for
+    * @param len the length of the key
+    * @param delta the amount to decrement
+    * @param initial initial value to store (if the key doesn't exist)
+    * @param expiration expiration time for the object (if the key doesn't exist)
+    * @param cas the CAS in the request
+    * @param result the result from the decrement
+    * @param result_cas the cas of the item
+    *
+    */
+   protocol_binary_response_status (*decrement)(const void *cookie,
+                                                const void *key,
+                                                uint16_t keylen,
+                                                uint64_t delta,
+                                                uint64_t initial,
+                                                uint32_t expiration,
+                                                uint64_t *result,
+                                                uint64_t *result_cas);
+
+   /**
+    * Delete an existing key
+    *
+    * @param cookie id of the client receiving the command
+    * @param key the key to delete_object
+    * @param len the length of the key
+    * @param cas the CAS in the request
+    */
+   protocol_binary_response_status (*delete_object)(const void *cookie,
+                                                    const void *key,
+                                                    uint16_t keylen,
+                                                    uint64_t cas);
+
+
+   /**
+    * Flush the cache
+    *
+    * @param cookie id of the client receiving the command
+    * @param when when the cache should be flushed (0 == immediately)
+    */
+   protocol_binary_response_status (*flush_object)(const void *cookie,
+                                                   uint32_t when);
+
+
+
+   /**
+    * Get a key-value pair
+    *
+    * @param cookie id of the client receiving the command
+    * @param key the key to get
+    * @param len the length of the key
+    * @param response_handler to send the result back to the client
+    */
+   protocol_binary_response_status (*get)(const void *cookie,
+                                          const void *key,
+                                          uint16_t keylen,
+                                          memcached_binary_protocol_get_response_handler response_handler);
+
+   /**
+    * Increment the value for a key
+    *
+    * @param cookie id of the client receiving the command
+    * @param key the key to increment the value on
+    * @param len the length of the key
+    * @param delta the amount to increment
+    * @param initial initial value to store (if the key doesn't exist)
+    * @param expiration expiration time for the object (if the key doesn't exist)
+    * @param cas the CAS in the request
+    * @param result the result from the decrement
+    * @param result_cas the cas of the item
+    *
+    */
+   protocol_binary_response_status (*increment)(const void *cookie,
+                                                const void *key,
+                                                uint16_t keylen,
+                                                uint64_t delta,
+                                                uint64_t initial,
+                                                uint32_t expiration,
+                                                uint64_t *result,
+                                                uint64_t *result_cas);
+
+   /**
+    * The noop command was received. This is just a notification callback (the
+    * response is automatically created).
+    *
+    * @param cookie id of the client receiving the command
+    */
+   protocol_binary_response_status (*noop)(const void *cookie);
+
+   /**
+    * Prepend data to an <b>existing</b> key-value pair.
+    *
+    * @param cookie id of the client receiving the command
+    * @param key the key to prepend data to
+    * @param len the length of the key
+    * @param val the value to prepend to the value
+    * @param vallen the length of the data
+    * @param cas the CAS in the request
+    * @param result-cas the cas id of the item
+    *
+    */
+   protocol_binary_response_status (*prepend)(const void *cookie,
+                                              const void *key,
+                                              uint16_t keylen,
+                                              const void* val,
+                                              uint32_t vallen,
+                                              uint64_t cas,
+                                              uint64_t *result_cas);
+
+   /**
+    * The quit command was received. This is just a notification callback (the
+    * response is automatically created).
+    *
+    * @param cookie id of the client receiving the command
+    */
+   protocol_binary_response_status (*quit)(const void *cookie);
+
+
+   /**
+    * Replace an <b>existing</b> item to the cache
+    *
+    * @param cookie id of the client receiving the command
+    * @param key the key to replace the content for
+    * @param len the length of the key
+    * @param val the value to store for the key (may be NIL)
+    * @param vallen the length of the data
+    * @param flags the flags to store with the key
+    * @param exptime the expiry time for the key-value pair
+    * @param cas the cas id in the request
+    * @param result_cas the cas id of the item
+    */
+   protocol_binary_response_status (*replace)(const void *cookie,
+                                              const void *key,
+                                              uint16_t keylen,
+                                              const void* val,
+                                              uint32_t vallen,
+                                              uint32_t flags,
+                                              uint32_t exptime,
+                                              uint64_t cas,
+                                              uint64_t *result_cas);
+
+
+   /**
+    * Set a key-value pair in the cache
+    *
+    * @param cookie id of the client receiving the command
+    * @param key the key to insert
+    * @param len the length of the key
+    * @param val the value to store for the key (may be NIL)
+    * @param vallen the length of the data
+    * @param flags the flags to store with the key
+    * @param exptime the expiry time for the key-value pair
+    * @param cas the cas id in the request
+    * @param result_cas the cas id of the new item
+    */
+   protocol_binary_response_status (*set)(const void *cookie,
+                                          const void *key,
+                                          uint16_t keylen,
+                                          const void* val,
+                                          uint32_t vallen,
+                                          uint32_t flags,
+                                          uint32_t exptime,
+                                          uint64_t cas,
+                                          uint64_t *result_cas);
+
+   /**
+    * Get status information
+    *
+    * @param cookie id of the client receiving the command
+    * @param key the key to get status for (or NIL to request all status).
+    *            Remember to insert the terminating packet if multiple
+    *            packets should be returned.
+    * @param keylen the length of the key
+    * @param response_handler to send the result back to the client, but
+    *                         don't send reply on success!
+    *
+    */
+   protocol_binary_response_status (*stat)(const void *cookie,
+                                           const void *key,
+                                           uint16_t keylen,
+                                           memcached_binary_protocol_stat_response_handler response_handler);
+
+   /**
+    * Get the version information
+    *
+    * @param cookie id of the client receiving the command
+    * @param response_handler to send the result back to the client, but
+    *                         don't send reply on success!
+    *
+    */
+   protocol_binary_response_status (*version)(const void *cookie,
+                                              memcached_binary_protocol_version_response_handler response_handler);
+} memcached_binary_protocol_callback_v1_st;
+
+
+/**
+ * The version numbers for the different callback structures.
+ */
+typedef enum {
+   /** Version 0 is a lowlevel interface that tries to maximize your freedom */
+   MEMCACHED_PROTOCOL_HANDLER_V0= 0,
+   /**
+    * Version 1 abstracts more of the protocol details, and let you work at
+    * a logical level
+    */
+   MEMCACHED_PROTOCOL_HANDLER_V1= 1
+} memcached_protocol_interface_version_t;
+
+/**
+ * Definition of the protocol callback structure.
+ */
+typedef struct {
+   /**
+    * The interface version you provide callbacks for.
+    */
+   memcached_protocol_interface_version_t interface_version;
+
+   /**
+    * Callback fired just before the command will be executed.
+    *
+    * @param cookie id of the client receiving the command
+    * @param header the command header as received on the wire. If you look
+    *               at the content you <b>must</b> ensure that you don't
+    *               try to access beyond the end of the message.
+    */
+   void (*pre_execute)(const void *cookie,
+                       protocol_binary_request_header *header);
+   /**
+    * Callback fired just after the command was exected (please note
+    * that the data transfer back to the client is not finished at this
+    * time).
+    *
+    * @param cookie id of the client receiving the command
+    * @param header the command header as received on the wire. If you look
+    *               at the content you <b>must</b> ensure that you don't
+    *               try to access beyond the end of the message.
+    */
+   void (*post_execute)(const void *cookie,
+                        protocol_binary_request_header *header);
+
+   /**
+    * Callback fired if no specialized callback is registered for this
+    * specific command code.
+    *
+    * @param cookie id of the client receiving the command
+    * @param header the command header as received on the wire. You <b>must</b>
+    *               ensure that you don't try to access beyond the end of the
+    *               message.
+    * @param response_handler The response handler to send data back.
+    */
+   protocol_binary_response_status (*unknown)(const void *cookie,
+                                              protocol_binary_request_header *header,
+                                              memcached_binary_protocol_raw_response_handler response_handler);
+
+   /**
+    * The different interface levels we support. A pointer is used so the
+    * size of the structure is fixed. You must ensure that the memory area
+    * passed as the pointer is valid as long as you use the protocol handler.
+    */
+   union {
+      memcached_binary_protocol_callback_v0_st v0;
+
+      /**
+       * The first version of the callback struct containing all of the
+       * documented commands in the initial release of the binary protocol
+       * (aka. memcached 1.4.0).
+       */
+      memcached_binary_protocol_callback_v1_st v1;
+   } interface;
+} memcached_binary_protocol_callback_st;
diff --git a/include/libmemcachedprotocol-0.0/handler.h b/include/libmemcachedprotocol-0.0/handler.h
new file mode 100644 (file)
index 0000000..113338d
--- /dev/null
@@ -0,0 +1,218 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Definition of the callback interface to the protocol handler
+ *
+ * Author: Trond Norbye
+ *
+ */
+
+#pragma once
+
+#include <sys/types.h>
+#if !defined(__cplusplus)
+# include <stdbool.h>
+#endif
+
+#include <libmemcached-1.0/visibility.h>
+#include <libmemcached-1.0/platform.h>
+#include <libmemcachedprotocol-0.0/binary.h>
+#include <libmemcachedprotocol-0.0/callback.h>
+
+/* Forward declarations */
+/*
+ * You should only access memcached_protocol_st from one thread!,
+ * and never assume anything about the internal layout / sizes of the
+ * structures.
+ */
+typedef struct memcached_protocol_st memcached_protocol_st;
+typedef struct memcached_protocol_client_st memcached_protocol_client_st;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Function the protocol handler should call to receive data.
+ * This function should behave exactly like read(2)
+ *
+ * @param cookie a cookie used to represent a given client
+ * @param fd the filedescriptor associated with the client
+ * @param buf destination buffer
+ * @param nbuf number of bytes to receive
+ * @return the number of bytes copied into buf
+ *         or -1 upon error (errno should contain more information)
+ */
+typedef ssize_t (*memcached_protocol_recv_func)(const void *cookie,
+                                                memcached_socket_t fd,
+                                                void *buf,
+                                                size_t nbuf);
+
+/**
+ * Function the protocol handler should call to send data.
+ * This function should behave exactly like write(2)
+ *
+ * @param cookie a cookie used to represent a given client
+ * @param fd the filedescriptor associated with the client
+ * @param buf the source buffer
+ * @param nbuf number of bytes to send
+ * @return the number of bytes sent
+ *         or -1 upon error (errno should contain more information)
+ */
+typedef ssize_t (*memcached_protocol_send_func)(const void *cookie,
+                                                memcached_socket_t fd,
+                                                const void *buf,
+                                                size_t nbuf);
+
+/**
+ * Create an instance of the protocol handler
+ *
+ * @return NULL if allocation of an instance fails
+ */
+LIBMEMCACHED_API
+memcached_protocol_st *memcached_protocol_create_instance(void);
+
+/**
+ * Get the callbacks associated with a protocol handler instance
+ * @return the callbacks currently used
+ */
+LIBMEMCACHED_API
+memcached_binary_protocol_callback_st *memcached_binary_protocol_get_callbacks(memcached_protocol_st *instance);
+
+/**
+ * Set the callbacks to be used by the given protocol handler instance
+ * @param instance the instance to update
+ * @param callback the callbacks to use
+ */
+LIBMEMCACHED_API
+void memcached_binary_protocol_set_callbacks(memcached_protocol_st *instance, memcached_binary_protocol_callback_st *callback);
+
+/**
+ * Should the library inspect the packages being sent and received and verify
+ * that they are according to the specification? If it encounters an invalid
+ * packet, it will return an EINVAL packet.
+ *
+ * @param instance the instance to update
+ * @param enable true if you want the library to check packages, false otherwise
+ */
+LIBMEMCACHED_API
+void memcached_binary_protocol_set_pedantic(memcached_protocol_st *instance, bool enable);
+
+/**
+ * Is the library inpecting each package?
+ * @param instance the instance to check
+ * @return true it the library is inspecting each package, false otherwise
+ */
+LIBMEMCACHED_API
+bool memcached_binary_protocol_get_pedantic(memcached_protocol_st *instance);
+
+/**
+ * Destroy an instance of the protocol handler
+ *
+ * @param instance The instance to destroy
+ */
+LIBMEMCACHED_API
+void memcached_protocol_destroy_instance(memcached_protocol_st *instance);
+
+/**
+ * Set the IO functions used by the instance to send and receive data. The
+ * functions should behave like recv(3socket) and send(3socket).
+ *
+ * @param instance the instance to specify the IO functions for
+ * @param recv the function to call for reciving data
+ * @param send the function to call for sending data
+ */
+LIBMEMCACHED_API
+void memached_protocol_set_io_functions(memcached_protocol_st *instance,
+                                        memcached_protocol_recv_func recv,
+                                        memcached_protocol_send_func send);
+
+
+/**
+ * Create a new client instance and associate it with a socket
+ * @param instance the protocol instance to bind the client to
+ * @param sock the client socket
+ * @return NULL if allocation fails, otherwise an instance
+ */
+LIBMEMCACHED_API
+memcached_protocol_client_st *memcached_protocol_create_client(memcached_protocol_st *instance, memcached_socket_t sock);
+
+/**
+ * Destroy a client handle.
+ * The caller needs to close the socket accociated with the client
+ * <b>before</b> calling this function. This function invalidates the
+ * client memory area.
+ *
+ * @param client the client to destroy
+ */
+LIBMEMCACHED_API
+void memcached_protocol_client_destroy(memcached_protocol_client_st *client);
+
+LIBMEMCACHED_API
+void memcached_protocol_client_set_verbose(struct memcached_protocol_client_st *client, bool arg);
+
+/**
+ * Error event means that the client encountered an error with the
+ * connection so you should shut it down
+ */
+#define MEMCACHED_PROTOCOL_ERROR_EVENT 1
+/**
+ * Please notify when there is more data available to read
+ */
+#define MEMCACHED_PROTOCOL_READ_EVENT 2
+/**
+ * Please notify when it is possible to send more data
+ */
+#define MEMCACHED_PROTOCOL_WRITE_EVENT 4
+/**
+ * Backed paused the execution for this client
+ */
+#define MEMCACHED_PROTOCOL_PAUSE_EVENT 8
+
+/**
+ * The different events the client is interested in. This is a bitmask of
+ * the constants defined above.
+ */
+typedef uint32_t memcached_protocol_event_t;
+
+/**
+ * Let the client do some work. This might involve reading / sending data
+ * to/from the client, or perform callbacks to execute a command.
+ * @param client the client structure to work on
+ * @return The next event the protocol handler will be notified for
+ */
+LIBMEMCACHED_API
+memcached_protocol_event_t memcached_protocol_client_work(memcached_protocol_client_st *client);
+
+/**
+ * Get the socket attached to a client handle
+ * @param client the client to query
+ * @return the socket handle
+ */
+LIBMEMCACHED_API
+memcached_socket_t memcached_protocol_client_get_socket(memcached_protocol_client_st *client);
+
+/**
+ * Get the error id socket attached to a client handle
+ * @param client the client to query for an error code
+ * @return the OS error code from the client
+ */
+LIBMEMCACHED_API
+int memcached_protocol_client_get_errno(memcached_protocol_client_st *client);
+
+/**
+ * Get a raw response handler for the given cookie
+ * @param cookie the cookie passed along into the callback
+ * @return the raw reponse handler you may use if you find
+ *         the generic callback too limiting
+ */
+LIBMEMCACHED_API
+memcached_binary_protocol_raw_response_handler memcached_binary_protocol_get_raw_response_handler(const void *cookie);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcachedprotocol-0.0/vbucket.h b/include/libmemcachedprotocol-0.0/vbucket.h
new file mode 100644 (file)
index 0000000..e2cc563
--- /dev/null
@@ -0,0 +1,59 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef enum {
+    vbucket_state_active = 1, /**< Actively servicing a vbucket. */
+    vbucket_state_replica, /**< Servicing a vbucket as a replica only. */
+    vbucket_state_pending, /**< Pending active. */
+    vbucket_state_dead /**< Not in use, pending deletion. */
+} vbucket_state_t;
+
+#define is_valid_vbucket_state_t(state) \
+    (state == vbucket_state_active || \
+     state == vbucket_state_replica || \
+     state == vbucket_state_pending || \
+     state == vbucket_state_dead)
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcachedutil-1.0/CMakeLists.txt b/include/libmemcachedutil-1.0/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c613887
--- /dev/null
@@ -0,0 +1,5 @@
+
+install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+        FILES_MATCHING REGEX "\\.h(pp)?$"
+        )
diff --git a/include/libmemcachedutil-1.0/flush.h b/include/libmemcachedutil-1.0/flush.h
new file mode 100644 (file)
index 0000000..dd7e779
--- /dev/null
@@ -0,0 +1,50 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+bool libmemcached_util_flush(const char *hostname, in_port_t port, memcached_return_t *ret);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/include/libmemcachedutil-1.0/ostream.hpp b/include/libmemcachedutil-1.0/ostream.hpp
new file mode 100644 (file)
index 0000000..cce7bfc
--- /dev/null
@@ -0,0 +1,50 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+static inline std::ostream& operator<<(std::ostream& output, const enum memcached_return_t &arg)
+{
+  output << memcached_strerror(NULL, arg);
+  return output;
+}
+
+static inline std::ostream& operator<<(std::ostream& output, const memcached_st &arg)
+{
+  output << " query_id: " <<  memcached_query_id(&arg);
+  output << " error: " <<  memcached_last_error_message(&arg);
+  return output;
+}
diff --git a/include/libmemcachedutil-1.0/pid.h b/include/libmemcachedutil-1.0/pid.h
new file mode 100644 (file)
index 0000000..3ce0131
--- /dev/null
@@ -0,0 +1,58 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifndef _WIN32
+# include <netdb.h>
+#endif
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_return_t *ret);
+
+LIBMEMCACHED_API
+pid_t libmemcached_util_getpid2(const char *hostname, in_port_t port, const char *username, const char *password,  memcached_return_t *ret);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/include/libmemcachedutil-1.0/ping.h b/include/libmemcachedutil-1.0/ping.h
new file mode 100644 (file)
index 0000000..faea8b2
--- /dev/null
@@ -0,0 +1,52 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret);
+
+LIBMEMCACHED_API
+bool libmemcached_util_ping2(const char *hostname, in_port_t port, const char *username, const char *password,  memcached_return_t *ret);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/include/libmemcachedutil-1.0/pool.h b/include/libmemcachedutil-1.0/pool.h
new file mode 100644 (file)
index 0000000..a11117c
--- /dev/null
@@ -0,0 +1,83 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#include <libmemcached-1.0/memcached.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct memcached_pool_st;
+typedef struct memcached_pool_st memcached_pool_st;
+
+LIBMEMCACHED_API
+memcached_pool_st *memcached_pool_create(memcached_st* mmc, uint32_t initial, uint32_t max);
+
+LIBMEMCACHED_API
+memcached_pool_st *memcached_pool(const char *option_string, size_t option_string_length);
+
+LIBMEMCACHED_API
+memcached_st* memcached_pool_destroy(memcached_pool_st* pool);
+
+LIBMEMCACHED_API
+memcached_st* memcached_pool_pop(memcached_pool_st* pool,
+                                 bool block,
+                                 memcached_return_t* rc);
+LIBMEMCACHED_API
+  memcached_return_t memcached_pool_push(memcached_pool_st* pool,
+                                         memcached_st* mmc);
+LIBMEMCACHED_API
+  memcached_return_t memcached_pool_release(memcached_pool_st* pool, memcached_st* mmc);
+
+LIBMEMCACHED_API
+memcached_st* memcached_pool_fetch(memcached_pool_st*, struct timespec* relative_time, memcached_return_t* rc);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_pool_behavior_set(memcached_pool_st *ptr,
+                                               memcached_behavior_t flag,
+                                               uint64_t data);
+LIBMEMCACHED_API
+memcached_return_t memcached_pool_behavior_get(memcached_pool_st *ptr,
+                                               memcached_behavior_t flag,
+                                               uint64_t *value);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/include/libmemcachedutil-1.0/util.h b/include/libmemcachedutil-1.0/util.h
new file mode 100644 (file)
index 0000000..d362098
--- /dev/null
@@ -0,0 +1,46 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libmemcached-1.0/memcached.h>
+
+#include <libmemcachedutil-1.0/pid.h>
+#include <libmemcachedutil-1.0/flush.h>
+#include <libmemcachedutil-1.0/ping.h>
+#include <libmemcachedutil-1.0/pool.h>
+#include <libmemcachedutil-1.0/version.h>
diff --git a/include/libmemcachedutil-1.0/version.h b/include/libmemcachedutil-1.0/version.h
new file mode 100644 (file)
index 0000000..372283a
--- /dev/null
@@ -0,0 +1,53 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+  bool libmemcached_util_version_check(memcached_st *memc, 
+                                       uint8_t major_version,
+                                       uint8_t minor_version,
+                                       uint8_t micro_version);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libhashkit-1.0/CMakeLists.txt b/libhashkit-1.0/CMakeLists.txt
deleted file mode 100644 (file)
index 7fc72a3..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-
-configure_file(configure.h.in configure.h @ONLY)
-
-install(DIRECTORY ../libhashkit-1.0
-        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
-        FILES_MATCHING REGEX "\\.h(pp)?$"
-        )
diff --git a/libhashkit-1.0/algorithm.h b/libhashkit-1.0/algorithm.h
deleted file mode 100644 (file)
index 72005aa..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-/**
- * @file
- * @brief HashKit Header
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HASHKIT_API
-uint32_t libhashkit_one_at_a_time(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_fnv1_64(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_fnv1a_64(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_fnv1_32(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_fnv1a_32(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_crc32(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_hsieh(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_murmur(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_murmur3(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_jenkins(const char *key, size_t key_length);
-
-HASHKIT_API
-uint32_t libhashkit_md5(const char *key, size_t key_length);
-
-HASHKIT_API
-void libhashkit_md5_signature(const unsigned char *key, size_t length, unsigned char *result);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libhashkit-1.0/basic_string.h b/libhashkit-1.0/basic_string.h
deleted file mode 100644 (file)
index 1cb17e3..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-
-#pragma once
-
-// No assumptions of NULL should be made
-
-#define hashkit_size(X) (X).size;
-#define hashkit_c_str(X) (X).c_str;
-#define hashkit_string_param(X) (X).c_str, (X).size
-
-#ifdef __cplusplus
-#define hashkit_string_printf(X) int((X).size), (X).c_str
-#else
-#define hashkit_string_printf(X) (int)((X).size), (X).c_str
-#endif
-
diff --git a/libhashkit-1.0/behavior.h b/libhashkit-1.0/behavior.h
deleted file mode 100644 (file)
index 8cc5709..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-
-
-
-/**
- * @file
- * @brief HashKit Header
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libhashkit-1.0/configure.h.in b/libhashkit-1.0/configure.h.in
deleted file mode 100644 (file)
index 508ff7b..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-
-
-
-#pragma once
-
-#define LIBHASHKIT_VERSION_STRING "@LIBHASHKIT_VERSION@"
-#define LIBHASHKIT_VERSION_HEX @LIBHASHKIT_VERSION_HEX@
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libhashkit-1.0/digest.h b/libhashkit-1.0/digest.h
deleted file mode 100644 (file)
index c34dc8a..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-
-
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HASHKIT_API
-uint32_t hashkit_digest(const hashkit_st *self, const char *key, size_t key_length);
-
-/**
-  This is a utilitly function provided so that you can directly access hashes with a hashkit_st.
-*/
-
-HASHKIT_API
-uint32_t libhashkit_digest(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libhashkit-1.0/function.h b/libhashkit-1.0/function.h
deleted file mode 100644 (file)
index 664a008..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
-  This sets/gets the default function we will be using.
-*/
-HASHKIT_API
-hashkit_return_t hashkit_set_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm);
-
-HASHKIT_API
-hashkit_return_t hashkit_set_custom_function(hashkit_st *hash, hashkit_hash_fn function, void *context);
-
-HASHKIT_API
-hashkit_hash_algorithm_t hashkit_get_function(const hashkit_st *hash);
-
-/**
-  This sets/gets the function we use for distribution.
-*/
-HASHKIT_API
-hashkit_return_t hashkit_set_distribution_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm);
-
-HASHKIT_API
-hashkit_return_t hashkit_set_custom_distribution_function(hashkit_st *self, hashkit_hash_fn function, void *context);
-
-HASHKIT_API
-hashkit_hash_algorithm_t hashkit_get_distribution_function(const hashkit_st *self);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libhashkit-1.0/has.h b/libhashkit-1.0/has.h
deleted file mode 100644 (file)
index 35e8616..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HASHKIT_API
-bool libhashkit_has_algorithm(const hashkit_hash_algorithm_t);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libhashkit-1.0/hashkit.h b/libhashkit-1.0/hashkit.h
deleted file mode 100644 (file)
index da9bd36..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-
-
-
-#pragma once
-
-
-#if !defined(__cplusplus)
-# include <stdbool.h>
-#endif
-#include <inttypes.h>
-#include <sys/types.h>
-
-#include <libhashkit-1.0/visibility.h>
-#include <libhashkit-1.0/configure.h>
-#include <libhashkit-1.0/types.h>
-#include <libhashkit-1.0/has.h>
-#include <libhashkit-1.0/algorithm.h>
-#include <libhashkit-1.0/behavior.h>
-#include <libhashkit-1.0/digest.h>
-#include <libhashkit-1.0/function.h>
-#include <libhashkit-1.0/str_algorithm.h>
-#include <libhashkit-1.0/strerror.h>
-#include <libhashkit-1.0/string.h>
-
-struct hashkit_st
-{
-  struct hashkit_function_st {
-    hashkit_hash_fn function;
-    void *context;
-  } base_hash, distribution_hash;
-
-  struct {
-    bool is_base_same_distributed:1;
-  } flags;
-
-  struct {
-    bool is_allocated:1;
-  } options;
-
-  void *_key;
-};
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HASHKIT_API
-  hashkit_st *hashkit_create(hashkit_st *hash);
-
-HASHKIT_API
-  hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *ptr);
-
-HASHKIT_API
-  bool hashkit_compare(const hashkit_st *first, const hashkit_st *second);
-
-HASHKIT_API
-  void hashkit_free(hashkit_st *hash);
-
-HASHKIT_API
-  hashkit_string_st *hashkit_encrypt(hashkit_st *,
-                                     const char* source, size_t source_length);
-
-HASHKIT_API
-  hashkit_string_st *hashkit_decrypt(hashkit_st *,
-                                     const char* source, size_t source_length);
-
-HASHKIT_API
-  bool hashkit_key(hashkit_st *, const char *key, const size_t key_length);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/libhashkit-1.0/hashkit.hpp b/libhashkit-1.0/hashkit.hpp
deleted file mode 100644 (file)
index a953d72..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#include <libhashkit-1.0/hashkit.h>
-#include <string>
-
-class Hashkit {
-
-public:
-
-  Hashkit()
-  {
-    hashkit_create(&self);
-  }
-
-  Hashkit(const Hashkit& source)
-  {
-    hashkit_clone(&self, &source.self);
-  }
-
-  Hashkit& operator=(const Hashkit& source)
-  {
-    hashkit_free(&self);
-    hashkit_clone(&self, &source.self);
-
-    return *this;
-  }
-
-  friend bool operator==(const Hashkit &left, const Hashkit &right)
-  {
-    return hashkit_compare(&left.self, &right.self);
-  }
-
-  uint32_t digest(std::string& str)
-  {
-    return hashkit_digest(&self, str.c_str(), str.length());
-  }
-
-  uint32_t digest(const char *key, size_t key_length)
-  {
-    return hashkit_digest(&self, key, key_length);
-  }
-
-  hashkit_return_t set_function(hashkit_hash_algorithm_t hash_algorithm)
-  {
-    return hashkit_set_function(&self, hash_algorithm);
-  }
-
-  hashkit_return_t set_distribution_function(hashkit_hash_algorithm_t hash_algorithm)
-  {
-    return hashkit_set_function(&self, hash_algorithm);
-  }
-
-  ~Hashkit()
-  {
-    hashkit_free(&self);
-  }
-private:
-
-  hashkit_st self;
-};
diff --git a/libhashkit-1.0/str_algorithm.h b/libhashkit-1.0/str_algorithm.h
deleted file mode 100644 (file)
index bb05eb5..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HASHKIT_API
-const char *libhashkit_string_hash(hashkit_hash_algorithm_t type);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libhashkit-1.0/strerror.h b/libhashkit-1.0/strerror.h
deleted file mode 100644 (file)
index 79eb145..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HASHKIT_API
-  const char *hashkit_strerror(hashkit_st *ptr, hashkit_return_t rc);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libhashkit-1.0/string.h b/libhashkit-1.0/string.h
deleted file mode 100644 (file)
index 90cb3ae..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#ifdef __cplusplus
-struct hashkit_string_st;
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-HASHKIT_API
-void hashkit_string_free(hashkit_string_st *ptr);
-
-
-HASHKIT_API
-size_t hashkit_string_length(const hashkit_string_st *self);
-
-HASHKIT_API
-const char *hashkit_string_c_str(const hashkit_string_st* self);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-
diff --git a/libhashkit-1.0/types.h b/libhashkit-1.0/types.h
deleted file mode 100644 (file)
index 37c33ee..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009-2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-typedef enum {
-  HASHKIT_SUCCESS,
-  HASHKIT_FAILURE,
-  HASHKIT_MEMORY_ALLOCATION_FAILURE,
-  HASHKIT_INVALID_HASH,
-  HASHKIT_INVALID_ARGUMENT,
-  HASHKIT_MAXIMUM_RETURN /* Always add new error code before */
-} hashkit_return_t;
-
-static inline bool hashkit_success(const hashkit_return_t rc)
-{
-  return (rc == HASHKIT_SUCCESS);
-}
-
-static inline bool hashkit_failed(const hashkit_return_t rc)
-{
-  return (rc != HASHKIT_SUCCESS);
-}
-
-typedef enum {
-  HASHKIT_HASH_DEFAULT= 0, // hashkit_one_at_a_time()
-  HASHKIT_HASH_MD5,
-  HASHKIT_HASH_CRC,
-  HASHKIT_HASH_FNV1_64,
-  HASHKIT_HASH_FNV1A_64,
-  HASHKIT_HASH_FNV1_32,
-  HASHKIT_HASH_FNV1A_32,
-  HASHKIT_HASH_HSIEH,
-  HASHKIT_HASH_MURMUR,
-  HASHKIT_HASH_JENKINS,
-  HASHKIT_HASH_MURMUR3,
-  HASHKIT_HASH_CUSTOM,
-  HASHKIT_HASH_MAX
-} hashkit_hash_algorithm_t;
-
-/**
- * Hash distributions that are available to use.
- */
-typedef enum
-{
-  HASHKIT_DISTRIBUTION_MODULA,
-  HASHKIT_DISTRIBUTION_RANDOM,
-  HASHKIT_DISTRIBUTION_KETAMA,
-  HASHKIT_DISTRIBUTION_MAX /* Always add new values before this. */
-} hashkit_distribution_t;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct hashkit_st hashkit_st;
-typedef struct hashkit_string_st hashkit_string_st;
-
-typedef uint32_t (*hashkit_hash_fn)(const char *key, size_t key_length, void *context);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libhashkit-1.0/visibility.h b/libhashkit-1.0/visibility.h
deleted file mode 100644 (file)
index b8f194c..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Summary: interface for HashKit functions
- * Description: visibitliy macros for HashKit library
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in this directory for full text.
- * 
- * Author: Monty Taylor
- */
-
-/**
- * @file
- * @brief Visibility control macros
- */
-
-#pragma once
-
-/**
- *
- * HASHKIT_API is used for the public API symbols. It either DLL imports or
- * DLL exports (or does nothing for static build).
- *
- * HASHKIT_LOCAL is used for non-api symbols.
- */
-
-#if defined(BUILDING_HASHKIT)
-# if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
-#  define HASHKIT_API __attribute__ ((visibility("default")))
-#  define HASHKIT_LOCAL  __attribute__ ((visibility("hidden")))
-# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
-#  define HASHKIT_API __global
-#  define HASHKIT_LOCAL __hidden
-# elif defined(_MSC_VER)
-#  define HASHKIT_API extern __declspec(dllexport) 
-#  define HASHKIT_LOCAL
-# else
-#  define HASHKIT_API
-#  define HASHKIT_LOCAL
-# endif /* defined(HAVE_VISIBILITY) */
-#else  /* defined(BUILDING_HASHKIT) */
-# if defined(_MSC_VER)
-#  define HASHKIT_API extern __declspec(dllimport) 
-#  define HASHKIT_LOCAL
-# else
-#  define HASHKIT_API
-#  define HASHKIT_LOCAL
-# endif /* defined(_MSC_VER) */
-#endif /* defined(BUILDING_HASHKIT) */
diff --git a/libhashkit/CMakeLists.txt b/libhashkit/CMakeLists.txt
deleted file mode 100644 (file)
index 646ffd3..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-if(HAVE_HSIEH_HASH)
-    set(HSIEH_CC hsieh.cc)
-else()
-    set(HSIEH_CC nohsieh.cc)
-endif()
-
-add_library(libhashkit SHARED
-        aes.cc
-        algorithm.cc
-        behavior.cc
-        crc32.cc
-        digest.cc
-        encrypt.cc
-        fnv_32.cc
-        fnv_64.cc
-        function.cc
-        has.cc
-        hashkit.cc
-        ${HSIEH_CC}
-        jenkins.cc
-        ketama.cc
-        md5.cc
-        murmur.cc
-        murmur3.cc
-        murmur3_api.cc
-        nohsieh.cc
-        one_at_a_time.cc
-        rijndael.cc
-        str_algorithm.cc
-        strerror.cc
-        string.cc
-        )
-add_library(hashkit ALIAS libhashkit)
-set_target_properties(libhashkit PROPERTIES LIBRARY_OUTPUT_NAME hashkit)
-target_include_directories(libhashkit PRIVATE ..)
-target_compile_options(libhashkit PRIVATE -DBUILDING_HASHKIT)
-
-configure_file(hashkitcon.h.in hashkitcon.h @ONLY)
-
-set_target_properties(libhashkit PROPERTIES SOVERSION ${LIBHASHKIT_SO_VERSION})
-install(TARGETS libhashkit EXPORT libhashkit
-        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
-export(EXPORT libhashkit)
-install(EXPORT libhashkit DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake)
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
-        FILES_MATCHING PATTERN hashkit.h
-        )
diff --git a/libhashkit/aes.cc b/libhashkit/aes.cc
deleted file mode 100644 (file)
index 12adcae..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libhashkit library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include "libhashkit/common.h"
-
-#include "libhashkit/rijndael.hpp"
-
-#include <cstring>
-
-#define AES_KEY_LENGTH 256               /* 128, 192, 256 */
-#define AES_BLOCK_SIZE 16
-
-enum encrypt_t
-{
-  AES_ENCRYPT,
-  AES_DECRYPT
-};
-
-struct _key_t {
-  int nr;
-  uint32_t rk[4*(AES_MAXNR +1)];
-};
-
-struct aes_key_t {
-  _key_t encode_key;
-  _key_t decode_key;
-};
-
-aes_key_t* aes_create_key(const char *key, const size_t key_length)
-{
-  aes_key_t* _aes_key= (aes_key_t*)(calloc(1, sizeof(aes_key_t)));
-  if (_aes_key)
-  {
-    uint8_t rkey[AES_KEY_LENGTH/8];
-    uint8_t *rkey_end= rkey +AES_KEY_LENGTH/8;
-    const char *key_end= key +key_length;
-
-    memset(rkey, 0, sizeof(rkey));      /* Set initial key  */
-
-    uint8_t *ptr= rkey;
-    const char* sptr= key;
-    for (; sptr < key_end; ptr++,sptr++)
-    {
-      if (ptr == rkey_end)
-      {
-        ptr= rkey;  /*  Just loop over tmp_key until we used all key */
-      }
-      *ptr^= (uint8_t)(*sptr);
-    }
-
-    _aes_key->decode_key.nr= rijndaelKeySetupDec(_aes_key->decode_key.rk, rkey, AES_KEY_LENGTH);
-    _aes_key->encode_key.nr= rijndaelKeySetupEnc(_aes_key->encode_key.rk, rkey, AES_KEY_LENGTH);
-  }
-
-  return _aes_key;
-}
-
-aes_key_t* aes_clone_key(aes_key_t *_aes_key)
-{
-  if (_aes_key == NULL)
-  {
-    return NULL;
-  }
-
-  aes_key_t* _aes_clone_key= (aes_key_t*)(calloc(1, sizeof(aes_key_t)));
-  if (_aes_clone_key)
-  {
-    memcpy(_aes_clone_key, _aes_key, sizeof(aes_key_t));
-  }
-
-  return _aes_clone_key;
-}
-
-hashkit_string_st* aes_encrypt(aes_key_t *_aes_key,
-                               const char* source, size_t source_length)
-{
-  if (_aes_key == NULL)
-  {
-    return NULL;
-  }
-
-  size_t num_blocks= source_length/AES_BLOCK_SIZE;
-
-  hashkit_string_st* destination= hashkit_string_create(source_length);
-  if (destination)
-  {
-    char *dest= hashkit_string_c_str_mutable(destination);
-
-    for (size_t x= num_blocks; x > 0; x--)   /* Encode complete blocks */
-    { 
-      rijndaelEncrypt(_aes_key->encode_key.rk, _aes_key->encode_key.nr, (const uint8_t*)(source),
-                      (uint8_t*) (dest));
-      source+= AES_BLOCK_SIZE;
-      dest+= AES_BLOCK_SIZE;
-    }
-
-    uint8_t block[AES_BLOCK_SIZE];
-    char pad_len= AES_BLOCK_SIZE - (source_length - AES_BLOCK_SIZE*num_blocks);
-    memcpy(block, source, 16 -pad_len);
-    memset(block + AES_BLOCK_SIZE -pad_len, pad_len, pad_len);
-    rijndaelEncrypt(_aes_key->encode_key.rk, _aes_key->encode_key.nr, block, (uint8_t*) (dest));
-    hashkit_string_set_length(destination, AES_BLOCK_SIZE*(num_blocks + 1));
-  }
-
-  return destination;
-}
-
-hashkit_string_st* aes_decrypt(aes_key_t *_aes_key,
-                               const char* source, size_t source_length)
-{
-  if (_aes_key == NULL)
-  {
-    return NULL;
-  }
-
-  size_t num_blocks= source_length/AES_BLOCK_SIZE;
-  if ((source_length != num_blocks*AES_BLOCK_SIZE) or num_blocks ==0 )
-  {
-    return NULL;
-  }
-
-  hashkit_string_st* destination= hashkit_string_create(source_length);
-  if (destination)
-  {
-    char *dest= hashkit_string_c_str_mutable(destination);
-
-    for (size_t x = num_blocks-1; x > 0; x--)
-    {
-      rijndaelDecrypt(_aes_key->decode_key.rk, _aes_key->decode_key.nr, (const uint8_t*) (source), (uint8_t*)(dest));
-      source+= AES_BLOCK_SIZE;
-      dest+= AES_BLOCK_SIZE;
-    }
-
-    uint8_t block[AES_BLOCK_SIZE];
-    rijndaelDecrypt(_aes_key->decode_key.rk, _aes_key->decode_key.nr, (const uint8_t*)(source), block);
-    /* Use last char in the block as size */
-    unsigned int pad_len= (unsigned int) (unsigned char)(block[AES_BLOCK_SIZE-1]);
-    if (pad_len > AES_BLOCK_SIZE)
-    {
-      hashkit_string_free(destination);
-      return NULL;
-    }
-
-    /* We could also check whole padding but we do not really need this */
-
-    memcpy(dest, block, AES_BLOCK_SIZE - pad_len);
-    hashkit_string_set_length(destination, AES_BLOCK_SIZE*num_blocks - pad_len);
-  }
-
-  return destination;
-}
diff --git a/libhashkit/aes.h b/libhashkit/aes.h
deleted file mode 100644 (file)
index c46ffa2..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-struct aes_key_t;
-
-hashkit_string_st* aes_encrypt(aes_key_t* _aes_key,
-                               const char* source, size_t source_length);
-
-hashkit_string_st* aes_decrypt(aes_key_t* _aes_key,
-                               const char* source, size_t source_length);
-
-aes_key_t* aes_create_key(const char *key, const size_t key_length);
-
-aes_key_t* aes_clone_key(aes_key_t* _aes_key);
diff --git a/libhashkit/algorithm.cc b/libhashkit/algorithm.cc
deleted file mode 100644 (file)
index 3eb28d6..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  HashKit library
- *
- *  Copyright (C) 2006-2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libhashkit/common.h"
-
-uint32_t libhashkit_one_at_a_time(const char *key, size_t key_length)
-{
-  return hashkit_one_at_a_time(key, key_length, NULL);
-}
-
-uint32_t libhashkit_fnv1_64(const char *key, size_t key_length)
-{
-  return hashkit_fnv1_64(key, key_length, NULL);
-}
-
-uint32_t libhashkit_fnv1a_64(const char *key, size_t key_length)
-{
-  return hashkit_fnv1a_64(key, key_length, NULL);
-}
-
-uint32_t libhashkit_fnv1_32(const char *key, size_t key_length)
-{
-  return hashkit_fnv1_32(key, key_length, NULL);
-}
-
-uint32_t libhashkit_fnv1a_32(const char *key, size_t key_length)
-{
-  return hashkit_fnv1a_32(key, key_length, NULL);
-}
-
-uint32_t libhashkit_crc32(const char *key, size_t key_length)
-{
-  return hashkit_crc32(key, key_length, NULL);
-}
-
-uint32_t libhashkit_hsieh(const char *key, size_t key_length)
-{
-  return hashkit_hsieh(key, key_length, NULL);
-}
-
-uint32_t libhashkit_murmur3(const char *key, size_t key_length)
-{
-  return hashkit_murmur3(key, key_length, NULL);
-}
-
-uint32_t libhashkit_murmur(const char *key, size_t key_length)
-{
-  return hashkit_murmur(key, key_length, NULL);
-}
-
-uint32_t libhashkit_jenkins(const char *key, size_t key_length)
-{
-  return hashkit_jenkins(key, key_length, NULL);
-}
-
-uint32_t libhashkit_md5(const char *key, size_t key_length)
-{
-  return hashkit_md5(key, key_length, NULL);
-}
-
-void libhashkit_md5_signature(const unsigned char *key, size_t length, unsigned char *result)
-{
-  md5_signature(key, (uint32_t)length, result);
-}
-
diff --git a/libhashkit/algorithm.h b/libhashkit/algorithm.h
deleted file mode 100644 (file)
index 93cdc1d..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-/**
- * @file
- * @brief HashKit Header
- */
-
-#pragma once
-
-uint32_t hashkit_one_at_a_time(const char *key, size_t key_length, void *context);
-
-uint32_t hashkit_fnv1_64(const char *key, size_t key_length, void *context);
-
-uint32_t hashkit_fnv1a_64(const char *key, size_t key_length, void *context);
-
-uint32_t hashkit_fnv1_32(const char *key, size_t key_length, void *context);
-
-uint32_t hashkit_fnv1a_32(const char *key, size_t key_length, void *context);
-
-uint32_t hashkit_crc32(const char *key, size_t key_length, void *context);
-
-uint32_t hashkit_hsieh(const char *key, size_t key_length, void *context);
-
-uint32_t hashkit_murmur(const char *key, size_t key_length, void *context);
-
-uint32_t hashkit_murmur3(const char *key, size_t key_length, void *context);
-
-uint32_t hashkit_jenkins(const char *key, size_t key_length, void *context);
-
-uint32_t hashkit_md5(const char *key, size_t key_length, void *context);
diff --git a/libhashkit/behavior.cc b/libhashkit/behavior.cc
deleted file mode 100644 (file)
index 6c7a9ac..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  HashKit library
- *
- *  Copyright (C) 2009-2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libhashkit/common.h>
diff --git a/libhashkit/common.h b/libhashkit/common.h
deleted file mode 100644 (file)
index d32d31b..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#include "libhashkit/hashkitcon.h"
-
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-#ifndef __WORDSIZE
-# ifdef __MINGW32__
-#  define __WORDSIZE 32
-# endif
-#endif
-
-#include <libhashkit-1.0/hashkit.h>
-#include "libhashkit/algorithm.h"
-#include "libhashkit/is.h"
-#include "libhashkit/string.h"
-#include "libhashkit/aes.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void md5_signature(const unsigned char *key, unsigned int length, unsigned char *result);
-
-int update_continuum(hashkit_st *hashkit);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libhashkit/crc32.cc b/libhashkit/crc32.cc
deleted file mode 100644 (file)
index fe9fe71..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  HashKit library
- *
- *  Copyright (C) 2009-2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* The crc32 functions and data was originally written by Spencer
- * Garrett <srg@quick.com> and was gleaned from the PostgreSQL source
- * tree via the files contrib/ltree/crc32.[ch] and from FreeBSD at
- * src/usr.bin/cksum/crc32.c.
- */
-
-#include <libhashkit/common.h>
-
-static const uint32_t crc32tab[256] = {
-  0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
-  0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
-  0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
-  0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
-  0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
-  0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
-  0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
-  0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
-  0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
-  0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
-  0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
-  0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
-  0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
-  0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
-  0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
-  0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
-  0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
-  0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
-  0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
-  0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
-  0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
-  0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
-  0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
-  0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
-  0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
-  0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
-  0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
-  0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
-  0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
-  0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
-  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
-  0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
-  0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
-  0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
-  0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
-  0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
-  0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
-  0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
-  0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
-  0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
-  0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
-  0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
-  0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
-  0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
-  0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
-  0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
-  0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
-  0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
-  0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
-  0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
-  0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
-  0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
-  0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
-  0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
-  0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
-  0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
-  0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
-  0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
-  0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
-  0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
-  0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
-  0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
-  0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
-  0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
-};
-
-uint32_t hashkit_crc32(const char *key, size_t key_length, void *context)
-{
-  uint64_t x;
-  uint32_t crc= UINT32_MAX;
-  (void)context;
-
-  for (x= 0; x < key_length; x++)
-     crc= (crc >> 8) ^ crc32tab[(crc ^ (uint64_t)key[x]) & 0xff];
-
-  return ((~crc) >> 16) & 0x7fff;
-}
diff --git a/libhashkit/digest.cc b/libhashkit/digest.cc
deleted file mode 100644 (file)
index 2300293..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  HashKit library
- *
- *  Copyright (C) 2010-2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libhashkit/common.h>
-
-uint32_t hashkit_digest(const hashkit_st *self, const char *key, size_t key_length)
-{
-  return self->base_hash.function(key, key_length, self->base_hash.context);
-}
-
-uint32_t libhashkit_digest(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm)
-{
-  switch (hash_algorithm)
-  {
-  case HASHKIT_HASH_DEFAULT:
-    return libhashkit_one_at_a_time(key, key_length);
-  case HASHKIT_HASH_MD5:
-    return libhashkit_md5(key, key_length);
-  case HASHKIT_HASH_CRC:
-    return libhashkit_crc32(key, key_length);
-  case HASHKIT_HASH_FNV1_64:
-    return libhashkit_fnv1_64(key, key_length);
-  case HASHKIT_HASH_FNV1A_64:
-    return libhashkit_fnv1a_64(key, key_length);
-  case HASHKIT_HASH_FNV1_32:
-    return libhashkit_fnv1_32(key, key_length);
-  case HASHKIT_HASH_FNV1A_32:
-    return libhashkit_fnv1a_32(key, key_length);
-  case HASHKIT_HASH_HSIEH:
-#ifdef HAVE_HSIEH_HASH
-    return libhashkit_hsieh(key, key_length);
-#else
-    return 1;
-#endif
-  case HASHKIT_HASH_MURMUR3:
-    return libhashkit_murmur3(key, key_length);
-
-  case HASHKIT_HASH_MURMUR:
-#ifdef HAVE_MURMUR_HASH
-    return libhashkit_murmur(key, key_length);
-#else
-    return 1;
-#endif
-  case HASHKIT_HASH_JENKINS:
-    return libhashkit_jenkins(key, key_length);
-  case HASHKIT_HASH_CUSTOM:
-  case HASHKIT_HASH_MAX:
-  default:
-    if (DEBUG)
-    {
-      fprintf(stderr, "hashkit_hash_t was extended but libhashkit_generate_value was not updated\n");
-      fflush(stderr);
-      assert(0);
-    }
-    break;
-  }
-
-  return 1;
-}
diff --git a/libhashkit/encrypt.cc b/libhashkit/encrypt.cc
deleted file mode 100644 (file)
index 95475d7..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libhashkit library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libhashkit/common.h>
-
-hashkit_string_st *hashkit_encrypt(hashkit_st *kit,
-                                   const char* source, size_t source_length)
-{
-  return aes_encrypt(static_cast<aes_key_t*>(kit->_key), source, source_length);
-}
-
-hashkit_string_st *hashkit_decrypt(hashkit_st *kit,
-                                   const char* source, size_t source_length)
-{
-  return aes_decrypt(static_cast<aes_key_t*>(kit->_key), source, source_length);
-}
-
-bool hashkit_key(hashkit_st *kit, const char *key, const size_t key_length)
-{
-  if (kit->_key)
-  {
-    free(kit->_key);
-  }
-
-  kit->_key= aes_create_key(key, key_length);
-  
-  return bool(kit->_key);
-}
-
diff --git a/libhashkit/fnv_32.cc b/libhashkit/fnv_32.cc
deleted file mode 100644 (file)
index 52eea80..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libhashkit/common.h>
-
-/* FNV hash'es lifted from Dustin Sallings work */
-static uint32_t FNV_32_INIT= 2166136261UL;
-static uint32_t FNV_32_PRIME= 16777619;
-
-uint32_t hashkit_fnv1_32(const char *key, size_t key_length, void *context)
-{
-  uint32_t hash= FNV_32_INIT;
-  (void)context;
-
-  for (size_t x= 0; x < key_length; x++)
-  {
-    uint32_t val= (uint32_t)key[x];
-    hash *= FNV_32_PRIME;
-    hash ^= val;
-  }
-
-  return hash;
-}
-
-uint32_t hashkit_fnv1a_32(const char *key, size_t key_length, void *context)
-{
-  uint32_t hash= FNV_32_INIT;
-  (void)context;
-
-  for (size_t x= 0; x < key_length; x++)
-  {
-    uint32_t val= (uint32_t)key[x];
-    hash ^= val;
-    hash *= FNV_32_PRIME;
-  }
-
-  return hash;
-}
diff --git a/libhashkit/fnv_64.cc b/libhashkit/fnv_64.cc
deleted file mode 100644 (file)
index 68e4dd0..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libhashkit/common.h>
-
-#if __WORDSIZE == 64 && defined(HAVE_FNV64_HASH)
-
-/* FNV hash'es lifted from Dustin Sallings work */
-static uint64_t FNV_64_INIT= 0xcbf29ce484222325;
-static uint64_t FNV_64_PRIME= 0x100000001b3;
-
-uint32_t hashkit_fnv1_64(const char *key, size_t key_length, void *)
-{
-  /* Thanks to pierre@demartines.com for the pointer */
-  uint64_t hash= FNV_64_INIT;
-
-  for (size_t x= 0; x < key_length; x++)
-  {
-    hash *= FNV_64_PRIME;
-    hash ^= (uint64_t)key[x];
-  }
-
-  return (uint32_t)hash;
-}
-
-uint32_t hashkit_fnv1a_64(const char *key, size_t key_length, void *)
-{
-  uint32_t hash= (uint32_t) FNV_64_INIT;
-
-  for (size_t x= 0; x < key_length; x++)
-  {
-    uint32_t val= (uint32_t)key[x];
-    hash ^= val;
-    hash *= (uint32_t) FNV_64_PRIME;
-  }
-
-  return hash;
-}
-
-#else
-uint32_t hashkit_fnv1_64(const char *, size_t, void *)
-{
-  return 0;
-}
-
-uint32_t hashkit_fnv1a_64(const char *, size_t, void *)
-{
-  return 0;
-}
-#endif
diff --git a/libhashkit/function.cc b/libhashkit/function.cc
deleted file mode 100644 (file)
index 3d530ae..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-/* HashKit
- * Copyright (C) 2010 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- */
-
-#include <libhashkit/common.h>
-
-static hashkit_return_t _set_function(struct hashkit_st::hashkit_function_st *self, hashkit_hash_algorithm_t hash_algorithm)
-{
-  if (self == NULL)
-  {
-    return HASHKIT_INVALID_ARGUMENT;
-  }
-
-  switch (hash_algorithm)
-  {
-  case HASHKIT_HASH_MD5:
-    self->function= hashkit_md5;
-    break;
-
-  case HASHKIT_HASH_CRC:
-    self->function= hashkit_crc32;
-    break;
-
-  case HASHKIT_HASH_FNV1_64:
-    if (libhashkit_has_algorithm(HASHKIT_HASH_FNV1_64))
-    {
-      self->function= hashkit_fnv1_64;
-      break;
-    }
-    return HASHKIT_INVALID_ARGUMENT;
-
-  case HASHKIT_HASH_FNV1A_64:
-    if (libhashkit_has_algorithm(HASHKIT_HASH_FNV1_64))
-    {
-      self->function= hashkit_fnv1a_64;
-      break;
-    }
-    return HASHKIT_INVALID_ARGUMENT;
-
-  case HASHKIT_HASH_FNV1_32:
-    self->function= hashkit_fnv1_32;
-    break;
-
-  case HASHKIT_HASH_FNV1A_32:
-    self->function= hashkit_fnv1a_32;
-    break;
-
-  case HASHKIT_HASH_HSIEH:
-    if (libhashkit_has_algorithm(HASHKIT_HASH_HSIEH))
-    {
-      self->function= hashkit_hsieh;
-      break;    
-    }
-    return HASHKIT_INVALID_ARGUMENT;
-
-  case HASHKIT_HASH_MURMUR3:
-    if (libhashkit_has_algorithm(HASHKIT_HASH_MURMUR3))
-    {
-      self->function= hashkit_murmur3;
-      break;
-    }
-    return HASHKIT_INVALID_ARGUMENT;
-  case HASHKIT_HASH_MURMUR:
-    if (libhashkit_has_algorithm(HASHKIT_HASH_MURMUR))
-    {
-      self->function= hashkit_murmur;
-      break;    
-    }
-    return HASHKIT_INVALID_ARGUMENT;
-
-  case HASHKIT_HASH_JENKINS:
-    self->function= hashkit_jenkins;
-    break;    
-
-  case HASHKIT_HASH_CUSTOM:
-    return HASHKIT_INVALID_ARGUMENT;
-
-  case HASHKIT_HASH_DEFAULT:
-    self->function= hashkit_one_at_a_time;
-    break;
-
-  case HASHKIT_HASH_MAX:
-    self->function= hashkit_one_at_a_time;
-    return HASHKIT_INVALID_HASH;
-  }
-
-  self->context= NULL;
-
-  return HASHKIT_SUCCESS;
-}
-
-hashkit_return_t hashkit_set_function(hashkit_st *self, hashkit_hash_algorithm_t hash_algorithm)
-{
-  return _set_function(&self->base_hash, hash_algorithm);
-}
-
-hashkit_return_t hashkit_set_distribution_function(hashkit_st *self, hashkit_hash_algorithm_t hash_algorithm)
-{
-  return _set_function(&self->distribution_hash, hash_algorithm);
-}
-
-static hashkit_return_t _set_custom_function(struct hashkit_st::hashkit_function_st *self, hashkit_hash_fn function, void *context)
-{
-  if (self == NULL)
-  {
-    return HASHKIT_INVALID_ARGUMENT;
-  }
-
-  if (function)
-  {
-    self->function= function;
-    self->context= context;
-
-    return HASHKIT_SUCCESS;
-  }
-
-  return HASHKIT_FAILURE;
-}
-
-hashkit_return_t hashkit_set_custom_function(hashkit_st *self, hashkit_hash_fn function, void *context)
-{
-  if (self == NULL)
-  {
-    return HASHKIT_INVALID_ARGUMENT;
-  }
-
-
-  return _set_custom_function(&self->base_hash, function, context);
-}
-
-hashkit_return_t hashkit_set_custom_distribution_function(hashkit_st *self, hashkit_hash_fn function, void *context)
-{
-  if (self == NULL)
-  {
-    return HASHKIT_INVALID_ARGUMENT;
-  }
-
-  return _set_custom_function(&self->distribution_hash, function, context);
-}
-
-static hashkit_hash_algorithm_t get_function_type(const hashkit_hash_fn function)
-{
-  if (function == hashkit_one_at_a_time)
-  {
-    return HASHKIT_HASH_DEFAULT;
-  }
-  else if (function == hashkit_md5)
-  {
-    return HASHKIT_HASH_MD5;
-  }
-  else if (function == hashkit_crc32)
-  {
-    return HASHKIT_HASH_CRC;
-  }
-  else if (function == hashkit_fnv1_64)
-  {
-    return HASHKIT_HASH_FNV1_64;
-  }
-  else if (function == hashkit_fnv1a_64)
-  {
-    return HASHKIT_HASH_FNV1A_64;
-  }
-  else if (function == hashkit_fnv1_32)
-  {
-    return HASHKIT_HASH_FNV1_32;
-  }
-  else if (function == hashkit_fnv1a_32)
-  {
-    return HASHKIT_HASH_FNV1A_32;
-  }
-  else if (function == hashkit_hsieh)
-  {
-    return HASHKIT_HASH_HSIEH;
-  }
-  else if (function == hashkit_murmur)
-  {
-    return HASHKIT_HASH_MURMUR;
-  }
-  else if (function == hashkit_murmur3)
-  {
-    return HASHKIT_HASH_MURMUR3;
-  }
-  else if (function == hashkit_jenkins)
-  {
-    return HASHKIT_HASH_JENKINS;
-  }
-
-  return HASHKIT_HASH_CUSTOM;
-}
-
-hashkit_hash_algorithm_t hashkit_get_function(const hashkit_st *self)
-{
-  if (self == NULL)
-  {
-    return HASHKIT_HASH_DEFAULT;
-  }
-
-  return get_function_type(self->base_hash.function);
-}
-
-hashkit_hash_algorithm_t hashkit_get_distribution_function(const hashkit_st *self)
-{
-  if (self == NULL)
-  {
-    return HASHKIT_HASH_DEFAULT;
-  }
-
-  return get_function_type(self->distribution_hash.function);
-}
diff --git a/libhashkit/has.cc b/libhashkit/has.cc
deleted file mode 100644 (file)
index 843e32e..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libhashkit/common.h>
-
-bool libhashkit_has_algorithm(const hashkit_hash_algorithm_t algo)
-{
-  switch (algo)
-  {
-  case HASHKIT_HASH_FNV1_64:
-  case HASHKIT_HASH_FNV1A_64:
-#if __WORDSIZE == 64 && defined(HAVE_FNV64_HASH)
-    return true;
-#else
-    return false;
-#endif
-
-  case HASHKIT_HASH_HSIEH:
-#ifdef HAVE_HSIEH_HASH
-    return true;
-#else
-    return false;
-#endif
-
-  case HASHKIT_HASH_MURMUR3:
-  case HASHKIT_HASH_MURMUR:
-#ifdef HAVE_MURMUR_HASH
-    return true;
-#else
-    return false;
-#endif
-
-  case HASHKIT_HASH_FNV1_32:
-  case HASHKIT_HASH_FNV1A_32:
-  case HASHKIT_HASH_DEFAULT:
-  case HASHKIT_HASH_MD5:
-  case HASHKIT_HASH_CRC:
-  case HASHKIT_HASH_JENKINS:
-  case HASHKIT_HASH_CUSTOM:
-    return true;
-
-  case HASHKIT_HASH_MAX:
-    break;
-  }
-
-  return false;
-}
diff --git a/libhashkit/hashkit.cc b/libhashkit/hashkit.cc
deleted file mode 100644 (file)
index e2528b9..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libhashkit/common.h>
-
-static inline void _hashkit_init(hashkit_st *self)
-{
-  self->base_hash.function= hashkit_one_at_a_time;
-  self->base_hash.context= NULL;
-
-  self->distribution_hash.function= hashkit_one_at_a_time;
-  self->distribution_hash.context= NULL;
-
-  self->flags.is_base_same_distributed= true;
-  self->_key= NULL;
-}
-
-static inline hashkit_st *_hashkit_create(hashkit_st *self)
-{
-  if (self)
-  {
-    self->options.is_allocated= false;
-  }
-  else
-  {
-    self= (hashkit_st*)calloc(1, sizeof(hashkit_st));
-    if (self == NULL)
-    {
-      return NULL;
-    }
-
-    self->options.is_allocated= true;
-  }
-
-  return self;
-}
-
-hashkit_st *hashkit_create(hashkit_st *self)
-{
-  self= _hashkit_create(self);
-  if (self == NULL)
-  {
-    return NULL;
-  }
-
-  _hashkit_init(self);
-
-  return self;
-}
-
-
-void hashkit_free(hashkit_st *self)
-{
-  if (self and self->_key)
-  {
-    free(self->_key);
-    self->_key= NULL;
-  }
-
-  if (hashkit_is_allocated(self))
-  {
-    free(self);
-  }
-}
-
-hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *source)
-{
-  if (source == NULL)
-  {
-    return hashkit_create(destination);
-  }
-
-  /* new_clone will be a pointer to destination */ 
-  destination= _hashkit_create(destination);
-
-  // Should only happen on allocation failure.
-  if (destination == NULL)
-  {
-    return NULL;
-  }
-
-  destination->base_hash= source->base_hash;
-  destination->distribution_hash= source->distribution_hash;
-  destination->flags= source->flags;
-  destination->_key= aes_clone_key(static_cast<aes_key_t*>(source->_key));
-
-  return destination;
-}
-
-bool hashkit_compare(const hashkit_st *first, const hashkit_st *second)
-{
-  if (not first or not second)
-    return false;
-
-  if (first->base_hash.function == second->base_hash.function and
-      first->base_hash.context == second->base_hash.context and
-      first->distribution_hash.function == second->distribution_hash.function and
-      first->distribution_hash.context == second->distribution_hash.context and
-      first->flags.is_base_same_distributed == second->flags.is_base_same_distributed)
-  {
-    return true;
-  }
-
-  return false;
-}
diff --git a/libhashkit/hashkit.h b/libhashkit/hashkit.h
deleted file mode 100644 (file)
index 692d591..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#include <libhashkit-1.0/hashkit.h>
diff --git a/libhashkit/hashkitcon.h.in b/libhashkit/hashkitcon.h.in
deleted file mode 100644 (file)
index 9834962..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  HashKit library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#include "@AUTOHEADER_FILE@"
diff --git a/libhashkit/hsieh.cc b/libhashkit/hsieh.cc
deleted file mode 100644 (file)
index ca88f8d..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* By Paul Hsieh (C) 2004, 2005.  Covered under the Paul Hsieh
- * derivative license.
- * See: http://www.azillionmonkeys.com/qed/weblicense.html for license
- * details.
- * http://www.azillionmonkeys.com/qed/hash.html
-*/
-
-#include <libhashkit/common.h>
-
-#undef get16bits
-#if (defined(__GNUC__) && defined(__i386__))
-#define get16bits(d) (*((const uint16_t *) (d)))
-#endif
-
-#if !defined (get16bits)
-#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
-                      +(uint32_t)(((const uint8_t *)(d))[0]) )
-#endif
-
-#ifdef HAVE_HSIEH_HASH
-uint32_t hashkit_hsieh(const char *key, size_t key_length, void *)
-{
-  uint32_t hash = 0, tmp;
-  int rem;
-
-  if (key_length <= 0 || key == NULL)
-    return 0;
-
-  rem = key_length & 3;
-  key_length >>= 2;
-
-  /* Main loop */
-  for (;key_length > 0; key_length--)
-  {
-    hash  += get16bits (key);
-    tmp    = (get16bits (key+2) << 11) ^ hash;
-    hash   = (hash << 16) ^ tmp;
-    key  += 2*sizeof (uint16_t);
-    hash  += hash >> 11;
-  }
-
-  /* Handle end cases */
-  switch (rem)
-  {
-  case 3: hash += get16bits (key);
-          hash ^= hash << 16;
-          hash ^= (uint32_t)key[sizeof (uint16_t)] << 18;
-          hash += hash >> 11;
-          break;
-  case 2: hash += get16bits (key);
-          hash ^= hash << 11;
-          hash += hash >> 17;
-          break;
-  case 1: hash += (unsigned char)(*key);
-          hash ^= hash << 10;
-          hash += hash >> 1;
-  default:
-          break;
-  }
-
-  /* Force "avalanching" of final 127 bits */
-  hash ^= hash << 3;
-  hash += hash >> 5;
-  hash ^= hash << 4;
-  hash += hash >> 17;
-  hash ^= hash << 25;
-  hash += hash >> 6;
-
-  return hash;
-}
-#else
-uint32_t hashkit_hsieh(const char *, size_t , void *)
-{
-  return 0;
-}
-#endif
diff --git a/libhashkit/is.h b/libhashkit/is.h
deleted file mode 100644 (file)
index e8e5772..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-
-#pragma once
-
-#define hashkit_is_allocated(__object) ((__object)->options.is_allocated)
-#define hashkit_is_initialized(__object) ((__object)->options.is_initialized)
-
diff --git a/libhashkit/jenkins.cc b/libhashkit/jenkins.cc
deleted file mode 100644 (file)
index 3c6558a..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
-*
-* By Bob Jenkins, 2006.  bob_jenkins@burtleburtle.net.  You may use this
-* code any way you wish, private, educational, or commercial.  It's free.
-* Use for hash table lookup, or anything where one collision in 2^^32 is
-* acceptable.  Do NOT use for cryptographic purposes.
-* http://burtleburtle.net/bob/hash/index.html
-*
-* Modified by Brian Pontz for libmemcached
-* TODO:
-* Add big endian support
-*/
-
-#include <libhashkit/common.h>
-
-#define hashsize(n) ((uint32_t)1<<(n))
-#define hashmask(n) (hashsize(n)-1)
-#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
-
-#define mix(a,b,c) \
-{ \
-  a -= c;  a ^= rot(c, 4);  c += b; \
-  b -= a;  b ^= rot(a, 6);  a += c; \
-  c -= b;  c ^= rot(b, 8);  b += a; \
-  a -= c;  a ^= rot(c,16);  c += b; \
-  b -= a;  b ^= rot(a,19);  a += c; \
-  c -= b;  c ^= rot(b, 4);  b += a; \
-}
-
-#define final(a,b,c) \
-{ \
-  c ^= b; c -= rot(b,14); \
-  a ^= c; a -= rot(c,11); \
-  b ^= a; b -= rot(a,25); \
-  c ^= b; c -= rot(b,16); \
-  a ^= c; a -= rot(c,4);  \
-  b ^= a; b -= rot(a,14); \
-  c ^= b; c -= rot(b,24); \
-}
-
-#define JENKINS_INITVAL 13
-
-/*
-jenkins_hash() -- hash a variable-length key into a 32-bit value
-  k       : the key (the unaligned variable-length array of bytes)
-  length  : the length of the key, counting by bytes
-  initval : can be any 4-byte value
-Returns a 32-bit value.  Every bit of the key affects every bit of
-the return value.  Two keys differing by one or two bits will have
-totally different hash values.
-
-The best hash table sizes are powers of 2.  There is no need to do
-mod a prime (mod is sooo slow!).  If you need less than 32 bits,
-use a bitmask.  For example, if you need only 10 bits, do
-  h = (h & hashmask(10));
-In which case, the hash table should have hashsize(10) elements.
-*/
-
-uint32_t hashkit_jenkins(const char *key, size_t length, void *)
-{
-  uint32_t a,b,c;                                          /* internal state */
-#ifndef WORDS_BIGENDIAN
-  union { const void *ptr; size_t i; } u;
-  u.ptr = key;
-#endif
-
-  /* Set up the internal state */
-  a = b = c = 0xdeadbeef + ((uint32_t)length) + JENKINS_INITVAL;
-
-#ifndef WORDS_BIGENDIAN
-  if ((u.i & 0x3) == 0)
-  {
-    const uint32_t *k = (const uint32_t *)key;         /* read 32-bit chunks */
-
-    /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
-    while (length > 12)
-    {
-      a += k[0];
-      b += k[1];
-      c += k[2];
-      mix(a,b,c);
-      length -= 12;
-      k += 3;
-    }
-
-    /*----------------------------- handle the last (probably partial) block */
-    /*
-     * "k[2]&0xffffff" actually reads beyond the end of the string, but
-     * then masks off the part it's not allowed to read.  Because the
-     * string is aligned, the masked-off tail is in the same word as the
-     * rest of the string.  Every machine with memory protection I've seen
-     * does it on word boundaries, so is OK with this.  But VALGRIND will
-     * still catch it and complain.  The masking trick does make the hash
-     * noticably faster for short strings (like English words).
-     */
-    switch(length)
-    {
-    case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
-    case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
-    case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
-    case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
-    case 8 : b+=k[1]; a+=k[0]; break;
-    case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
-    case 6 : b+=k[1]&0xffff; a+=k[0]; break;
-    case 5 : b+=k[1]&0xff; a+=k[0]; break;
-    case 4 : a+=k[0]; break;
-    case 3 : a+=k[0]&0xffffff; break;
-    case 2 : a+=k[0]&0xffff; break;
-    case 1 : a+=k[0]&0xff; break;
-    case 0 : return c;              /* zero length strings require no mixing */
-    default: return c;
-    }
-
-  }
-  else if ((u.i & 0x1) == 0)
-  {
-    const uint16_t *k = (const uint16_t *)key;         /* read 16-bit chunks */
-    const uint8_t  *k8;
-
-    /*--------------- all but last block: aligned reads and different mixing */
-    while (length > 12)
-    {
-      a += k[0] + (((uint32_t)k[1])<<16);
-      b += k[2] + (((uint32_t)k[3])<<16);
-      c += k[4] + (((uint32_t)k[5])<<16);
-      mix(a,b,c);
-      length -= 12;
-      k += 6;
-    }
-
-    /*----------------------------- handle the last (probably partial) block */
-    k8 = (const uint8_t *)k;
-    switch(length)
-    {
-    case 12: c+=k[4]+(((uint32_t)k[5])<<16);
-             b+=k[2]+(((uint32_t)k[3])<<16);
-             a+=k[0]+(((uint32_t)k[1])<<16);
-             break;
-    case 11: c+=((uint32_t)k8[10])<<16;
-             /* fall through */
-    case 10: c+=k[4];
-             b+=k[2]+(((uint32_t)k[3])<<16);
-             a+=k[0]+(((uint32_t)k[1])<<16);
-             break;
-    case 9 : c+=k8[8];
-             /* fall through */
-    case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
-             a+=k[0]+(((uint32_t)k[1])<<16);
-             break;
-    case 7 : b+=((uint32_t)k8[6])<<16;
-             /* fall through */
-    case 6 : b+=k[2];
-             a+=k[0]+(((uint32_t)k[1])<<16);
-             break;
-    case 5 : b+=k8[4];
-             /* fall through */
-    case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
-             break;
-    case 3 : a+=((uint32_t)k8[2])<<16;
-             /* fall through */
-    case 2 : a+=k[0];
-             break;
-    case 1 : a+=k8[0];
-             break;
-    case 0 : return c;                     /* zero length requires no mixing */
-    default: return c;
-    }
-
-  }
-  else
-  {                        /* need to read the key one byte at a time */
-#endif /* little endian */
-    const uint8_t *k = (const uint8_t *)key;
-
-    /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
-    while (length > 12)
-    {
-      a += k[0];
-      a += ((uint32_t)k[1])<<8;
-      a += ((uint32_t)k[2])<<16;
-      a += ((uint32_t)k[3])<<24;
-      b += k[4];
-      b += ((uint32_t)k[5])<<8;
-      b += ((uint32_t)k[6])<<16;
-      b += ((uint32_t)k[7])<<24;
-      c += k[8];
-      c += ((uint32_t)k[9])<<8;
-      c += ((uint32_t)k[10])<<16;
-      c += ((uint32_t)k[11])<<24;
-      mix(a,b,c);
-      length -= 12;
-      k += 12;
-    }
-
-    /*-------------------------------- last block: affect all 32 bits of (c) */
-    switch(length)                   /* all the case statements fall through */
-    {
-    case 12: c+=((uint32_t)k[11])<<24;
-             /* fall through */
-    case 11: c+=((uint32_t)k[10])<<16;
-             /* fall through */
-    case 10: c+=((uint32_t)k[9])<<8;
-             /* fall through */
-    case 9 : c+=k[8];
-             /* fall through */
-    case 8 : b+=((uint32_t)k[7])<<24;
-             /* fall through */
-    case 7 : b+=((uint32_t)k[6])<<16;
-             /* fall through */
-    case 6 : b+=((uint32_t)k[5])<<8;
-             /* fall through */
-    case 5 : b+=k[4];
-             /* fall through */
-    case 4 : a+=((uint32_t)k[3])<<24;
-             /* fall through */
-    case 3 : a+=((uint32_t)k[2])<<16;
-             /* fall through */
-    case 2 : a+=((uint32_t)k[1])<<8;
-             /* fall through */
-    case 1 : a+=k[0];
-             break;
-    case 0 : return c;
-    default : return c;
-    }
-#ifndef WORDS_BIGENDIAN
-  }
-#endif
-
-  final(a,b,c);
-  return c;
-}
diff --git a/libhashkit/ketama.cc b/libhashkit/ketama.cc
deleted file mode 100644 (file)
index eaa8442..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libhashkit/common.h>
-#include <math.h>
-
-#if 0
-static uint32_t ketama_server_hash(const char *key, unsigned int key_length, int alignment)
-{
-  unsigned char results[16];
-
-  md5_signature((unsigned char*)key, key_length, results);
-  return ((uint32_t) (results[3 + alignment * 4] & 0xFF) << 24)
-    | ((uint32_t) (results[2 + alignment * 4] & 0xFF) << 16)
-    | ((uint32_t) (results[1 + alignment * 4] & 0xFF) << 8)
-    | (results[0 + alignment * 4] & 0xFF);
-}
-
-static int continuum_points_cmp(const void *t1, const void *t2)
-{
-  hashkit_continuum_point_st *ct1= (hashkit_continuum_point_st *)t1;
-  hashkit_continuum_point_st *ct2= (hashkit_continuum_point_st *)t2;
-
-  if (ct1->value == ct2->value)
-    return 0;
-  else if (ct1->value > ct2->value)
-    return 1;
-  else
-    return -1;
-}
-
-int update_continuum(hashkit_st *hashkit)
-{
-  uint32_t count;
-  uint32_t continuum_index= 0;
-  uint32_t value;
-  uint32_t points_index;
-  uint32_t points_count= 0;
-  uint32_t points_per_server;
-  uint32_t points_per_hash;
-  uint64_t total_weight= 0;
-  uint32_t live_servers;
-  uint8_t *context;
-
-  if (hashkit->active_fn != NULL || hashkit->weight_fn != NULL)
-  {
-    live_servers= 0;
-
-    for (count= 0, context= hashkit->list; count < hashkit->list_size;
-         count++, context+= hashkit->context_size)
-    {
-      if (hashkit->active_fn != NULL)
-      {
-        if (hashkit->active_fn(context))
-          live_servers++;
-        else
-          continue;
-      }
-
-      if (hashkit->weight_fn != NULL)
-        total_weight+= hashkit->weight_fn(context);
-    }
-  }
-
-  if (hashkit->active_fn == NULL)
-    live_servers= (uint32_t)hashkit->list_size;
-
-  if (live_servers == 0)
-    return 0;
-
-  if (hashkit->weight_fn == NULL)
-  {
-    points_per_server= HASHKIT_POINTS_PER_NODE;
-    points_per_hash= 1;
-  }
-  else
-  {
-    points_per_server= HASHKIT_POINTS_PER_NODE_WEIGHTED;
-    points_per_hash= 4;
-  }
-
-  if (live_servers > hashkit->continuum_count)
-  {
-    hashkit_continuum_point_st *new_continuum;
-
-    new_continuum= realloc(hashkit->continuum,
-                           sizeof(hashkit_continuum_point_st) *
-                           (live_servers + HASHKIT_CONTINUUM_ADDITION) *
-                           points_per_server);
-
-    if (new_continuum == NULL)
-      return ENOMEM;
-
-    hashkit->continuum= new_continuum;
-    hashkit->continuum_count= live_servers + HASHKIT_CONTINUUM_ADDITION;
-  }
-
-  for (count= 0, context= hashkit->list; count < hashkit->list_size;
-       count++, context+= hashkit->context_size)
-  {
-    if (hashkit->active_fn != NULL && hashkit->active_fn(context) == false)
-      continue;
-
-    if (hashkit->weight_fn != NULL)
-    {
-        float pct = (float)hashkit->weight_fn(context) / (float)total_weight;
-        points_per_server= (uint32_t) ((floorf((float) (pct * HASHKIT_POINTS_PER_NODE_WEIGHTED / 4 * (float)live_servers + 0.0000000001))) * 4);
-    }
-
-    for (points_index= 0;
-         points_index < points_per_server / points_per_hash;
-         points_index++)
-    {
-      char sort_host[HASHKIT_CONTINUUM_KEY_SIZE]= "";
-      size_t sort_host_length;
-
-      if (hashkit->continuum_key_fn == NULL)
-      {
-        sort_host_length= (size_t) snprintf(sort_host, HASHKIT_CONTINUUM_KEY_SIZE, "%u",
-                                            points_index);
-      }
-      else
-      {
-        sort_host_length= hashkit->continuum_key_fn(sort_host, HASHKIT_CONTINUUM_KEY_SIZE,
-                                                 points_index, context);
-      }
-
-      if (hashkit->weight_fn == NULL)
-      {
-        if (hashkit->continuum_hash_fn == NULL)
-          value= hashkit_default(sort_host, sort_host_length);
-        else
-          value= hashkit->continuum_hash_fn(sort_host, sort_host_length);
-
-        hashkit->continuum[continuum_index].index= count;
-        hashkit->continuum[continuum_index++].value= value;
-      }
-      else
-      {
-        unsigned int i;
-        for (i = 0; i < points_per_hash; i++)
-        {
-           value= ketama_server_hash(sort_host, (uint32_t) sort_host_length, (int) i);
-           hashkit->continuum[continuum_index].index= count;
-           hashkit->continuum[continuum_index++].value= value;
-        }
-      }
-    }
-
-    points_count+= points_per_server;
-  }
-
-  hashkit->continuum_points_count= points_count;
-  qsort(hashkit->continuum, hashkit->continuum_points_count, sizeof(hashkit_continuum_point_st),
-        continuum_points_cmp);
-
-  return 0;
-}
-#endif
diff --git a/libhashkit/md5.cc b/libhashkit/md5.cc
deleted file mode 100644 (file)
index ef86776..0000000
+++ /dev/null
@@ -1,412 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
-  This Library has been modified from its original form by
-  Brian Aker (brian@tangent.org)
-
-  See below for original Copyright.
-*/
-/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
- */
-
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
-
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
-*/
-
-#include <libhashkit/common.h>
-
-#include <string.h>
-#include <sys/types.h>
-
-#define GCC_VERSION (__GNUC__ * 10000 \
-                     + __GNUC_MINOR__ * 100 \
-                     + __GNUC_PATCHLEVEL__)
-
-#if GCC_VERSION > 40600
-# pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"
-#endif
-
-/* POINTER defines a generic pointer type */
-typedef unsigned char *POINTER;
-typedef const unsigned char *CONST_POINTER;
-
-
-/* UINT4 defines a four byte word */
-typedef unsigned int UINT4;
-
-
-/* MD5 context. */
-typedef struct {
-  UINT4 state[4];                                   /* state (ABCD) */
-  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
-  unsigned char buffer[64];                         /* input buffer */
-} MD5_CTX;
-
-static void MD5Init (MD5_CTX *context);      /* context */
-static void MD5Update ( MD5_CTX *context,                                        /* context */
-                        const unsigned char *input,                              /* input block */
-                        unsigned int inputLen);                     /* length of input block */
-static void MD5Final ( unsigned char digest[16],                         /* message digest */
-                       MD5_CTX *context);                              /* context */
-
-/* Constants for MD5Transform routine. */
-
-#define S11 7
-#define S12 12
-#define S13 17
-#define S14 22
-#define S21 5
-#define S22 9
-#define S23 14
-#define S24 20
-#define S31 4
-#define S32 11
-#define S33 16
-#define S34 23
-#define S41 6
-#define S42 10
-#define S43 15
-#define S44 21
-
-
-static void MD5Transform (UINT4 state[4],
-                          const unsigned char block[64]);
-static void Encode (unsigned char *output,
-                    UINT4 *input,
-                    unsigned int len);
-static void Decode(UINT4 *output, const unsigned char *input, unsigned int len);
-
-static unsigned char PADDING[64] = {
-  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* F, G, H and I are basic MD5 functions.
- */
-#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
-#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | (~z)))
-
-/* ROTATE_LEFT rotates x left n bits.
- */
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
-
-/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
-Rotation is separate from addition to prevent recomputation.
- */
-#define FF(a, b, c, d, x, s, ac) { \
- (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-#define GG(a, b, c, d, x, s, ac) { \
- (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-#define HH(a, b, c, d, x, s, ac) { \
- (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-#define II(a, b, c, d, x, s, ac) { \
- (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
-  }
-
-
-/*
-  Just a simple method for getting the signature
-  result must be == 16
-*/
-void md5_signature(const unsigned char *key, unsigned int length, unsigned char *result)
-{
-    MD5_CTX my_md5;
-
-    MD5Init(&my_md5);
-    (void)MD5Update(&my_md5, key, length);
-    MD5Final(result, &my_md5);
-}
-
-/* MD5 initialization. Begins an MD5 operation, writing a new context.
- */
-static void MD5Init (MD5_CTX *context)      /* context */
-{
-  context->count[0] = context->count[1] = 0;
-  /* Load magic initialization constants.
-*/
-  context->state[0] = 0x67452301;
-  context->state[1] = 0xefcdab89;
-  context->state[2] = 0x98badcfe;
-  context->state[3] = 0x10325476;
-}
-
-/* MD5 block update operation. Continues an MD5 message-digest
-  operation, processing another message block, and updating the
-  context.
- */
-
-static void MD5Update (
-                       MD5_CTX *context,                                        /* context */
-                       const unsigned char *input,                              /* input block */
-                       unsigned int inputLen)                     /* length of input block */
-{
-  unsigned int i, idx, partLen;
-
-  /* Compute number of bytes mod 64 */
-  idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
-
-
-  /* Update number of bits */
-  if ((context->count[0] += ((UINT4)inputLen << 3))
-      < ((UINT4)inputLen << 3))
-    context->count[1]++;
-  context->count[1] += ((UINT4)inputLen >> 29);
-
-  partLen = 64 - idx;
-
-  /* Transform as many times as possible.
-*/
-  if (inputLen >= partLen) {
-    memcpy((POINTER)&context->buffer[idx], (CONST_POINTER)input, partLen);
-    MD5Transform(context->state, context->buffer);
-
-    for (i = partLen; i + 63 < inputLen; i += 64)
-      MD5Transform (context->state, (CONST_POINTER)&input[i]);
-
-    idx = 0;
-  }
-  else
-    i = 0;
-
-  /* Buffer remaining input */
-  memcpy((POINTER)&context->buffer[idx], (CONST_POINTER)&input[i],
-         inputLen-i);
-}
-
-/* MD5 finalization. Ends an MD5 message-digest operation, writing the
-  the message digest and zeroizing the context.
- */
-
-static void MD5Final (
-                      unsigned char digest[16],                         /* message digest */
-                      MD5_CTX *context)                              /* context */
-{
-  unsigned char bits[8];
-  unsigned int idx, padLen;
-
-  /* Save number of bits */
-  Encode (bits, context->count, 8);
-
-  /* Pad out to 56 mod 64.
-*/
-  idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
-  padLen = (idx < 56) ? (56 - idx) : (120 - idx);
-  MD5Update (context, PADDING, padLen);
-
-  /* Append length (before padding) */
-  MD5Update (context, bits, 8);
-
-  /* Store state in digest */
-  Encode (digest, context->state, 16);
-
-  /* Zeroize sensitive information.
-*/
-  memset((POINTER)context, 0, sizeof (*context));
-}
-
-/* MD5 basic transformation. Transforms state based on block.
- */
-static void MD5Transform (
-                          UINT4 state[4],
-                          const unsigned char block[64])
-{
-  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
-
-  Decode (x, block, 64);
-
-  /* Round 1 */
-  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
-  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
-  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
-  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
-  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
-  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
-  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
-  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
-  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
-  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
-  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
-  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
-  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
-  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
-  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
-  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
-
- /* Round 2 */
-  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
-  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
-  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
-  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
-  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
-  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
-  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
-  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
-  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
-  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
-  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
-  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
-  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
-  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
-  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
-  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
-
-  /* Round 3 */
-  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
-  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
-  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
-  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
-  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
-  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
-  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
-  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
-  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
-  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
-  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
-  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
-  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
-  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
-  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
-  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
-
-  /* Round 4 */
-  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
-  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
-  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
-  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
-  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
-  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
-  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
-  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
-  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
-  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
-  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
-  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
-  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
-  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
-  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
-  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
-
-
-  state[0] += a;
-  state[1] += b;
-  state[2] += c;
-  state[3] += d;
-
-  /* Zeroize sensitive information.
-*/
-  memset((POINTER)x, 0, sizeof (x));
-}
-
-/* Encodes input (UINT4) into output (unsigned char). Assumes len is
-  a multiple of 4.
- */
-static void Encode (
-unsigned char *output,
-UINT4 *input,
-unsigned int len)
-{
-  unsigned int i, j;
-
-  for (i = 0, j = 0; j < len; i++, j += 4) {
- output[j] = (unsigned char)(input[i] & 0xff);
- output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
- output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
- output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
-  }
-}
-
-
-/* Decodes input (unsigned char) into output (UINT4). Assumes len is
-  a multiple of 4.
- */
-static void Decode (
-                    UINT4 *output,
-                    const unsigned char *input,
-                    unsigned int len)
-{
-  unsigned int i, j;
-
-  for (i = 0, j = 0; j < len; i++, j += 4)
-    output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
-      (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
-}
-
-uint32_t hashkit_md5(const char *key, size_t key_length, void *context)
-{
-  unsigned char results[16];
-  (void)context;
-
-  md5_signature((unsigned char*)key, (unsigned int)key_length, results);
-
-  return ((uint32_t) (results[3] & 0xFF) << 24)
-    | ((uint32_t) (results[2] & 0xFF) << 16)
-    | ((uint32_t) (results[1] & 0xFF) << 8)
-    | (results[0] & 0xFF);
-}
diff --git a/libhashkit/murmur.cc b/libhashkit/murmur.cc
deleted file mode 100644 (file)
index f3e8fe6..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
-  "Murmur" hash provided by Austin, tanjent@gmail.com
-  http://murmurhash.googlepages.com/
-
-  Note - This code makes a few assumptions about how your machine behaves -
-
-  1. We can read a 4-byte value from any address without crashing
-  2. sizeof(int) == 4
-
-  And it has a few limitations -
-  1. It will not work incrementally.
-  2. It will not produce the same results on little-endian and big-endian
-  machines.
-
-  Updated to murmur2 hash - BP
-*/
-
-#include <libhashkit/common.h>
-
-#ifdef HAVE_MURMUR_HASH
-
-#include <cstring>
-
-uint32_t hashkit_murmur(const char *key, size_t length, void *context)
-{
-  /*
-    'm' and 'r' are mixing constants generated offline.  They're not
-    really 'magic', they just happen to work well.
-  */
-
-  const unsigned int m= 0x5bd1e995;
-  const uint32_t seed= (0xdeadbeef * (uint32_t)length);
-  const int r= 24;
-
-
-  // Initialize the hash to a 'random' value
-
-  uint32_t h= seed ^ (uint32_t)length;
-
-  // Mix 4 bytes at a time into the hash
-
-  const unsigned char * data= (const unsigned char *)key;
-  (void)context;
-
-  while(length >= 4)
-  {
-    unsigned int k;
-    memcpy(&k, data, sizeof(unsigned int));
-
-    k *= m;
-    k ^= k >> r;
-    k *= m;
-
-    h *= m;
-    h ^= k;
-
-    data += 4;
-    length -= 4;
-  }
-
-  // Handle the last few bytes of the input array
-
-  switch(length)
-  {
-  case 3: h ^= ((uint32_t)data[2]) << 16;   /* fall through */
-  case 2: h ^= ((uint32_t)data[1]) << 8;    /* fall through */
-  case 1: h ^= data[0];
-          h *= m;
-  default: break;
-  };
-
-  /*
-    Do a few final mixes of the hash to ensure the last few bytes are
-    well-incorporated.
-  */
-
-  h ^= h >> 13;
-  h *= m;
-  h ^= h >> 15;
-
-  return h;
-}
-
-#else
-uint32_t hashkit_murmur(const char *, size_t , void *)
-{
-  return 0;
-}
-#endif
diff --git a/libhashkit/murmur3.cc b/libhashkit/murmur3.cc
deleted file mode 100644 (file)
index 254b509..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-//-----------------------------------------------------------------------------
-//MurmurHash3 was written by Austin Appleby, and is placed in the public
-//domain. The author hereby disclaims copyright to this source code.
-
-// Note - The x86 and x64 versions do _not_ produce the same results, as the
-// algorithms are optimized for their respective platforms. You can still
-// compile and run any of them on any platform, but your performance with the
-// non-native version will be less than optimal.
-
-#include "libhashkit/hashkitcon.h"
-
-#include "libhashkit/murmur3.h"
-
-//-----------------------------------------------------------------------------
-// Platform-specific functions and macros
-
-#ifdef __GNUC__
-#define FORCE_INLINE __attribute__((always_inline)) inline
-#else
-#define FORCE_INLINE inline
-#endif
-
-static FORCE_INLINE uint32_t rotl32 ( uint32_t x, int8_t r )
-{
-  return (x << r) | (x >> (32 - r));
-}
-
-static FORCE_INLINE uint64_t rotl64 ( uint64_t x, int8_t r )
-{
-  return (x << r) | (x >> (64 - r));
-}
-
-#define        ROTL32(x,y)     rotl32(x,y)
-#define ROTL64(x,y)    rotl64(x,y)
-
-#define BIG_CONSTANT(x) (x##LLU)
-
-//-----------------------------------------------------------------------------
-// Block read - if your platform needs to do endian-swapping or can only
-// handle aligned reads, do the conversion here
-
-#include <cstring>
-template <typename T>
-static inline T getblock(const T *blocks, int i) {
-  T b;
-  memcpy(&b, ((const uint8_t *) blocks) + i * sizeof(T), sizeof(T));
-  return b;
-}
-
-//-----------------------------------------------------------------------------
-// Finalization mix - force all bits of a hash block to avalanche
-
-static FORCE_INLINE uint32_t fmix32 ( uint32_t h )
-{
-  h ^= h >> 16;
-  h *= 0x85ebca6b;
-  h ^= h >> 13;
-  h *= 0xc2b2ae35;
-  h ^= h >> 16;
-
-  return h;
-}
-
-//----------
-
-static FORCE_INLINE uint64_t fmix64 ( uint64_t k )
-{
-  k ^= k >> 33;
-  k *= BIG_CONSTANT(0xff51afd7ed558ccd);
-  k ^= k >> 33;
-  k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
-  k ^= k >> 33;
-
-  return k;
-}
-
-//-----------------------------------------------------------------------------
-
-void MurmurHash3_x86_32 ( const void * key, int len,
-                          uint32_t seed, void * out )
-{
-  const uint8_t * data = (const uint8_t*)key;
-  const int nblocks = len / 4;
-  int i;
-
-  uint32_t h1 = seed;
-
-  uint32_t c1 = 0xcc9e2d51;
-  uint32_t c2 = 0x1b873593;
-
-  //----------
-  // body
-
-  const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
-
-  for(i = -nblocks; i; i++)
-  {
-    uint32_t k1 = getblock(blocks,i);
-
-    k1 *= c1;
-    k1 = ROTL32(k1,15);
-    k1 *= c2;
-    
-    h1 ^= k1;
-    h1 = ROTL32(h1,13); 
-    h1 = h1*5+0xe6546b64;
-  }
-
-  //----------
-  // tail
-
-  const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
-
-  uint32_t k1 = 0;
-
-  switch(len & 3)
-  {
-  case 3: k1 ^= tail[2] << 16;
-          /* fall through */
-  case 2: k1 ^= tail[1] << 8;
-          /* fall through */
-  case 1: k1 ^= tail[0];
-          k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
-  };
-
-  //----------
-  // finalization
-
-  h1 ^= len;
-
-  h1 = fmix32(h1);
-
-  *(uint32_t*)out = h1;
-} 
-
-//-----------------------------------------------------------------------------
-
-void MurmurHash3_x86_128 ( const void * key, const int len,
-                           uint32_t seed, void * out )
-{
-  const uint8_t * data = (const uint8_t*)key;
-  const int nblocks = len / 16;
-  int i;
-
-  uint32_t h1 = seed;
-  uint32_t h2 = seed;
-  uint32_t h3 = seed;
-  uint32_t h4 = seed;
-
-  uint32_t c1 = 0x239b961b; 
-  uint32_t c2 = 0xab0e9789;
-  uint32_t c3 = 0x38b34ae5; 
-  uint32_t c4 = 0xa1e38b93;
-
-  //----------
-  // body
-
-  const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
-
-  for(i = -nblocks; i; i++)
-  {
-    uint32_t k1 = getblock(blocks,i*4+0);
-    uint32_t k2 = getblock(blocks,i*4+1);
-    uint32_t k3 = getblock(blocks,i*4+2);
-    uint32_t k4 = getblock(blocks,i*4+3);
-
-    k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
-
-    h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
-
-    k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
-
-    h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
-
-    k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
-
-    h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
-
-    k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
-
-    h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
-  }
-
-  //----------
-  // tail
-
-  const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
-
-  uint32_t k1 = 0;
-  uint32_t k2 = 0;
-  uint32_t k3 = 0;
-  uint32_t k4 = 0;
-
-  switch(len & 15)
-  {
-  case 15: k4 ^= tail[14] << 16;
-           /* fall through */
-  case 14: k4 ^= tail[13] << 8;
-           /* fall through */
-  case 13: k4 ^= tail[12] << 0;
-           k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
-           /* fall through */
-  case 12: k3 ^= tail[11] << 24;
-           /* fall through */
-  case 11: k3 ^= tail[10] << 16;
-           /* fall through */
-  case 10: k3 ^= tail[ 9] << 8;
-           /* fall through */
-  case  9: k3 ^= tail[ 8] << 0;
-           k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
-           /* fall through */
-  case  8: k2 ^= tail[ 7] << 24;
-           /* fall through */
-  case  7: k2 ^= tail[ 6] << 16;
-           /* fall through */
-  case  6: k2 ^= tail[ 5] << 8;
-           /* fall through */
-  case  5: k2 ^= tail[ 4] << 0;
-           k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
-           /* fall through */
-  case  4: k1 ^= tail[ 3] << 24;
-           /* fall through */
-  case  3: k1 ^= tail[ 2] << 16;
-           /* fall through */
-  case  2: k1 ^= tail[ 1] << 8;
-           /* fall through */
-  case  1: k1 ^= tail[ 0] << 0;
-           k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
-  };
-
-  //----------
-  // finalization
-
-  h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
-
-  h1 += h2; h1 += h3; h1 += h4;
-  h2 += h1; h3 += h1; h4 += h1;
-
-  h1 = fmix32(h1);
-  h2 = fmix32(h2);
-  h3 = fmix32(h3);
-  h4 = fmix32(h4);
-
-  h1 += h2; h1 += h3; h1 += h4;
-  h2 += h1; h3 += h1; h4 += h1;
-
-  ((uint32_t*)out)[0] = h1;
-  ((uint32_t*)out)[1] = h2;
-  ((uint32_t*)out)[2] = h3;
-  ((uint32_t*)out)[3] = h4;
-}
-
-//-----------------------------------------------------------------------------
-
-void MurmurHash3_x64_128 ( const void * key, const int len,
-                           const uint32_t seed, void * out )
-{
-  const uint8_t * data = (const uint8_t*)key;
-  const int nblocks = len / 16;
-  int i;
-
-  uint64_t h1 = seed;
-  uint64_t h2 = seed;
-
-  uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
-  uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
-
-  //----------
-  // body
-
-  const uint64_t * blocks = (const uint64_t *)(data);
-
-  for(i = 0; i < nblocks; i++)
-  {
-    uint64_t k1 = getblock(blocks,i*2+0);
-    uint64_t k2 = getblock(blocks,i*2+1);
-
-    k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
-
-    h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
-
-    k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
-
-    h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
-  }
-
-  //----------
-  // tail
-
-  const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
-
-  uint64_t k1 = 0;
-  uint64_t k2 = 0;
-
-  switch(len & 15)
-  {
-  case 15: k2 ^= (uint64_t)(tail[14]) << 48;
-           /* fall through */
-  case 14: k2 ^= (uint64_t)(tail[13]) << 40;
-           /* fall through */
-  case 13: k2 ^= (uint64_t)(tail[12]) << 32;
-           /* fall through */
-  case 12: k2 ^= (uint64_t)(tail[11]) << 24;
-           /* fall through */
-  case 11: k2 ^= (uint64_t)(tail[10]) << 16;
-           /* fall through */
-  case 10: k2 ^= (uint64_t)(tail[ 9]) << 8;
-           /* fall through */
-  case  9: k2 ^= (uint64_t)(tail[ 8]) << 0;
-           k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
-           /* fall through */
-  case  8: k1 ^= (uint64_t)(tail[ 7]) << 56;
-           /* fall through */
-  case  7: k1 ^= (uint64_t)(tail[ 6]) << 48;
-           /* fall through */
-  case  6: k1 ^= (uint64_t)(tail[ 5]) << 40;
-           /* fall through */
-  case  5: k1 ^= (uint64_t)(tail[ 4]) << 32;
-           /* fall through */
-  case  4: k1 ^= (uint64_t)(tail[ 3]) << 24;
-           /* fall through */
-  case  3: k1 ^= (uint64_t)(tail[ 2]) << 16;
-           /* fall through */
-  case  2: k1 ^= (uint64_t)(tail[ 1]) << 8;
-           /* fall through */
-  case  1: k1 ^= (uint64_t)(tail[ 0]) << 0;
-           k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
-  };
-
-  //----------
-  // finalization
-
-  h1 ^= len; h2 ^= len;
-
-  h1 += h2;
-  h2 += h1;
-
-  h1 = fmix64(h1);
-  h2 = fmix64(h2);
-
-  h1 += h2;
-  h2 += h1;
-
-  ((uint64_t*)out)[0] = h1;
-  ((uint64_t*)out)[1] = h2;
-}
-
-//-----------------------------------------------------------------------------
-
diff --git a/libhashkit/murmur3.h b/libhashkit/murmur3.h
deleted file mode 100644 (file)
index 4eb4fa6..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-//-----------------------------------------------------------------------------
-// MurmurHash3 was written by Austin Appleby, and is placed in the
-// public domain. The author hereby disclaims copyright to this source
-// code.
-
-#pragma once
-
-//-----------------------------------------------------------------------------
-
-void MurmurHash3_x86_32 (const void *key, int len, uint32_t seed, void *out);
-
-void MurmurHash3_x86_128(const void *key, int len, uint32_t seed, void *out);
-
-void MurmurHash3_x64_128(const void *key, int len, uint32_t seed, void *out);
-
-//-----------------------------------------------------------------------------
diff --git a/libhashkit/murmur3_api.cc b/libhashkit/murmur3_api.cc
deleted file mode 100644 (file)
index db35700..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libhashkit/common.h"
-#include "libhashkit/murmur3.h"
-
-uint32_t hashkit_murmur3(const char *key, size_t length, void *)
-{
-  const uint32_t seed= (0xdeadbeef * (uint32_t)length);
-
-  uint32_t ret;
-  MurmurHash3_x86_32(key, int(length), seed, &ret);
-
-  return ret;
-}
diff --git a/libhashkit/nohsieh.cc b/libhashkit/nohsieh.cc
deleted file mode 100644 (file)
index 8def993..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  HashKit library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libhashkit/common.h>
-
-#ifdef HAVE_HSIEH_HASH
-#error "not supported"
-#else
-uint32_t hashkit_hsieh(const char *, size_t , void *)
-{
-  return 0;
-}
-#endif
diff --git a/libhashkit/one_at_a_time.cc b/libhashkit/one_at_a_time.cc
deleted file mode 100644 (file)
index 647f3c1..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-/*
-  This has is Jenkin's "One at A time Hash".
-http://en.wikipedia.org/wiki/Jenkins_hash_function
-*/
-
-#include <libhashkit/common.h>
-
-uint32_t hashkit_one_at_a_time(const char *key, size_t key_length, void *context)
-{
-  const char *ptr= key;
-  uint32_t value= 0;
-  (void)context;
-
-  while (key_length--)
-  {
-    uint32_t val= (uint32_t) *ptr++;
-    value += val;
-    value += (value << 10);
-    value ^= (value >> 6);
-  }
-  value += (value << 3);
-  value ^= (value >> 11);
-  value += (value << 15);
-
-  return value;
-}
diff --git a/libhashkit/rijndael.cc b/libhashkit/rijndael.cc
deleted file mode 100644 (file)
index 93997cc..0000000
+++ /dev/null
@@ -1,1437 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-/**
- * rijndael-alg-fst.c
- *
- * @version 3.0 (December 2000)
- *
- * Optimised ANSI C code for the Rijndael cipher (now AES)
- *
- * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
- * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
- * @author Paulo Barreto <paulo.barreto@terra.com.br>
- *
- * This code is hereby placed in the public domain.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <assert.h>
-#include <stdlib.h>
-
-#include "libhashkit/rijndael.hpp"
-
-/*
-Te0[x] = S [x].[02, 01, 01, 03];
-Te1[x] = S [x].[03, 02, 01, 01];
-Te2[x] = S [x].[01, 03, 02, 01];
-Te3[x] = S [x].[01, 01, 03, 02];
-Te4[x] = S [x].[01, 01, 01, 01];
-
-Td0[x] = Si[x].[0e, 09, 0d, 0b];
-Td1[x] = Si[x].[0b, 0e, 09, 0d];
-Td2[x] = Si[x].[0d, 0b, 0e, 09];
-Td3[x] = Si[x].[09, 0d, 0b, 0e];
-Td4[x] = Si[x].[01, 01, 01, 01];
-*/
-
-static const u32 Te0[256] = {
-    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
-    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
-    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
-    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
-    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
-    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
-    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
-    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
-    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
-    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
-    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
-    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
-    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
-    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
-    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
-    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
-    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
-    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
-    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
-    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
-    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
-    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
-    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
-    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
-    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
-    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
-    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
-    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
-    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
-    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
-    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
-    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
-    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
-    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
-    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
-    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
-    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
-    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
-    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
-    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
-    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
-    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
-    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
-    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
-    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
-    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
-    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
-    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
-    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
-    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
-    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
-    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
-    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
-    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
-    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
-    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
-    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
-    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
-    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
-    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
-    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
-    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
-    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
-    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
-};
-static const u32 Te1[256] = {
-    0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
-    0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
-    0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
-    0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
-    0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
-    0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
-    0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
-    0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
-    0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
-    0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
-    0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
-    0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
-    0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
-    0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
-    0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
-    0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
-    0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
-    0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
-    0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
-    0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
-    0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
-    0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
-    0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
-    0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
-    0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
-    0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
-    0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
-    0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
-    0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
-    0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
-    0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
-    0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
-    0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
-    0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
-    0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
-    0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
-    0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
-    0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
-    0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
-    0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
-    0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
-    0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
-    0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
-    0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
-    0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
-    0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
-    0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
-    0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
-    0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
-    0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
-    0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
-    0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
-    0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
-    0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
-    0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
-    0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
-    0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
-    0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
-    0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
-    0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
-    0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
-    0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
-    0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
-    0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
-};
-static const u32 Te2[256] = {
-    0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
-    0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
-    0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
-    0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
-    0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
-    0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
-    0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
-    0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
-    0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
-    0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
-    0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
-    0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
-    0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
-    0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
-    0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
-    0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
-    0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
-    0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
-    0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
-    0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
-    0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
-    0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
-    0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
-    0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
-    0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
-    0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
-    0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
-    0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
-    0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
-    0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
-    0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
-    0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
-    0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
-    0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
-    0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
-    0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
-    0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
-    0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
-    0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
-    0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
-    0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
-    0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
-    0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
-    0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
-    0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
-    0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
-    0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
-    0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
-    0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
-    0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
-    0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
-    0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
-    0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
-    0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
-    0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
-    0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
-    0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
-    0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
-    0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
-    0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
-    0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
-    0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
-    0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
-    0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
-};
-static const u32 Te3[256] = {
-
-    0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
-    0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
-    0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
-    0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
-    0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
-    0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
-    0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
-    0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
-    0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
-    0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
-    0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
-    0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
-    0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
-    0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
-    0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
-    0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
-    0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
-    0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
-    0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
-    0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
-    0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
-    0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
-    0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
-    0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
-    0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
-    0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
-    0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
-    0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
-    0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
-    0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
-    0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
-    0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
-    0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
-    0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
-    0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
-    0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
-    0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
-    0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
-    0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
-    0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
-    0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
-    0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
-    0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
-    0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
-    0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
-    0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
-    0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
-    0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
-    0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
-    0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
-    0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
-    0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
-    0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
-    0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
-    0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
-    0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
-    0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
-    0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
-    0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
-    0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
-    0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
-    0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
-    0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
-    0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
-};
-static const u32 Te4[256] = {
-    0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
-    0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
-    0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
-    0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
-    0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
-    0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
-    0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
-    0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
-    0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
-    0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
-    0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
-    0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
-    0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
-    0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
-    0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
-    0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
-    0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
-    0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
-    0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
-    0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
-    0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
-    0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
-    0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
-    0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
-    0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
-    0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
-    0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
-    0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
-    0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
-    0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
-    0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
-    0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
-    0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
-    0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
-    0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
-    0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
-    0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
-    0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
-    0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
-    0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
-    0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
-    0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
-    0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
-    0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
-    0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
-    0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
-    0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
-    0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
-    0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
-    0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
-    0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
-    0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
-    0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
-    0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
-    0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
-    0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
-    0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
-    0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
-    0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
-    0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
-    0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
-    0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
-    0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
-    0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
-};
-static const u32 Td0[256] = {
-    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
-    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
-    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
-    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
-    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
-    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
-    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
-    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
-    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
-    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
-    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
-    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
-    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
-    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
-    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
-    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
-    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
-    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
-    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
-    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
-    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
-    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
-    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
-    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
-    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
-    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
-    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
-    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
-    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
-    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
-    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
-    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
-    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
-    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
-    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
-    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
-    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
-    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
-    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
-    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
-    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
-    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
-    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
-    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
-    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
-    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
-    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
-    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
-    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
-    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
-    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
-    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
-    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
-    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
-    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
-    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
-    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
-    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
-    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
-    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
-    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
-    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
-    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
-    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
-};
-static const u32 Td1[256] = {
-    0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
-    0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
-    0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
-    0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
-    0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
-    0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
-    0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
-    0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
-    0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
-    0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
-    0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
-    0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
-    0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
-    0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
-    0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
-    0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
-    0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
-    0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
-    0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
-    0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
-    0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
-    0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
-    0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
-    0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
-    0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
-    0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
-    0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
-    0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
-    0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
-    0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
-    0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
-    0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
-    0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
-    0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
-    0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
-    0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
-    0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
-    0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
-    0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
-    0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
-    0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
-    0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
-    0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
-    0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
-    0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
-    0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
-    0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
-    0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
-    0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
-    0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
-    0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
-    0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
-    0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
-    0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
-    0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
-    0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
-    0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
-    0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
-    0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
-    0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
-    0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
-    0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
-    0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
-    0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
-};
-static const u32 Td2[256] = {
-    0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
-    0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
-    0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
-    0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
-    0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
-    0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
-    0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
-    0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
-    0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
-    0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
-    0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
-    0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
-    0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
-    0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
-    0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
-    0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
-    0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
-    0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
-    0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
-    0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
-
-    0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
-    0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
-    0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
-    0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
-    0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
-    0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
-    0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
-    0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
-    0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
-    0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
-    0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
-    0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
-    0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
-    0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
-    0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
-    0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
-    0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
-    0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
-    0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
-    0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
-    0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
-    0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
-    0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
-    0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
-    0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
-    0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
-    0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
-    0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
-    0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
-    0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
-    0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
-    0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
-    0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
-    0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
-    0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
-    0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
-    0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
-    0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
-    0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
-    0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
-    0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
-    0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
-    0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
-    0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
-};
-static const u32 Td3[256] = {
-    0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
-    0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
-    0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
-    0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
-    0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
-    0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
-    0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
-    0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
-    0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
-    0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
-    0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
-    0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
-    0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
-    0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
-    0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
-    0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
-    0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
-    0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
-    0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
-    0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
-    0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
-    0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
-    0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
-    0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
-    0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
-    0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
-    0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
-    0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
-    0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
-    0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
-    0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
-    0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
-    0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
-    0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
-    0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
-    0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
-    0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
-    0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
-    0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
-    0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
-    0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
-    0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
-    0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
-    0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
-    0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
-    0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
-    0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
-    0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
-    0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
-    0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
-    0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
-    0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
-    0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
-    0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
-    0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
-    0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
-    0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
-    0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
-    0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
-    0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
-    0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
-    0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
-    0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
-    0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
-};
-static const u32 Td4[256] = {
-    0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
-    0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
-    0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
-    0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
-    0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
-    0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
-    0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
-    0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
-    0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
-    0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
-    0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
-    0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
-    0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
-    0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
-    0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
-    0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
-    0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
-    0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
-    0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
-    0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
-    0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
-    0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
-    0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
-    0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
-    0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
-    0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
-    0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
-    0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
-    0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
-    0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
-    0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
-    0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
-    0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
-    0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
-    0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
-    0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
-    0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
-    0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
-    0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
-    0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
-    0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
-    0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
-    0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
-    0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
-    0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
-    0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
-    0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
-    0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
-    0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
-    0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
-    0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
-    0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
-    0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
-    0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
-    0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
-    0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
-    0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
-    0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
-    0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
-    0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
-    0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
-    0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
-    0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
-    0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
-};
-static const u32 rcon[] = {
-       0x01000000, 0x02000000, 0x04000000, 0x08000000,
-       0x10000000, 0x20000000, 0x40000000, 0x80000000,
-       0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
-};
-
-#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
-
-#ifdef _MSC_VER
-#define GETU32(p) SWAP(*((u32 *)(p)))
-#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
-#else
-#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
-#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
-#endif
-
-/**
- * Expand the cipher key into the encryption key schedule.
- *
- * @return     the number of rounds for the given cipher key size.
- */
-int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
-       int i = 0;
-       u32 temp;
-
-       rk[0] = GETU32(cipherKey     );
-       rk[1] = GETU32(cipherKey +  4);
-       rk[2] = GETU32(cipherKey +  8);
-       rk[3] = GETU32(cipherKey + 12);
-       if (keyBits == 128) {
-               for (;;) {
-                       temp  = rk[3];
-                       rk[4] = rk[0] ^
-                               (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
-                               (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
-                               (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
-                               (Te4[(temp >> 24)       ] & 0x000000ff) ^
-                               rcon[i];
-                       rk[5] = rk[1] ^ rk[4];
-                       rk[6] = rk[2] ^ rk[5];
-                       rk[7] = rk[3] ^ rk[6];
-                       if (++i == 10) {
-                               return 10;
-                       }
-                       rk += 4;
-               }
-       }
-       rk[4] = GETU32(cipherKey + 16);
-       rk[5] = GETU32(cipherKey + 20);
-       if (keyBits == 192) {
-               for (;;) {
-                       temp = rk[ 5];
-                       rk[ 6] = rk[ 0] ^
-                               (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
-                               (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
-                               (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
-                               (Te4[(temp >> 24)       ] & 0x000000ff) ^
-                               rcon[i];
-                       rk[ 7] = rk[ 1] ^ rk[ 6];
-                       rk[ 8] = rk[ 2] ^ rk[ 7];
-                       rk[ 9] = rk[ 3] ^ rk[ 8];
-                       if (++i == 8) {
-                               return 12;
-                       }
-                       rk[10] = rk[ 4] ^ rk[ 9];
-                       rk[11] = rk[ 5] ^ rk[10];
-                       rk += 6;
-               }
-       }
-       rk[6] = GETU32(cipherKey + 24);
-       rk[7] = GETU32(cipherKey + 28);
-       if (keyBits == 256) {
-        for (;;) {
-               temp = rk[ 7];
-               rk[ 8] = rk[ 0] ^
-                       (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
-                       (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
-                       (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
-                       (Te4[(temp >> 24)       ] & 0x000000ff) ^
-                       rcon[i];
-               rk[ 9] = rk[ 1] ^ rk[ 8];
-               rk[10] = rk[ 2] ^ rk[ 9];
-               rk[11] = rk[ 3] ^ rk[10];
-                       if (++i == 7) {
-                               return 14;
-                       }
-               temp = rk[11];
-               rk[12] = rk[ 4] ^
-                       (Te4[(temp >> 24)       ] & 0xff000000) ^
-                       (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
-                       (Te4[(temp >>  8) & 0xff] & 0x0000ff00) ^
-                       (Te4[(temp      ) & 0xff] & 0x000000ff);
-               rk[13] = rk[ 5] ^ rk[12];
-               rk[14] = rk[ 6] ^ rk[13];
-               rk[15] = rk[ 7] ^ rk[14];
-
-                       rk += 8;
-        }
-       }
-       return 0;
-}
-
-/**
- * Expand the cipher key into the decryption key schedule.
- *
- * @return     the number of rounds for the given cipher key size.
- */
-int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
-       int Nr, i, j;
-       u32 temp;
-
-       /* expand the cipher key: */
-       Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
-       /* invert the order of the round keys: */
-       for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
-               temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
-               temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
-               temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
-               temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
-       }
-       /* apply the inverse MixColumn transform to all round keys but the first and the last: */
-       for (i = 1; i < Nr; i++) {
-               rk += 4;
-               rk[0] =
-                       Td0[Te4[(rk[0] >> 24)       ] & 0xff] ^
-                       Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
-                       Td2[Te4[(rk[0] >>  8) & 0xff] & 0xff] ^
-                       Td3[Te4[(rk[0]      ) & 0xff] & 0xff];
-               rk[1] =
-                       Td0[Te4[(rk[1] >> 24)       ] & 0xff] ^
-                       Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
-                       Td2[Te4[(rk[1] >>  8) & 0xff] & 0xff] ^
-                       Td3[Te4[(rk[1]      ) & 0xff] & 0xff];
-               rk[2] =
-                       Td0[Te4[(rk[2] >> 24)       ] & 0xff] ^
-                       Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
-                       Td2[Te4[(rk[2] >>  8) & 0xff] & 0xff] ^
-                       Td3[Te4[(rk[2]      ) & 0xff] & 0xff];
-               rk[3] =
-                       Td0[Te4[(rk[3] >> 24)       ] & 0xff] ^
-                       Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
-                       Td2[Te4[(rk[3] >>  8) & 0xff] & 0xff] ^
-                       Td3[Te4[(rk[3]      ) & 0xff] & 0xff];
-       }
-       return Nr;
-}
-
-void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) {
-       u32 s0, s1, s2, s3, t0, t1, t2, t3;
-#ifndef FULL_UNROLL
-    int r;
-#endif /* ?FULL_UNROLL */
-
-    /*
-        * map byte array block to cipher state
-        * and add initial round key:
-        */
-       s0 = GETU32(pt     ) ^ rk[0];
-       s1 = GETU32(pt +  4) ^ rk[1];
-       s2 = GETU32(pt +  8) ^ rk[2];
-       s3 = GETU32(pt + 12) ^ rk[3];
-#ifdef FULL_UNROLL
-    /* round 1: */
-       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
-       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
-       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
-       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
-       /* round 2: */
-       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
-       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
-       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
-       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
-    /* round 3: */
-       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
-       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
-       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
-       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
-       /* round 4: */
-       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
-       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
-       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
-       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
-    /* round 5: */
-       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
-       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
-       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
-       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
-       /* round 6: */
-       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
-       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
-       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
-       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
-    /* round 7: */
-       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
-       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
-       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
-       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
-       /* round 8: */
-       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
-       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
-       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
-       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
-    /* round 9: */
-       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
-       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
-       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
-       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
-    if (Nr > 10) {
-        /* round 10: */
-        s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
-        s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
-        s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
-        s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
-        /* round 11: */
-        t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
-        t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
-        t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
-        t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
-        if (Nr > 12) {
-            /* round 12: */
-            s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
-            s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
-            s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
-            s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
-            /* round 13: */
-            t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
-            t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
-            t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
-            t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
-        }
-    }
-    rk += Nr << 2;
-#else  /* !FULL_UNROLL */
-    /*
-        * Nr - 1 full rounds:
-        */
-    r = Nr >> 1;
-    for (;;) {
-        t0 =
-            Te0[(s0 >> 24)       ] ^
-            Te1[(s1 >> 16) & 0xff] ^
-            Te2[(s2 >>  8) & 0xff] ^
-            Te3[(s3      ) & 0xff] ^
-            rk[4];
-        t1 =
-            Te0[(s1 >> 24)       ] ^
-            Te1[(s2 >> 16) & 0xff] ^
-            Te2[(s3 >>  8) & 0xff] ^
-            Te3[(s0      ) & 0xff] ^
-            rk[5];
-        t2 =
-            Te0[(s2 >> 24)       ] ^
-            Te1[(s3 >> 16) & 0xff] ^
-            Te2[(s0 >>  8) & 0xff] ^
-            Te3[(s1      ) & 0xff] ^
-            rk[6];
-        t3 =
-            Te0[(s3 >> 24)       ] ^
-            Te1[(s0 >> 16) & 0xff] ^
-            Te2[(s1 >>  8) & 0xff] ^
-            Te3[(s2      ) & 0xff] ^
-            rk[7];
-
-        rk += 8;
-        if (--r == 0) {
-            break;
-        }
-
-        s0 =
-            Te0[(t0 >> 24)       ] ^
-            Te1[(t1 >> 16) & 0xff] ^
-            Te2[(t2 >>  8) & 0xff] ^
-            Te3[(t3      ) & 0xff] ^
-            rk[0];
-        s1 =
-            Te0[(t1 >> 24)       ] ^
-            Te1[(t2 >> 16) & 0xff] ^
-            Te2[(t3 >>  8) & 0xff] ^
-            Te3[(t0      ) & 0xff] ^
-            rk[1];
-        s2 =
-            Te0[(t2 >> 24)       ] ^
-            Te1[(t3 >> 16) & 0xff] ^
-            Te2[(t0 >>  8) & 0xff] ^
-            Te3[(t1      ) & 0xff] ^
-            rk[2];
-        s3 =
-            Te0[(t3 >> 24)       ] ^
-            Te1[(t0 >> 16) & 0xff] ^
-            Te2[(t1 >>  8) & 0xff] ^
-            Te3[(t2      ) & 0xff] ^
-            rk[3];
-    }
-#endif /* ?FULL_UNROLL */
-    /*
-        * apply last round and
-        * map cipher state to byte array block:
-        */
-       s0 =
-               (Te4[(t0 >> 24)       ] & 0xff000000) ^
-               (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
-               (Te4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
-               (Te4[(t3      ) & 0xff] & 0x000000ff) ^
-               rk[0];
-       PUTU32(ct     , s0);
-       s1 =
-               (Te4[(t1 >> 24)       ] & 0xff000000) ^
-               (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
-               (Te4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
-               (Te4[(t0      ) & 0xff] & 0x000000ff) ^
-               rk[1];
-       PUTU32(ct +  4, s1);
-       s2 =
-               (Te4[(t2 >> 24)       ] & 0xff000000) ^
-               (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
-               (Te4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
-               (Te4[(t1      ) & 0xff] & 0x000000ff) ^
-               rk[2];
-       PUTU32(ct +  8, s2);
-       s3 =
-               (Te4[(t3 >> 24)       ] & 0xff000000) ^
-               (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
-               (Te4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
-               (Te4[(t2      ) & 0xff] & 0x000000ff) ^
-               rk[3];
-       PUTU32(ct + 12, s3);
-}
-
-void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) {
-       u32 s0, s1, s2, s3, t0, t1, t2, t3;
-#ifndef FULL_UNROLL
-    int r;
-#endif /* ?FULL_UNROLL */
-
-    /*
-        * map byte array block to cipher state
-        * and add initial round key:
-        */
-    s0 = GETU32(ct     ) ^ rk[0];
-    s1 = GETU32(ct +  4) ^ rk[1];
-    s2 = GETU32(ct +  8) ^ rk[2];
-    s3 = GETU32(ct + 12) ^ rk[3];
-#ifdef FULL_UNROLL
-    /* round 1: */
-    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
-    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
-    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
-    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
-    /* round 2: */
-    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
-    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
-    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
-    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
-    /* round 3: */
-    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
-    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
-    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
-    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
-    /* round 4: */
-    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
-    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
-    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
-    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
-    /* round 5: */
-    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
-    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
-    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
-    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
-    /* round 6: */
-    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
-    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
-    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
-    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
-    /* round 7: */
-    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
-    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
-    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
-    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
-    /* round 8: */
-    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
-    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
-    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
-    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
-    /* round 9: */
-    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
-    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
-    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
-    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
-    if (Nr > 10) {
-        /* round 10: */
-        s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
-        s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
-        s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
-        s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
-        /* round 11: */
-        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
-        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
-        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
-        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
-        if (Nr > 12) {
-            /* round 12: */
-            s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
-            s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
-            s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
-            s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
-            /* round 13: */
-            t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
-            t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
-            t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
-            t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
-        }
-    }
-       rk += Nr << 2;
-#else  /* !FULL_UNROLL */
-    /*
-     * Nr - 1 full rounds:
-     */
-    r = Nr >> 1;
-    for (;;) {
-        t0 =
-            Td0[(s0 >> 24)       ] ^
-            Td1[(s3 >> 16) & 0xff] ^
-            Td2[(s2 >>  8) & 0xff] ^
-            Td3[(s1      ) & 0xff] ^
-            rk[4];
-        t1 =
-            Td0[(s1 >> 24)       ] ^
-            Td1[(s0 >> 16) & 0xff] ^
-            Td2[(s3 >>  8) & 0xff] ^
-            Td3[(s2      ) & 0xff] ^
-            rk[5];
-        t2 =
-            Td0[(s2 >> 24)       ] ^
-            Td1[(s1 >> 16) & 0xff] ^
-            Td2[(s0 >>  8) & 0xff] ^
-            Td3[(s3      ) & 0xff] ^
-            rk[6];
-        t3 =
-            Td0[(s3 >> 24)       ] ^
-            Td1[(s2 >> 16) & 0xff] ^
-            Td2[(s1 >>  8) & 0xff] ^
-            Td3[(s0      ) & 0xff] ^
-            rk[7];
-
-        rk += 8;
-        if (--r == 0) {
-            break;
-        }
-
-        s0 =
-            Td0[(t0 >> 24)       ] ^
-            Td1[(t3 >> 16) & 0xff] ^
-            Td2[(t2 >>  8) & 0xff] ^
-            Td3[(t1      ) & 0xff] ^
-            rk[0];
-        s1 =
-            Td0[(t1 >> 24)       ] ^
-            Td1[(t0 >> 16) & 0xff] ^
-            Td2[(t3 >>  8) & 0xff] ^
-            Td3[(t2      ) & 0xff] ^
-            rk[1];
-        s2 =
-            Td0[(t2 >> 24)       ] ^
-            Td1[(t1 >> 16) & 0xff] ^
-            Td2[(t0 >>  8) & 0xff] ^
-            Td3[(t3      ) & 0xff] ^
-            rk[2];
-        s3 =
-            Td0[(t3 >> 24)       ] ^
-            Td1[(t2 >> 16) & 0xff] ^
-            Td2[(t1 >>  8) & 0xff] ^
-            Td3[(t0      ) & 0xff] ^
-            rk[3];
-    }
-#endif /* ?FULL_UNROLL */
-    /*
-        * apply last round and
-        * map cipher state to byte array block:
-        */
-       s0 =
-               (Td4[(t0 >> 24)       ] & 0xff000000) ^
-               (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
-               (Td4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
-               (Td4[(t1      ) & 0xff] & 0x000000ff) ^
-               rk[0];
-       PUTU32(pt     , s0);
-       s1 =
-               (Td4[(t1 >> 24)       ] & 0xff000000) ^
-               (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
-               (Td4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
-               (Td4[(t2      ) & 0xff] & 0x000000ff) ^
-               rk[1];
-       PUTU32(pt +  4, s1);
-       s2 =
-               (Td4[(t2 >> 24)       ] & 0xff000000) ^
-               (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
-               (Td4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
-               (Td4[(t3      ) & 0xff] & 0x000000ff) ^
-               rk[2];
-       PUTU32(pt +  8, s2);
-       s3 =
-               (Td4[(t3 >> 24)       ] & 0xff000000) ^
-               (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
-               (Td4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
-               (Td4[(t0      ) & 0xff] & 0x000000ff) ^
-               rk[3];
-       PUTU32(pt + 12, s3);
-}
-
-#ifdef INTERMEDIATE_VALUE_KAT
-
-void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) {
-       int r;
-       u32 s0, s1, s2, s3, t0, t1, t2, t3;
-
-    /*
-        * map byte array block to cipher state
-        * and add initial round key:
-        */
-       s0 = GETU32(block     ) ^ rk[0];
-       s1 = GETU32(block +  4) ^ rk[1];
-       s2 = GETU32(block +  8) ^ rk[2];
-       s3 = GETU32(block + 12) ^ rk[3];
-    rk += 4;
-
-    /*
-        * Nr - 1 full rounds:
-        */
-       for (r = (rounds < Nr ? rounds : Nr - 1); r > 0; r--) {
-               t0 =
-                       Te0[(s0 >> 24)       ] ^
-                       Te1[(s1 >> 16) & 0xff] ^
-                       Te2[(s2 >>  8) & 0xff] ^
-                       Te3[(s3      ) & 0xff] ^
-                       rk[0];
-               t1 =
-                       Te0[(s1 >> 24)       ] ^
-                       Te1[(s2 >> 16) & 0xff] ^
-                       Te2[(s3 >>  8) & 0xff] ^
-                       Te3[(s0      ) & 0xff] ^
-                       rk[1];
-               t2 =
-                       Te0[(s2 >> 24)       ] ^
-                       Te1[(s3 >> 16) & 0xff] ^
-                       Te2[(s0 >>  8) & 0xff] ^
-                       Te3[(s1      ) & 0xff] ^
-                       rk[2];
-               t3 =
-                       Te0[(s3 >> 24)       ] ^
-                       Te1[(s0 >> 16) & 0xff] ^
-                       Te2[(s1 >>  8) & 0xff] ^
-                       Te3[(s2      ) & 0xff] ^
-                       rk[3];
-
-               s0 = t0;
-               s1 = t1;
-               s2 = t2;
-               s3 = t3;
-               rk += 4;
-
-    }
-
-    /*
-        * apply last round and
-        * map cipher state to byte array block:
-        */
-       if (rounds == Nr) {
-       t0 =
-               (Te4[(s0 >> 24)       ] & 0xff000000) ^
-               (Te4[(s1 >> 16) & 0xff] & 0x00ff0000) ^
-               (Te4[(s2 >>  8) & 0xff] & 0x0000ff00) ^
-               (Te4[(s3      ) & 0xff] & 0x000000ff) ^
-               rk[0];
-       t1 =
-               (Te4[(s1 >> 24)       ] & 0xff000000) ^
-               (Te4[(s2 >> 16) & 0xff] & 0x00ff0000) ^
-               (Te4[(s3 >>  8) & 0xff] & 0x0000ff00) ^
-               (Te4[(s0      ) & 0xff] & 0x000000ff) ^
-               rk[1];
-       t2 =
-               (Te4[(s2 >> 24)       ] & 0xff000000) ^
-               (Te4[(s3 >> 16) & 0xff] & 0x00ff0000) ^
-               (Te4[(s0 >>  8) & 0xff] & 0x0000ff00) ^
-               (Te4[(s1      ) & 0xff] & 0x000000ff) ^
-               rk[2];
-       t3 =
-               (Te4[(s3 >> 24)       ] & 0xff000000) ^
-               (Te4[(s0 >> 16) & 0xff] & 0x00ff0000) ^
-               (Te4[(s1 >>  8) & 0xff] & 0x0000ff00) ^
-               (Te4[(s2      ) & 0xff] & 0x000000ff) ^
-               rk[3];
-               
-               s0 = t0;
-               s1 = t1;
-               s2 = t2;
-               s3 = t3;
-       }
-
-       PUTU32(block     , s0);
-       PUTU32(block +  4, s1);
-       PUTU32(block +  8, s2);
-       PUTU32(block + 12, s3);
-}
-
-void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) {
-       int r;
-       u32 s0, s1, s2, s3, t0, t1, t2, t3;
-
-    /*
-        * map byte array block to cipher state
-        * and add initial round key:
-        */
-       s0 = GETU32(block     ) ^ rk[0];
-       s1 = GETU32(block +  4) ^ rk[1];
-       s2 = GETU32(block +  8) ^ rk[2];
-       s3 = GETU32(block + 12) ^ rk[3];
-    rk += 4;
-
-    /*
-        * Nr - 1 full rounds:
-        */
-       for (r = (rounds < Nr ? rounds : Nr) - 1; r > 0; r--) {
-               t0 =
-                       Td0[(s0 >> 24)       ] ^
-                       Td1[(s3 >> 16) & 0xff] ^
-                       Td2[(s2 >>  8) & 0xff] ^
-                       Td3[(s1      ) & 0xff] ^
-                       rk[0];
-               t1 =
-                       Td0[(s1 >> 24)       ] ^
-                       Td1[(s0 >> 16) & 0xff] ^
-                       Td2[(s3 >>  8) & 0xff] ^
-                       Td3[(s2      ) & 0xff] ^
-                       rk[1];
-               t2 =
-                       Td0[(s2 >> 24)       ] ^
-                       Td1[(s1 >> 16) & 0xff] ^
-                       Td2[(s0 >>  8) & 0xff] ^
-                       Td3[(s3      ) & 0xff] ^
-                       rk[2];
-               t3 =
-                       Td0[(s3 >> 24)       ] ^
-                       Td1[(s2 >> 16) & 0xff] ^
-                       Td2[(s1 >>  8) & 0xff] ^
-                       Td3[(s0      ) & 0xff] ^
-                       rk[3];
-
-               s0 = t0;
-               s1 = t1;
-               s2 = t2;
-               s3 = t3;
-               rk += 4;
-
-    }
-
-    /*
-        * complete the last round and
-        * map cipher state to byte array block:
-        */
-       t0 =
-               (Td4[(s0 >> 24)       ] & 0xff000000) ^
-               (Td4[(s3 >> 16) & 0xff] & 0x00ff0000) ^
-               (Td4[(s2 >>  8) & 0xff] & 0x0000ff00) ^
-               (Td4[(s1      ) & 0xff] & 0x000000ff);
-       t1 =
-               (Td4[(s1 >> 24)       ] & 0xff000000) ^
-               (Td4[(s0 >> 16) & 0xff] & 0x00ff0000) ^
-               (Td4[(s3 >>  8) & 0xff] & 0x0000ff00) ^
-               (Td4[(s2      ) & 0xff] & 0x000000ff);
-       t2 =
-               (Td4[(s2 >> 24)       ] & 0xff000000) ^
-               (Td4[(s1 >> 16) & 0xff] & 0x00ff0000) ^
-               (Td4[(s0 >>  8) & 0xff] & 0x0000ff00) ^
-               (Td4[(s3      ) & 0xff] & 0x000000ff);
-       t3 =
-               (Td4[(s3 >> 24)       ] & 0xff000000) ^
-               (Td4[(s2 >> 16) & 0xff] & 0x00ff0000) ^
-               (Td4[(s1 >>  8) & 0xff] & 0x0000ff00) ^
-               (Td4[(s0      ) & 0xff] & 0x000000ff);
-
-       if (rounds == Nr) {
-           t0 ^= rk[0];
-           t1 ^= rk[1];
-           t2 ^= rk[2];
-           t3 ^= rk[3];
-       }
-
-       PUTU32(block     , t0);
-       PUTU32(block +  4, t1);
-       PUTU32(block +  8, t2);
-       PUTU32(block + 12, t3);
-}
-
-#endif /* INTERMEDIATE_VALUE_KAT */
diff --git a/libhashkit/rijndael.hpp b/libhashkit/rijndael.hpp
deleted file mode 100644 (file)
index 1d3aec6..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * rijndael-alg-fst.h
- *
- * @version 3.0 (December 2000)
- *
- * Optimised ANSI C code for the Rijndael cipher (now AES)
- *
- * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
- * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
- * @author Paulo Barreto <paulo.barreto@terra.com.br>
- *
- * This code is hereby placed in the public domain.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
- * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#define MAXKC  (256/32)
-#define MAXKB  (256/8)
-#define MAXNR  14
-
-#define AES_MAXKC MAXKC
-#define AES_MAXKB MAXKB
-#define AES_MAXNR MAXNR
-
-typedef unsigned char  u8;     
-typedef unsigned short u16;    
-typedef unsigned int   u32;
-
-int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
-int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
-void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]);
-void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]);
-
-#ifdef INTERMEDIATE_VALUE_KAT
-void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds);
-void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds);
-#endif /* INTERMEDIATE_VALUE_KAT */
diff --git a/libhashkit/str_algorithm.cc b/libhashkit/str_algorithm.cc
deleted file mode 100644 (file)
index b84a0bb..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libhashkit/common.h>
-
-const char * libhashkit_string_hash(hashkit_hash_algorithm_t type)
-{
-  switch(type)
-  {
-  case HASHKIT_HASH_DEFAULT: return "DEFAULT";
-  case HASHKIT_HASH_MD5: return "MD5";
-  case HASHKIT_HASH_CRC: return "CRC";
-  case HASHKIT_HASH_FNV1_64: return "FNV1_64";
-  case HASHKIT_HASH_FNV1A_64: return "FNV1A_64";
-  case HASHKIT_HASH_FNV1_32: return "FNV1_32";
-  case HASHKIT_HASH_FNV1A_32: return "FNV1A_32";
-  case HASHKIT_HASH_HSIEH: return "HSIEH";
-  case HASHKIT_HASH_MURMUR: return "MURMUR";
-  case HASHKIT_HASH_MURMUR3: return "MURMUR3";
-  case HASHKIT_HASH_JENKINS: return "JENKINS";
-  case HASHKIT_HASH_CUSTOM: return "CUSTOM";
-  default:
-  case HASHKIT_HASH_MAX: return "INVALID";
-  }
-}
diff --git a/libhashkit/strerror.cc b/libhashkit/strerror.cc
deleted file mode 100644 (file)
index f67e5c5..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  HashKit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2009 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-
-#include <libhashkit/common.h>
-
-const char *hashkit_strerror(hashkit_st *ptr, hashkit_return_t rc)
-{
-  (void)ptr;
-  switch (rc)
-  {
-  case HASHKIT_SUCCESS: return "SUCCESS";
-  case HASHKIT_FAILURE: return "FAILURE";
-  case HASHKIT_MEMORY_ALLOCATION_FAILURE: return "MEMORY ALLOCATION FAILURE";
-  case HASHKIT_INVALID_ARGUMENT: return "INVALID ARGUMENT";
-  case HASHKIT_INVALID_HASH: return "INVALID hashkit_hash_algorithm_t";
-  case HASHKIT_MAXIMUM_RETURN:
-  default:
-    return "INVALID hashkit_return_t";
-  }
-}
diff --git a/libhashkit/string.cc b/libhashkit/string.cc
deleted file mode 100644 (file)
index 05bbdc5..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libhashkit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libhashkit/common.h>
-
-#include <cassert>
-#include <cstring>
-
-#define HASHKIT_BLOCK_SIZE 1024
-
-struct hashkit_string_st {
-  char *end;
-  size_t current_size;
-  char *string;
-};
-
-inline static bool _string_check(hashkit_string_st *string, size_t need)
-{
-  if (need and need > (size_t)(string->current_size - (size_t)(string->end - string->string)))
-  {
-    size_t current_offset= (size_t) (string->end - string->string);
-
-    /* This is the block multiplier. To keep it larger and surive division errors we must round it up */
-    size_t adjust= (need - (size_t)(string->current_size - (size_t)(string->end - string->string))) / HASHKIT_BLOCK_SIZE;
-    adjust++;
-
-    size_t new_size= sizeof(char) * (size_t)((adjust * HASHKIT_BLOCK_SIZE) + string->current_size);
-    /* Test for overflow */
-    if (new_size < need)
-    {
-      return false;
-    }
-
-    char *new_value= (char*)realloc(string->string, new_size);
-
-    if (new_value == NULL)
-    {
-      return false;
-    }
-
-    string->string= new_value;
-    string->end= string->string + current_offset;
-
-    string->current_size+= (HASHKIT_BLOCK_SIZE * adjust);
-  }
-
-  return true;
-}
-
-static inline void _init_string(hashkit_string_st *self)
-{
-  self->current_size= 0;
-  self->end= self->string= NULL;
-}
-
-hashkit_string_st *hashkit_string_create(size_t initial_size)
-{
-  hashkit_string_st* self= (hashkit_string_st*)calloc(1, sizeof(hashkit_string_st));
-
-  if (self)
-  {
-    if (_string_check(self, initial_size) == false)
-    {
-      free(self);
-
-      return NULL;
-    }
-  }
-
-  return self;
-}
-
-#if 0
-static bool hashkit_string_append_null(hashkit_string_st *string)
-{
-  if (_string_check(string, 1) == false)
-  {
-    return false;
-  }
-
-  *string->end= 0;
-
-  return true;
-}
-#endif
-
-bool hashkit_string_append_character(hashkit_string_st *string,
-                                     char character)
-{
-  if (_string_check(string, 1) == false)
-  {
-    return false;
-  }
-
-  *string->end= character;
-  string->end++;
-
-  return true;
-}
-
-bool hashkit_string_append(hashkit_string_st *string,
-                           const char *value, size_t length)
-{
-  if (_string_check(string, length) == false)
-  {
-    return false;
-  }
-
-  assert(length <= string->current_size);
-  assert(string->string);
-  assert(string->end >= string->string);
-
-  memcpy(string->end, value, length);
-  string->end+= length;
-
-  return true;
-}
-
-char *hashkit_string_c_copy(hashkit_string_st *string)
-{
-  if (hashkit_string_length(string) == 0)
-  {
-    return NULL;
-  }
-
-  char *c_ptr= static_cast<char *>(malloc((hashkit_string_length(string)+1) * sizeof(char)));
-  if (c_ptr == NULL)
-  {
-    return NULL;
-  }
-
-  memcpy(c_ptr, hashkit_string_c_str(string), hashkit_string_length(string));
-  c_ptr[hashkit_string_length(string)]= 0;
-
-  return c_ptr;
-}
-
-void hashkit_string_reset(hashkit_string_st *string)
-{
-  string->end= string->string;
-}
-
-void hashkit_string_free(hashkit_string_st *ptr)
-{
-  if (ptr == NULL)
-  {
-    return;
-  }
-
-  if (ptr->string)
-  {
-    free(ptr->string);
-  }
-  free(ptr);
-}
-
-bool hashkit_string_resize(hashkit_string_st& string, const size_t need)
-{
-  return _string_check(&string, need);
-}
-
-size_t hashkit_string_length(const hashkit_string_st *self)
-{
-  return size_t(self->end -self->string);
-}
-
-size_t hashkit_string_max_size(const hashkit_string_st *self)
-{
-  return self->current_size;
-}
-
-char *hashkit_string_take(hashkit_string_st *self)
-{
-  assert(self);
-  if (self == NULL)
-  {
-    return NULL;
-  }
-  char *value= self->string;
-
-  _init_string(self);
-
-  return value;
-}
-
-char *hashkit_string_c_str_mutable(hashkit_string_st *self)
-{
-  assert(self);
-  if (self == NULL)
-  {
-    return NULL;
-  }
-  return self->string;
-}
-
-const char *hashkit_string_c_str(const hashkit_string_st* self)
-{
-  assert(self);
-  if (self == NULL)
-  {
-    return NULL;
-  }
-  return self->string;
-}
-
-void hashkit_string_set_length(hashkit_string_st *self, size_t length)
-{
-  assert(self);
-  if (self and _string_check(self, length))
-  {
-    self->end= self->string +length;
-  }
-}
diff --git a/libhashkit/string.h b/libhashkit/string.h
deleted file mode 100644 (file)
index 8aee89e..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Hashkit library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-hashkit_string_st *hashkit_string_create(size_t initial_size);
-
-bool hashkit_string_append_character(hashkit_string_st *string, char character);
-
-bool hashkit_string_append(hashkit_string_st *string, const char *value, size_t length);
-
-char *hashkit_string_c_copy(hashkit_string_st *string);
-
-void hashkit_string_reset(hashkit_string_st *string);
-
-bool hashkit_string_resize(hashkit_string_st& string, const size_t need);
-
-size_t hashkit_string_max_size(const hashkit_string_st *self);
-
-char *hashkit_string_take(hashkit_string_st *self);
-
-char *hashkit_string_c_str_mutable(hashkit_string_st *self);
-
-void hashkit_string_set_length(hashkit_string_st *self, size_t length);
diff --git a/libmemcached-1.0/CMakeLists.txt b/libmemcached-1.0/CMakeLists.txt
deleted file mode 100644 (file)
index 061c6f7..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-
-configure_file(configure.h.in configure.h @ONLY)
-
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
-        FILES_MATCHING REGEX "\\.h(pp)?$"
-        PATTERN t EXCLUDE
-        )
diff --git a/libmemcached-1.0/alloc.h b/libmemcached-1.0/alloc.h
deleted file mode 100644 (file)
index bc65b95..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
-  Memory allocation functions.
-*/
-typedef void (*memcached_free_fn)(const memcached_st *ptr, void *mem, void *context);
-typedef void *(*memcached_malloc_fn)(const memcached_st *ptr, const size_t size, void *context);
-typedef void *(*memcached_realloc_fn)(const memcached_st *ptr, void *mem, const size_t size, void *context);
-typedef void *(*memcached_calloc_fn)(const memcached_st *ptr, size_t nelem, const size_t elsize, void *context);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/allocators.h b/libmemcached-1.0/allocators.h
deleted file mode 100644 (file)
index 86f05a0..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_set_memory_allocators(memcached_st *ptr,
-                                                   memcached_malloc_fn mem_malloc,
-                                                   memcached_free_fn mem_free,
-                                                   memcached_realloc_fn mem_realloc,
-                                                   memcached_calloc_fn mem_calloc,
-                                                   void *context);
-
-LIBMEMCACHED_API
-void memcached_get_memory_allocators(const memcached_st *ptr,
-                                     memcached_malloc_fn *mem_malloc,
-                                     memcached_free_fn *mem_free,
-                                     memcached_realloc_fn *mem_realloc,
-                                     memcached_calloc_fn *mem_calloc);
-
-LIBMEMCACHED_API
-void *memcached_get_memory_allocators_context(const memcached_st *ptr);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/analyze.h b/libmemcached-1.0/analyze.h
deleted file mode 100644 (file)
index 0da3814..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached-1.0/struct/analysis.h>
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_analysis_st *memcached_analyze(memcached_st *memc,
-                                         memcached_stat_st *memc_stat,
-                                         memcached_return_t *error);
-
-LIBMEMCACHED_API
-void memcached_analyze_free(memcached_analysis_st *);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/auto.h b/libmemcached-1.0/auto.h
deleted file mode 100644 (file)
index f37d50f..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-  memcached_return_t memcached_increment(memcached_st *ptr,
-                                         const char *key, size_t key_length,
-                                         uint32_t offset,
-                                         uint64_t *value);
-LIBMEMCACHED_API
-  memcached_return_t memcached_decrement(memcached_st *ptr,
-                                         const char *key, size_t key_length,
-                                         uint32_t offset,
-                                         uint64_t *value);
-
-LIBMEMCACHED_API
-  memcached_return_t memcached_increment_by_key(memcached_st *ptr,
-                                                const char *group_key, size_t group_key_length,
-                                                const char *key, size_t key_length,
-                                                uint64_t offset,
-                                                uint64_t *value);
-
-LIBMEMCACHED_API
-  memcached_return_t memcached_decrement_by_key(memcached_st *ptr,
-                                                const char *group_key, size_t group_key_length,
-                                                const char *key, size_t key_length,
-                                                uint64_t offset,
-                                                uint64_t *value);
-
-LIBMEMCACHED_API
-  memcached_return_t memcached_increment_with_initial(memcached_st *ptr,
-                                                      const char *key,
-                                                      size_t key_length,
-                                                      uint64_t offset,
-                                                      uint64_t initial,
-                                                      time_t expiration,
-                                                      uint64_t *value);
-
-LIBMEMCACHED_API
-  memcached_return_t memcached_decrement_with_initial(memcached_st *ptr,
-                                                      const char *key,
-                                                      size_t key_length,
-                                                      uint64_t offset,
-                                                      uint64_t initial,
-                                                      time_t expiration,
-                                                      uint64_t *value);
-
-LIBMEMCACHED_API
-  memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr,
-                                                             const char *group_key,
-                                                             size_t group_key_length,
-                                                             const char *key,
-                                                             size_t key_length,
-                                                             uint64_t offset,
-                                                             uint64_t initial,
-                                                             time_t expiration,
-                                                             uint64_t *value);
-
-LIBMEMCACHED_API
-  memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr,
-                                                             const char *group_key,
-                                                             size_t group_key_length,
-                                                             const char *key,
-                                                             size_t key_length,
-                                                             uint64_t offset,
-                                                             uint64_t initial,
-                                                             time_t expiration,
-                                                             uint64_t *value);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/basic_string.h b/libmemcached-1.0/basic_string.h
deleted file mode 100644 (file)
index de8d3d5..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-// No assumptions of NULL should be made
-
-struct memcached_string_t {
-  const char *c_str;
-  size_t size;
-};
-
-#define memcached_size(X) (X).size;
-#define memcached_c_str(X) (X).c_str;
-#define memcached_string_param(X) (X).c_str, (X).size
-
-#ifdef __cplusplus
-#define memcached_string_printf(X) int((X).size), (X).c_str
-#else
-#define memcached_string_printf(X) (int)((X).size), (X).c_str
-#endif
-
diff --git a/libmemcached-1.0/behavior.h b/libmemcached-1.0/behavior.h
deleted file mode 100644 (file)
index c663353..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_behavior_set(memcached_st *ptr, const memcached_behavior_t flag, uint64_t data);
-
-LIBMEMCACHED_API
-uint64_t memcached_behavior_get(memcached_st *ptr, const memcached_behavior_t flag);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_behavior_set_distribution(memcached_st *ptr, memcached_server_distribution_t type);
-
-LIBMEMCACHED_API
-memcached_server_distribution_t memcached_behavior_get_distribution(memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_behavior_set_key_hash(memcached_st *ptr, memcached_hash_t type);
-
-LIBMEMCACHED_API
-memcached_hash_t memcached_behavior_get_key_hash(memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_behavior_set_distribution_hash(memcached_st *ptr, memcached_hash_t type);
-
-LIBMEMCACHED_API
-memcached_hash_t memcached_behavior_get_distribution_hash(memcached_st *ptr);
-
-LIBMEMCACHED_API
-  const char *libmemcached_string_behavior(const memcached_behavior_t flag);
-
-LIBMEMCACHED_API
-  const char *libmemcached_string_distribution(const memcached_server_distribution_t flag);
-
-LIBMEMCACHED_API
-  memcached_return_t memcached_bucket_set(memcached_st *self,
-                                          const uint32_t *host_map,
-                                          const uint32_t *forward_map,
-                                          const uint32_t buckets,
-                                          const uint32_t replicas);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/callback.h b/libmemcached-1.0/callback.h
deleted file mode 100644 (file)
index a62e9aa..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_callback_set(memcached_st *ptr,
-                                          const memcached_callback_t flag,
-                                          const void *data);
-LIBMEMCACHED_API
-void *memcached_callback_get(memcached_st *ptr,
-                             const memcached_callback_t flag,
-                             memcached_return_t *error);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/callbacks.h b/libmemcached-1.0/callbacks.h
deleted file mode 100644 (file)
index 7ab8cb1..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef memcached_return_t (*memcached_execute_fn)(const memcached_st *ptr, memcached_result_st *result, void *context);
-typedef memcached_return_t (*memcached_server_fn)(const memcached_st *ptr, const memcached_instance_st * server, void *context);
-typedef memcached_return_t (*memcached_stat_fn)(const memcached_instance_st * server,
-                                                const char *key, size_t key_length,
-                                                const char *value, size_t value_length,
-                                                void *context);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/configure.h.in b/libmemcached-1.0/configure.h.in
deleted file mode 100644 (file)
index 07d8442..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker, Trond Norbye All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#cmakedefine01 LIBMEMCACHED_ENABLE_DEPRECATED
-#cmakedefine01 LIBMEMCACHED_WITH_SASL_SUPPORT
-
-#define LIBMEMCACHED_VERSION_STRING "@LIBMEMCACHED_VERSION@"
-#define LIBMEMCACHED_VERSION_HEX @LIBMEMCACHED_VERSION_HEX@
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/defaults.h b/libmemcached-1.0/defaults.h
deleted file mode 100644 (file)
index d440f8c..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-/* Public defines */
-#define MEMCACHED_DEFAULT_PORT 11211
-#define MEMCACHED_DEFAULT_PORT_STRING "11211"
-#define MEMCACHED_POINTS_PER_SERVER 100
-#define MEMCACHED_POINTS_PER_SERVER_KETAMA 160
-#define MEMCACHED_CONTINUUM_SIZE MEMCACHED_POINTS_PER_SERVER*100 /* This would then set max hosts to 100 */
-#define MEMCACHED_STRIDE 4
-#define MEMCACHED_DEFAULT_TIMEOUT 5000
-#define MEMCACHED_DEFAULT_CONNECT_TIMEOUT 4000
-#define MEMCACHED_CONTINUUM_ADDITION 10 /* How many extra slots we should build for in the continuum */
-#define MEMCACHED_EXPIRATION_NOT_ADD 0xffffffffU
-#define MEMCACHED_SERVER_FAILURE_LIMIT 5
-#define MEMCACHED_SERVER_FAILURE_RETRY_TIMEOUT 2
-#define MEMCACHED_SERVER_FAILURE_DEAD_TIMEOUT 0
-#define MEMCACHED_SERVER_TIMEOUT_LIMIT 0
-
diff --git a/libmemcached-1.0/delete.h b/libmemcached-1.0/delete.h
deleted file mode 100644 (file)
index 617d585..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_delete(memcached_st *ptr, const char *key, size_t key_length,
-                                    time_t expiration);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_delete_by_key(memcached_st *ptr,
-                                           const char *group_key, size_t group_key_length,
-                                           const char *key, size_t key_length,
-                                           time_t expiration);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/deprecated_types.h b/libmemcached-1.0/deprecated_types.h
deleted file mode 100644 (file)
index 0a6df65..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * Warning, none of these should ever be used.
- */
-
-#pragma once
-
-/**
-  @note The following definitions are just here for backwards compatibility.
-*/
-typedef memcached_return_t memcached_return;
-typedef memcached_server_distribution_t memcached_server_distribution;
-typedef memcached_behavior_t memcached_behavior;
-typedef memcached_callback_t memcached_callback;
-typedef memcached_hash_t memcached_hash;
-typedef memcached_connection_t memcached_connection;
-typedef memcached_clone_fn memcached_clone_func;
-typedef memcached_cleanup_fn memcached_cleanup_func;
-typedef memcached_execute_fn memcached_execute_function;
-typedef memcached_server_fn memcached_server_function;
-typedef memcached_trigger_key_fn memcached_trigger_key;
-typedef memcached_trigger_delete_key_fn memcached_trigger_delete_key;
-typedef memcached_dump_fn memcached_dump_func;
-typedef memcached_instance_st *memcached_server_instance_st;
-
diff --git a/libmemcached-1.0/dump.h b/libmemcached-1.0/dump.h
deleted file mode 100644 (file)
index b6e639e..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_dump(memcached_st *ptr, memcached_dump_fn *function, void *context, uint32_t number_of_callbacks);
-
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/encoding_key.h b/libmemcached-1.0/encoding_key.h
deleted file mode 100644 (file)
index 3adbcb6..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-  memcached_return_t memcached_set_encoding_key(memcached_st*, const char *str, size_t length);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/error.h b/libmemcached-1.0/error.h
deleted file mode 100644 (file)
index 9346bb0..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-  const char *memcached_error(const memcached_st *);
-
-LIBMEMCACHED_API
-  const char *memcached_last_error_message(const memcached_st *);
-
-LIBMEMCACHED_API
-  void memcached_error_print(const memcached_st *);
-
-LIBMEMCACHED_API
-  memcached_return_t memcached_last_error(const memcached_st *);
-
-LIBMEMCACHED_API
-  int memcached_last_error_errno(const memcached_st *);
-
-LIBMEMCACHED_API
-  const char *memcached_server_error(const memcached_instance_st * ptr);
-
-LIBMEMCACHED_API
-  memcached_return_t memcached_server_error_return(const memcached_instance_st * ptr);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/libmemcached-1.0/exception.hpp b/libmemcached-1.0/exception.hpp
deleted file mode 100644 (file)
index 4759072..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Summary: Exceptions for the C++ interface
- *
- * Copy: See Copyright for the status of this software.
- *
- */
-
-/**
- * @file
- * @brief Exception declarations
- */
-
-#pragma once
-
-#include <stdexcept>
-#include <string>
-
-namespace memcache 
-{
-  class Exception : public std::runtime_error
-  {
-  public:
-    Exception(const std::string& msg, int in_errno)
-      : 
-        std::runtime_error(msg), 
-        _errno(in_errno) 
-    {}
-
-    Exception(const char *msg, int in_errno)
-      : 
-        std::runtime_error(std::string(msg)), 
-        _errno(in_errno) {}
-
-    virtual ~Exception() throw() {}
-
-    int getErrno() const 
-    { 
-      return _errno; 
-    }
-
-  private:
-    int _errno;
-  };
-
-  class Warning : public Exception
-  {
-  public:
-    Warning(const std::string& msg, int in_errno) : Exception(msg, in_errno) {}
-    Warning(const char *msg, int in_errno) : Exception(msg, in_errno) {}
-  };
-
-  class Error : public Exception
-  {
-  public:
-    Error(const std::string& msg, int in_errno) : Exception(msg, in_errno) {}
-    Error(const char *msg, int in_errno) : Exception(msg, in_errno) {}
-    virtual ~Error() throw() {}
-  };
-
-} /* namespace libmemcached */
diff --git a/libmemcached-1.0/exist.h b/libmemcached-1.0/exist.h
deleted file mode 100644 (file)
index ef60a81..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_exist(memcached_st *memc, const char *key, size_t key_length);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_exist_by_key(memcached_st *memc,
-                                          const char *group_key, size_t group_key_length,
-                                          const char *key, size_t key_length);
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/fetch.h b/libmemcached-1.0/fetch.h
deleted file mode 100644 (file)
index bff186a..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_fetch_execute(memcached_st *ptr,
-                                           memcached_execute_fn *callback,
-                                           void *context,
-                                           uint32_t number_of_callbacks);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/flush.h b/libmemcached-1.0/flush.h
deleted file mode 100644 (file)
index 820a98e..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_flush(memcached_st *ptr, time_t expiration);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/flush_buffers.h b/libmemcached-1.0/flush_buffers.h
deleted file mode 100644 (file)
index 31b5868..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_flush_buffers(memcached_st *mem);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/get.h b/libmemcached-1.0/get.h
deleted file mode 100644 (file)
index 32e4c5f..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Public defines */
-LIBMEMCACHED_API
-char *memcached_get(memcached_st *ptr,
-                    const char *key, size_t key_length,
-                    size_t *value_length,
-                    uint32_t *flags,
-                    memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_mget(memcached_st *ptr,
-                                  const char * const *keys,
-                                  const size_t *key_length,
-                                  size_t number_of_keys);
-
-LIBMEMCACHED_API
-char *memcached_get_by_key(memcached_st *ptr,
-                           const char *group_key, size_t group_key_length,
-                           const char *key, size_t key_length,
-                           size_t *value_length,
-                           uint32_t *flags,
-                           memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_mget_by_key(memcached_st *ptr,
-                                         const char *group_key,
-                                         size_t group_key_length,
-                                         const char * const *keys,
-                                         const size_t *key_length,
-                                         const size_t number_of_keys);
-
-LIBMEMCACHED_API
-char *memcached_fetch(memcached_st *ptr,
-                      char *key,
-                      size_t *key_length,
-                      size_t *value_length,
-                      uint32_t *flags,
-                      memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_result_st *memcached_fetch_result(memcached_st *ptr,
-                                            memcached_result_st *result,
-                                            memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_mget_execute(memcached_st *ptr,
-                                          const char * const *keys,
-                                          const size_t *key_length,
-                                          const size_t number_of_keys,
-                                          memcached_execute_fn *callback,
-                                          void *context,
-                                          const uint32_t number_of_callbacks);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_mget_execute_by_key(memcached_st *ptr,
-                                                 const char *group_key,
-                                                 size_t group_key_length,
-                                                 const char * const *keys,
-                                                 const size_t *key_length,
-                                                 size_t number_of_keys,
-                                                 memcached_execute_fn *callback,
-                                                 void *context,
-                                                 const uint32_t number_of_callbacks);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/hash.h b/libmemcached-1.0/hash.h
deleted file mode 100644 (file)
index 9fdb7d6..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* The two public hash bits */
-LIBMEMCACHED_API
-uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash_t hash_algorithm);
-
-LIBMEMCACHED_API
-const hashkit_st *memcached_get_hashkit(const memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_set_hashkit(memcached_st *ptr, hashkit_st *hashk);
-
-LIBMEMCACHED_API
-uint32_t memcached_generate_hash(const memcached_st *ptr, const char *key, size_t key_length);
-
-LIBMEMCACHED_API
-void memcached_autoeject(memcached_st *ptr);
-
-LIBMEMCACHED_API
-  const char * libmemcached_string_hash(memcached_hash_t type);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/limits.h b/libmemcached-1.0/limits.h
deleted file mode 100644 (file)
index 076df40..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#define MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH 20
-#define MEMCACHED_MAX_BUFFER 8196
-#define MEMCACHED_MAX_HOST_SORT_LENGTH 86 /* Used for Ketama */
-#define MEMCACHED_MAX_KEY 251 /* We add one to have it null terminated */
-#define MEMCACHED_PREFIX_KEY_MAX_SIZE 128
-#define MEMCACHED_VERSION_STRING_LENGTH 24
diff --git a/libmemcached-1.0/memcached.h b/libmemcached-1.0/memcached.h
deleted file mode 100644 (file)
index 1ee54bb..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-/* This seems to be required for older compilers @note http://stackoverflow.com/questions/8132399/how-to-printf-uint64-t  */
-#ifndef __STDC_FORMAT_MACROS
-#  define __STDC_FORMAT_MACROS
-#endif
-
-#ifdef __cplusplus
-#  if __cplusplus >= 201103L
-#    include <cinttypes>
-#  else
-#    include <inttypes.h>
-#  endif
-#  include <cstddef>
-#  include <cstdlib>
-#else
-#  include <inttypes.h>
-#  include <stddef.h>
-#  include <stdlib.h>
-#  include <stdbool.h>
-#endif
-
-#include <sys/types.h>
-
-#include <libmemcached-1.0/visibility.h>
-#include <libmemcached-1.0/configure.h>
-#include <libmemcached-1.0/platform.h>
-
-#include <libmemcached-1.0/limits.h>
-#include <libmemcached-1.0/defaults.h>
-
-#include <libmemcached-1.0/types/behavior.h>
-#include <libmemcached-1.0/types/callback.h>
-#include <libmemcached-1.0/types/connection.h>
-#include <libmemcached-1.0/types/hash.h>
-#include <libmemcached-1.0/types/return.h>
-#include <libmemcached-1.0/types/server_distribution.h>
-
-#include <libmemcached-1.0/return.h>
-
-#include <libmemcached-1.0/types.h>
-#include <libmemcached-1.0/callbacks.h>
-#include <libmemcached-1.0/alloc.h>
-#include <libmemcached-1.0/triggers.h>
-
-#include <libhashkit-1.0/hashkit.h>
-
-#include <libmemcached-1.0/struct/callback.h>
-#include <libmemcached-1.0/struct/string.h>
-#include <libmemcached-1.0/struct/result.h>
-#include <libmemcached-1.0/struct/allocator.h>
-#include <libmemcached-1.0/struct/sasl.h>
-#include <libmemcached-1.0/struct/memcached.h>
-#include <libmemcached-1.0/struct/server.h>
-#include <libmemcached-1.0/struct/stat.h>
-
-#include <libmemcached-1.0/basic_string.h>
-#include <libmemcached-1.0/error.h>
-#include <libmemcached-1.0/stats.h>
-
-// Everything above this line must be in the order specified.
-#include <libmemcached-1.0/allocators.h>
-#include <libmemcached-1.0/analyze.h>
-#include <libmemcached-1.0/auto.h>
-#include <libmemcached-1.0/behavior.h>
-#include <libmemcached-1.0/callback.h>
-#include <libmemcached-1.0/delete.h>
-#include <libmemcached-1.0/dump.h>
-#include <libmemcached-1.0/encoding_key.h>
-#include <libmemcached-1.0/exist.h>
-#include <libmemcached-1.0/fetch.h>
-#include <libmemcached-1.0/flush.h>
-#include <libmemcached-1.0/flush_buffers.h>
-#include <libmemcached-1.0/get.h>
-#include <libmemcached-1.0/hash.h>
-#include <libmemcached-1.0/options.h>
-#include <libmemcached-1.0/parse.h>
-#include <libmemcached-1.0/quit.h>
-#include <libmemcached-1.0/result.h>
-#include <libmemcached-1.0/server.h>
-#include <libmemcached-1.0/server_list.h>
-#include <libmemcached-1.0/storage.h>
-#include <libmemcached-1.0/strerror.h>
-#include <libmemcached-1.0/touch.h>
-#include <libmemcached-1.0/verbosity.h>
-#include <libmemcached-1.0/version.h>
-#include <libmemcached-1.0/sasl.h>
-
-#include <libmemcached-1.0/deprecated_types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-void memcached_servers_reset(memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_st *memcached_create(memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_st *memcached(const char *string, size_t string_length);
-
-LIBMEMCACHED_API
-void memcached_free(memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_reset(memcached_st *ptr);
-
-LIBMEMCACHED_API
-void memcached_reset_last_disconnected_server(memcached_st *ptr);
-
-LIBMEMCACHED_API
-memcached_st *memcached_clone(memcached_st *clone, const memcached_st *ptr);
-
-LIBMEMCACHED_API
-void *memcached_get_user_data(const memcached_st *ptr);
-
-LIBMEMCACHED_API
-void *memcached_set_user_data(memcached_st *ptr, void *data);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_push(memcached_st *destination, const memcached_st *source);
-
-LIBMEMCACHED_API
-const memcached_instance_st * memcached_server_instance_by_position(const memcached_st *ptr, uint32_t server_key);
-
-LIBMEMCACHED_API
-uint32_t memcached_server_count(const memcached_st *);
-
-LIBMEMCACHED_API
-uint64_t memcached_query_id(const memcached_st *);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/libmemcached-1.0/memcached.hpp b/libmemcached-1.0/memcached.hpp
deleted file mode 100644 (file)
index af12f30..0000000
+++ /dev/null
@@ -1,876 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * Summary: C++ interface for memcached server
- *
- * Copy: See Copyright for the status of this software.
- *
- * Authors: Padraig O'Sullivan <osullivan.padraig@gmail.com>
- *          Patrick Galbraith <patg@patg.net>
- */
-
-/**
- * @file memcached.hpp
- * @brief Libmemcached C++ interface
- */
-
-#pragma once
-
-#include <libmemcached-1.0/memcached.h>
-#if 0
-#include <libmemcached/exception.hpp>
-#endif
-
-#include <string.h>
-
-#include <sstream>
-#include <string>
-#include <vector>
-#include <map>
-
-namespace memcache
-{
-
-/**
- * This is the core memcached library (if later, other objects
- * are needed, they will be created from this class).
- */
-class Memcache
-{
-public:
-
-  Memcache()
-  {
-    memc_= memcached(NULL, 0);
-  }
-
-  Memcache(const std::string &config)
-  {
-    memc_= memcached(config.c_str(), config.size());
-  }
-
-  Memcache(const std::string &hostname, in_port_t port)
-  {
-    memc_= memcached(NULL, 0);
-    if (memc_)
-    {
-      memcached_server_add(memc_, hostname.c_str(), port);
-    }
-  }
-
-  Memcache(memcached_st *clone)
-  {
-    memc_= memcached_clone(NULL, clone);
-  }
-
-  Memcache(const Memcache &rhs)
-  {
-    memc_= memcached_clone(NULL, rhs.getImpl());
-  }
-
-  Memcache &operator=(const Memcache &rhs)
-  {
-    if (this != &rhs)
-    {
-      memcached_free(memc_);
-      memc_= memcached_clone(NULL, rhs.getImpl());
-    }
-
-    return *this;
-  }
-
-  ~Memcache()
-  {
-    memcached_free(memc_);
-  }
-
-  /**
-   * Get the internal memcached_st *
-   */
-  const memcached_st *getImpl() const
-  {
-    return memc_;
-  }
-
-  /**
-   * Return an error string for the given return structure.
-   *
-   * @param[in] rc a memcached_return_t structure
-   * @return error string corresponding to given return code in the library.
-   */
-  const std::string getError(memcached_return_t rc) const
-  {
-    /* first parameter to strerror is unused */
-    return memcached_strerror(NULL, rc);
-  }
-
-  bool error(std::string& error_message) const
-  {
-    if (memcached_failed(memcached_last_error(memc_)))
-    {
-      error_message+= memcached_last_error_message(memc_);
-      return true;
-    }
-
-    return false;
-  }
-
-  bool error() const
-  {
-    if (memcached_failed(memcached_last_error(memc_)))
-    {
-      return true;
-    }
-
-    return false;
-  }
-
-  bool error(memcached_return_t& arg) const
-  {
-    arg= memcached_last_error(memc_);
-    return memcached_failed(arg);
-  }
-
-  bool setBehavior(memcached_behavior_t flag, uint64_t data)
-  {
-    return (memcached_success(memcached_behavior_set(memc_, flag, data)));
-  }
-
-  uint64_t getBehavior(memcached_behavior_t flag)
-  {
-    return memcached_behavior_get(memc_, flag);
-  }
-
-  /**
-   * Configure the memcache object
-   *
-   * @param[in] in_config configuration
-   * @return true on success; false otherwise
-   */
-  bool configure(const std::string &configuration)
-  {
-    memcached_st *new_memc= memcached(configuration.c_str(), configuration.size());
-
-    if (new_memc)
-    {
-      memcached_free(memc_);
-      memc_= new_memc;
-
-      return true;
-    }
-
-    return false;
-  }
-
-  /**
-   * Add a server to the list of memcached servers to use.
-   *
-   * @param[in] server_name name of the server to add
-   * @param[in] port port number of server to add
-   * @return true on success; false otherwise
-   */
-  bool addServer(const std::string &server_name, in_port_t port)
-  {
-    return memcached_success(memcached_server_add(memc_, server_name.c_str(), port));
-  }
-
-  /**
-   * Remove a server from the list of memcached servers to use.
-   *
-   * @param[in] server_name name of the server to remove
-   * @param[in] port port number of server to remove
-   * @return true on success; false otherwise
-   */
-  bool removeServer(const std::string &server_name, in_port_t port)
-  {
-    std::string tmp_str;
-    std::ostringstream strstm;
-    tmp_str.append(",");
-    tmp_str.append(server_name);
-    tmp_str.append(":");
-    strstm << port;
-    tmp_str.append(strstm.str());
-
-    //memcached_return_t rc= memcached_server_remove(server);
-    
-    return false;
-  }
-
-  /**
-   * Fetches an individual value from the server. mget() must always
-   * be called before using this method.
-   *
-   * @param[in] key key of object to fetch
-   * @param[out] ret_val store returned object in this vector
-   * @return a memcached return structure
-   */
-  memcached_return_t fetch(std::string &key,
-                           std::vector<char> &ret_val,
-                           uint32_t &flags,
-                           uint64_t &cas_value)
-  {
-    memcached_return_t rc;
-
-    memcached_result_st *result;
-    if ((result= memcached_fetch_result(memc_, NULL, &rc)))
-    {
-      // Key
-      key.assign(memcached_result_key_value(result), memcached_result_key_length(result));
-
-      // Actual value, null terminated
-      ret_val.reserve(memcached_result_length(result) +1);
-      ret_val.assign(memcached_result_value(result),
-                     memcached_result_value(result) +memcached_result_length(result) +1);
-      ret_val.resize(memcached_result_length(result));
-
-      // Misc
-      flags= memcached_result_flags(result);
-      cas_value= memcached_result_cas(result);
-    }
-    memcached_result_free(result);
-
-    return rc;
-  }
-
-  memcached_return_t fetch(std::string &key,
-                           std::vector<char> &ret_val)
-  {
-    uint32_t flags= 0;
-    uint64_t cas_value= 0;
-
-    return fetch(key, ret_val, flags, cas_value);
-  }
-
-  /**
-   * Fetches an individual value from the server.
-   *
-   * @param[in] key key of object whose value to get
-   * @param[out] ret_val object that is retrieved is stored in
-   *                     this vector
-   * @return true on success; false otherwise
-   */
-  bool get(const std::string &key, std::vector<char> &ret_val)
-  {
-    uint32_t flags= 0;
-    memcached_return_t rc;
-    size_t value_length= 0;
-
-    char *value= memcached_get(memc_, key.c_str(), key.length(),
-                               &value_length, &flags, &rc);
-    if (value != NULL && ret_val.empty())
-    {
-      ret_val.reserve(value_length +1); // Always provide null
-      ret_val.assign(value, value +value_length +1);
-      ret_val.resize(value_length);
-      free(value);
-
-      return true;
-    }
-
-    return false;
-  }
-
-  /**
-   * Fetches an individual from a server which is specified by
-   * the master_key parameter that is used for determining which
-   * server an object was stored in if key partitioning was
-   * used for storage.
-   *
-   * @param[in] master_key key that specifies server object is stored on
-   * @param[in] key key of object whose value to get
-   * @param[out] ret_val object that is retrieved is stored in
-   *                     this vector
-   * @return true on success; false otherwise
-   */
-  bool getByKey(const std::string &master_key,
-                const std::string &key,
-                std::vector<char> &ret_val)
-  {
-    uint32_t flags= 0;
-    memcached_return_t rc;
-    size_t value_length= 0;
-
-    char *value= memcached_get_by_key(memc_,
-                                      master_key.c_str(), master_key.length(),
-                                      key.c_str(), key.length(),
-                                      &value_length, &flags, &rc);
-    if (value)
-    {
-      ret_val.reserve(value_length +1); // Always provide null
-      ret_val.assign(value, value +value_length +1);
-      ret_val.resize(value_length);
-      free(value);
-
-      return true;
-    }
-    return false;
-  }
-
-  /**
-   * Selects multiple keys at once. This method always
-   * works asynchronously.
-   *
-   * @param[in] keys vector of keys to select
-   * @return true if all keys are found
-   */
-  bool mget(const std::vector<std::string>& keys)
-  {
-    std::vector<const char *> real_keys;
-    std::vector<size_t> key_len;
-    /*
-     * Construct an array which will contain the length
-     * of each of the strings in the input vector. Also, to
-     * interface with the memcached C API, we need to convert
-     * the vector of std::string's to a vector of char *.
-     */
-    real_keys.reserve(keys.size());
-    key_len.reserve(keys.size());
-
-    std::vector<std::string>::const_iterator it= keys.begin();
-
-    while (it != keys.end())
-    {
-      real_keys.push_back(const_cast<char *>((*it).c_str()));
-      key_len.push_back((*it).length());
-      ++it;
-    }
-
-    /*
-     * If the std::vector of keys is empty then we cannot
-     * call memcached_mget as we will get undefined behavior.
-     */
-    if (not real_keys.empty())
-    {
-      return memcached_success(memcached_mget(memc_, &real_keys[0], &key_len[0], real_keys.size()));
-    }
-
-    return false;
-  }
-
-  /**
-   * Writes an object to the server. If the object already exists, it will
-   * overwrite the existing object. This method always returns true
-   * when using non-blocking mode unless a network error occurs.
-   *
-   * @param[in] key key of object to write to server
-   * @param[in] value value of object to write to server
-   * @param[in] expiration time to keep the object stored in the server for
-   * @param[in] flags flags to store with the object
-   * @return true on succcess; false otherwise
-   */
-  bool set(const std::string &key,
-           const std::vector<char> &value,
-           time_t expiration,
-           uint32_t flags)
-  {
-    memcached_return_t rc= memcached_set(memc_,
-                                         key.c_str(), key.length(),
-                                         value.data(), value.size(),
-                                         expiration, flags);
-    return memcached_success(rc);
-  }
-
-  bool set(const std::string &key,
-           const char* value, const size_t value_length,
-           time_t expiration,
-           uint32_t flags)
-  {
-    memcached_return_t rc= memcached_set(memc_,
-                                         key.c_str(), key.length(),
-                                         value, value_length,
-                                         expiration, flags);
-    return memcached_success(rc);
-  }
-
-  /**
-   * Writes an object to a server specified by the master_key parameter.
-   * If the object already exists, it will overwrite the existing object.
-   *
-   * @param[in] master_key key that specifies server to write to
-   * @param[in] key key of object to write to server
-   * @param[in] value value of object to write to server
-   * @param[in] expiration time to keep the object stored in the server for
-   * @param[in] flags flags to store with the object
-   * @return true on succcess; false otherwise
-   */
-  bool setByKey(const std::string& master_key,
-                const std::string& key,
-                const std::vector<char> &value,
-                time_t expiration,
-                uint32_t flags)
-  {
-    return memcached_success(memcached_set_by_key(memc_, master_key.c_str(),
-                                                  master_key.length(),
-                                                  key.c_str(), key.length(),
-                                                  &value[0], value.size(),
-                                                  expiration,
-                                                  flags));
-  }
-
-  /**
-   * Writes a list of objects to the server. Objects are specified by
-   * 2 vectors - 1 vector of keys and 1 vector of values.
-   *
-   * @param[in] keys vector of keys of objects to write to server
-   * @param[in] values vector of values of objects to write to server
-   * @param[in] expiration time to keep the objects stored in server for
-   * @param[in] flags flags to store with the objects
-   * @return true on success; false otherwise
-   */
-  bool setAll(const std::vector<std::string>& keys,
-              const std::vector< std::vector<char> *>& values,
-              time_t expiration,
-              uint32_t flags)
-  {
-    bool retval= true;
-    std::vector<std::string>::const_iterator key_it= keys.begin();
-    std::vector< std::vector<char> *>::const_iterator val_it= values.begin();
-    while (key_it != keys.end())
-    {
-      retval= set((*key_it), *(*val_it), expiration, flags);
-      if (retval == false)
-      {
-        return retval;
-      }
-      ++key_it;
-      ++val_it;
-    }
-    return retval;
-  }
-
-  /**
-   * Writes a list of objects to the server. Objects are specified by
-   * a map of keys to values.
-   *
-   * @param[in] key_value_map map of keys and values to store in server
-   * @param[in] expiration time to keep the objects stored in server for
-   * @param[in] flags flags to store with the objects
-   * @return true on success; false otherwise
-   */
-  bool setAll(const std::map<const std::string, std::vector<char> >& key_value_map,
-              time_t expiration,
-              uint32_t flags)
-  {
-    std::map<const std::string, std::vector<char> >::const_iterator it= key_value_map.begin();
-
-    while (it != key_value_map.end())
-    {
-      if (!set(it->first, it->second, expiration, flags))
-      {
-        // We should tell the user what the key that failed was
-        return false;
-      }
-      ++it;
-    }
-
-    return true;
-  }
-
-  /**
-   * Increment the value of the object associated with the specified
-   * key by the offset given. The resulting value is saved in the value
-   * parameter.
-   *
-   * @param[in] key key of object in server whose value to increment
-   * @param[in] offset amount to increment object's value by
-   * @param[out] value store the result of the increment here
-   * @return true on success; false otherwise
-   */
-  bool increment(const std::string& key, uint32_t offset, uint64_t *value)
-  {
-    return memcached_success(memcached_increment(memc_, key.c_str(), key.length(), offset, value));
-  }
-
-  /**
-   * Decrement the value of the object associated with the specified
-   * key by the offset given. The resulting value is saved in the value
-   * parameter.
-   *
-   * @param[in] key key of object in server whose value to decrement
-   * @param[in] offset amount to increment object's value by
-   * @param[out] value store the result of the decrement here
-   * @return true on success; false otherwise
-   */
-  bool decrement(const std::string& key, uint32_t offset, uint64_t *value)
-  {
-    return memcached_success(memcached_decrement(memc_, key.c_str(),
-                                                 key.length(),
-                                                 offset, value));
-  }
-
-
-  /**
-   * Add an object with the specified key and value to the server. This
-   * function returns false if the object already exists on the server.
-   *
-   * @param[in] key key of object to add
-   * @param[in] value of object to add
-   * @return true on success; false otherwise
-   */
-  bool add(const std::string& key, const std::vector<char>& value)
-  {
-    return memcached_success(memcached_add(memc_, key.c_str(), key.length(),
-                                           &value[0], value.size(), 0, 0));
-  }
-
-  /**
-   * Add an object with the specified key and value to the server. This
-   * function returns false if the object already exists on the server. The
-   * server to add the object to is specified by the master_key parameter.
-   *
-   * @param[in[ master_key key of server to add object to
-   * @param[in] key key of object to add
-   * @param[in] value of object to add
-   * @return true on success; false otherwise
-   */
-  bool addByKey(const std::string& master_key,
-                const std::string& key,
-                const std::vector<char>& value)
-  {
-    return memcached_success(memcached_add_by_key(memc_,
-                                                  master_key.c_str(),
-                                                  master_key.length(),
-                                                  key.c_str(),
-                                                  key.length(),
-                                                  &value[0],
-                                                  value.size(),
-                                                  0, 0));
-  }
-
-  /**
-   * Replaces an object on the server. This method only succeeds
-   * if the object is already present on the server.
-   *
-   * @param[in] key key of object to replace
-   * @param[in[ value value to replace object with
-   * @return true on success; false otherwise
-   */
-  bool replace(const std::string& key, const std::vector<char>& value)
-  {
-    return memcached_success(memcached_replace(memc_, key.c_str(), key.length(),
-                                               &value[0], value.size(),
-                                               0, 0));
-  }
-
-  /**
-   * Replaces an object on the server. This method only succeeds
-   * if the object is already present on the server. The server
-   * to replace the object on is specified by the master_key param.
-   *
-   * @param[in] master_key key of server to replace object on
-   * @param[in] key key of object to replace
-   * @param[in[ value value to replace object with
-   * @return true on success; false otherwise
-   */
-  bool replaceByKey(const std::string& master_key,
-                    const std::string& key,
-                    const std::vector<char>& value)
-  {
-    return memcached_success(memcached_replace_by_key(memc_,
-                                                      master_key.c_str(),
-                                                      master_key.length(),
-                                                      key.c_str(),
-                                                      key.length(),
-                                                      &value[0],
-                                                      value.size(),
-                                                      0, 0));
-  }
-
-  /**
-   * Places a segment of data before the last piece of data stored.
-   *
-   * @param[in] key key of object whose value we will prepend data to
-   * @param[in] value data to prepend to object's value
-   * @return true on success; false otherwise
-   */
-  bool prepend(const std::string& key, const std::vector<char>& value)
-  {
-    return memcached_success(memcached_prepend(memc_, key.c_str(), key.length(),
-                                               &value[0], value.size(), 0, 0));
-  }
-
-  /**
-   * Places a segment of data before the last piece of data stored. The
-   * server on which the object where we will be prepending data is stored
-   * on is specified by the master_key parameter.
-   *
-   * @param[in] master_key key of server where object is stored
-   * @param[in] key key of object whose value we will prepend data to
-   * @param[in] value data to prepend to object's value
-   * @return true on success; false otherwise
-   */
-  bool prependByKey(const std::string& master_key,
-                    const std::string& key,
-                    const std::vector<char>& value)
-  {
-    return memcached_success(memcached_prepend_by_key(memc_,
-                                                      master_key.c_str(),
-                                                      master_key.length(),
-                                                      key.c_str(),
-                                                      key.length(),
-                                                      &value[0],
-                                                      value.size(),
-                                                      0,
-                                                      0));
-  }
-
-  /**
-   * Places a segment of data at the end of the last piece of data stored.
-   *
-   * @param[in] key key of object whose value we will append data to
-   * @param[in] value data to append to object's value
-   * @return true on success; false otherwise
-   */
-  bool append(const std::string& key, const std::vector<char>& value)
-  {
-    return memcached_success(memcached_append(memc_,
-                                              key.c_str(),
-                                              key.length(),
-                                              &value[0],
-                                              value.size(),
-                                              0, 0));
-  }
-
-  /**
-   * Places a segment of data at the end of the last piece of data stored. The
-   * server on which the object where we will be appending data is stored
-   * on is specified by the master_key parameter.
-   *
-   * @param[in] master_key key of server where object is stored
-   * @param[in] key key of object whose value we will append data to
-   * @param[in] value data to append to object's value
-   * @return true on success; false otherwise
-   */
-  bool appendByKey(const std::string& master_key,
-                   const std::string& key,
-                   const std::vector<char> &value)
-  {
-    return memcached_success(memcached_append_by_key(memc_,
-                                                     master_key.c_str(),
-                                                     master_key.length(),
-                                                     key.c_str(),
-                                                     key.length(),
-                                                     &value[0],
-                                                     value.size(),
-                                                     0, 0));
-  }
-
-  /**
-   * Overwrite data in the server as long as the cas_arg value
-   * is still the same in the server.
-   *
-   * @param[in] key key of object in server
-   * @param[in] value value to store for object in server
-   * @param[in] cas_arg "cas" value
-   */
-  bool cas(const std::string& key,
-           const std::vector<char>& value,
-           uint64_t cas_arg)
-  {
-    return memcached_success(memcached_cas(memc_, key.c_str(), key.length(),
-                                           &value[0], value.size(),
-                                           0, 0, cas_arg));
-  }
-
-  /**
-   * Overwrite data in the server as long as the cas_arg value
-   * is still the same in the server. The server to use is
-   * specified by the master_key parameter.
-   *
-   * @param[in] master_key specifies server to operate on
-   * @param[in] key key of object in server
-   * @param[in] value value to store for object in server
-   * @param[in] cas_arg "cas" value
-   */
-  bool casByKey(const std::string& master_key,
-                const std::string& key,
-                const std::vector<char> &value,
-                uint64_t cas_arg)
-  {
-    return memcached_success(memcached_cas_by_key(memc_,
-                                                  master_key.c_str(),
-                                                  master_key.length(),
-                                                  key.c_str(),
-                                                  key.length(),
-                                                  &value[0],
-                                                  value.size(),
-                                                  0, 0, cas_arg));
-  }
-
-  /**
-   * Delete an object from the server specified by the key given.
-   *
-   * @param[in] key key of object to delete
-   * @return true on success; false otherwise
-   */
-  bool remove(const std::string& key)
-  {
-    return memcached_success(memcached_delete(memc_, key.c_str(), key.length(), 0));
-  }
-
-  /**
-   * Delete an object from the server specified by the key given.
-   *
-   * @param[in] key key of object to delete
-   * @param[in] expiration time to delete the object after
-   * @return true on success; false otherwise
-   */
-  bool remove(const std::string& key, time_t expiration)
-  {
-    return memcached_success(memcached_delete(memc_,
-                                              key.c_str(),
-                                              key.length(),
-                                              expiration));
-  }
-
-  /**
-   * Delete an object from the server specified by the key given.
-   *
-   * @param[in] master_key specifies server to remove object from
-   * @param[in] key key of object to delete
-   * @return true on success; false otherwise
-   */
-  bool removeByKey(const std::string& master_key,
-                   const std::string& key)
-  {
-    return memcached_success(memcached_delete_by_key(memc_,
-                                                     master_key.c_str(),
-                                                     master_key.length(),
-                                                     key.c_str(),
-                                                     key.length(),
-                                                     0));
-  }
-
-  /**
-   * Delete an object from the server specified by the key given.
-   *
-   * @param[in] master_key specifies server to remove object from
-   * @param[in] key key of object to delete
-   * @param[in] expiration time to delete the object after
-   * @return true on success; false otherwise
-   */
-  bool removeByKey(const std::string& master_key,
-                   const std::string& key,
-                   time_t expiration)
-  {
-    return memcached_success(memcached_delete_by_key(memc_,
-                                                     master_key.c_str(),
-                                                     master_key.length(),
-                                                     key.c_str(),
-                                                     key.length(),
-                                                     expiration));
-  }
-
-  /**
-   * Wipe the contents of memcached servers.
-   *
-   * @param[in] expiration time to wait until wiping contents of
-   *                       memcached servers
-   * @return true on success; false otherwise
-   */
-  bool flush(time_t expiration= 0)
-  {
-    return memcached_success(memcached_flush(memc_, expiration));
-  }
-
-  /**
-   * Get the library version string.
-   * @return std::string containing a copy of the library version string.
-   */
-  const std::string libVersion() const
-  {
-    const char *ver= memcached_lib_version();
-    const std::string version(ver);
-    return version;
-  }
-
-  /**
-   * Retrieve memcached statistics. Populate a std::map with the retrieved
-   * stats. Each server will map to another std::map of the key:value stats.
-   *
-   * @param[out] stats_map a std::map to be populated with the memcached
-   *                       stats
-   * @return true on success; false otherwise
-   */
-  bool getStats(std::map< std::string, std::map<std::string, std::string> >& stats_map)
-  {
-    memcached_return_t rc;
-    memcached_stat_st *stats= memcached_stat(memc_, NULL, &rc);
-
-    if (rc != MEMCACHED_SUCCESS &&
-        rc != MEMCACHED_SOME_ERRORS)
-    {
-      return false;
-    }
-
-    uint32_t server_count= memcached_server_count(memc_);
-
-    /*
-     * For each memcached server, construct a std::map for its stats and add
-     * it to the std::map of overall stats.
-     */
-    for (uint32_t x= 0; x < server_count; x++)
-    {
-      const memcached_instance_st * instance= memcached_server_instance_by_position(memc_, x);
-      std::ostringstream strstm;
-      std::string server_name(memcached_server_name(instance));
-      server_name.append(":");
-      strstm << memcached_server_port(instance);
-      server_name.append(strstm.str());
-
-      std::map<std::string, std::string> server_stats;
-      char **list= memcached_stat_get_keys(memc_, &stats[x], &rc);
-      for (char** ptr= list; *ptr; ptr++)
-      {
-        char *value= memcached_stat_get_value(memc_, &stats[x], *ptr, &rc);
-        server_stats[*ptr]= value;
-        free(value);
-      }
-     
-      stats_map[server_name]= server_stats;
-      free(list);
-    }
-
-    memcached_stat_free(memc_, stats);
-    return true;
-  }
-
-private:
-  memcached_st *memc_;
-};
-
-}
diff --git a/libmemcached-1.0/options.h b/libmemcached-1.0/options.h
deleted file mode 100644 (file)
index f5a6e06..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-  memcached_return_t libmemcached_check_configuration(const char *option_string, size_t length, char *error_buffer, size_t error_buffer_size);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/parse.h b/libmemcached-1.0/parse.h
deleted file mode 100644 (file)
index a91f769..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2010 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Work with fetching results
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_server_list_st memcached_servers_parse(const char *server_strings);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/platform.h b/libmemcached-1.0/platform.h
deleted file mode 100644 (file)
index efdf53f..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#if defined(_WIN32)
-# include <winsock2.h>
-# include <ws2tcpip.h>
-
-#ifndef HAVE_IN_PORT_T
-typedef int in_port_t;
-# define HAVE_IN_PORT_T 1
-#endif
-
-typedef SOCKET memcached_socket_t;
-
-#else
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-# include <netdb.h>
-# include <sys/un.h>
-# include <netinet/tcp.h>
-
-typedef int memcached_socket_t;
-
-#endif /* _WIN32 */
diff --git a/libmemcached-1.0/quit.h b/libmemcached-1.0/quit.h
deleted file mode 100644 (file)
index 90ff3ff..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-void memcached_quit(memcached_st *ptr);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/result.h b/libmemcached-1.0/result.h
deleted file mode 100644 (file)
index 615957f..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached-1.0/struct/result.h>
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Result Struct */
-LIBMEMCACHED_API
-void memcached_result_free(memcached_result_st *result);
-
-LIBMEMCACHED_API
-void memcached_result_reset(memcached_result_st *ptr);
-
-LIBMEMCACHED_API
-memcached_result_st *memcached_result_create(const memcached_st *ptr,
-                                             memcached_result_st *result);
-
-LIBMEMCACHED_API
-const char *memcached_result_key_value(const memcached_result_st *self);
-
-LIBMEMCACHED_API
-size_t memcached_result_key_length(const memcached_result_st *self);
-
-LIBMEMCACHED_API
-const char *memcached_result_value(const memcached_result_st *self);
-
-LIBMEMCACHED_API
-char *memcached_result_take_value(memcached_result_st *self);
-
-LIBMEMCACHED_API
-size_t memcached_result_length(const memcached_result_st *self);
-
-LIBMEMCACHED_API
-uint32_t memcached_result_flags(const memcached_result_st *self);
-
-LIBMEMCACHED_API
-uint64_t memcached_result_cas(const memcached_result_st *self);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_result_set_value(memcached_result_st *ptr, const char *value, size_t length);
-
-LIBMEMCACHED_API
-void memcached_result_set_flags(memcached_result_st *self, uint32_t flags);
-
-LIBMEMCACHED_API
-void memcached_result_set_expiration(memcached_result_st *self, time_t expiration);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/libmemcached-1.0/return.h b/libmemcached-1.0/return.h
deleted file mode 100644 (file)
index e2b4104..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-static inline bool memcached_success(memcached_return_t rc)
-{
-  return (rc == MEMCACHED_BUFFERED ||
-          rc == MEMCACHED_DELETED ||
-          rc == MEMCACHED_END || 
-          rc == MEMCACHED_ITEM || 
-          rc == MEMCACHED_STAT || 
-          rc == MEMCACHED_STORED || 
-          rc == MEMCACHED_SUCCESS || 
-          rc == MEMCACHED_VALUE);
-}
-
-static inline bool memcached_failed(memcached_return_t rc)
-{
-  return (rc != MEMCACHED_AUTH_CONTINUE &&
-          rc != MEMCACHED_BUFFERED &&
-          rc != MEMCACHED_DELETED &&
-          rc != MEMCACHED_END && 
-          rc != MEMCACHED_ITEM &&
-          rc != MEMCACHED_STAT &&
-          rc != MEMCACHED_STORED && 
-          rc != MEMCACHED_SUCCESS &&
-          rc != MEMCACHED_VALUE);
-}
-
-static inline bool memcached_fatal(memcached_return_t rc)
-{
-  return (rc != MEMCACHED_AUTH_CONTINUE &&
-          rc != MEMCACHED_BUFFERED &&
-          rc != MEMCACHED_CLIENT_ERROR &&
-          rc != MEMCACHED_DATA_EXISTS &&
-          rc != MEMCACHED_DELETED &&
-          rc != MEMCACHED_E2BIG && 
-          rc != MEMCACHED_END && 
-          rc != MEMCACHED_ITEM &&
-          rc != MEMCACHED_ERROR &&
-          rc != MEMCACHED_NOTFOUND && 
-          rc != MEMCACHED_NOTSTORED && 
-          rc != MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE && 
-          rc != MEMCACHED_STAT && 
-          rc != MEMCACHED_STORED && 
-          rc != MEMCACHED_SUCCESS && 
-          rc != MEMCACHED_VALUE);
-}
-
-#define memcached_continue(__memcached_return_t) ((__memcached_return_t) == MEMCACHED_IN_PROGRESS)
diff --git a/libmemcached-1.0/sasl.h b/libmemcached-1.0/sasl.h
deleted file mode 100644 (file)
index c308421..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
-#include <sasl/sasl.h>
-#else
-#define sasl_callback_t void
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-void memcached_set_sasl_callbacks(memcached_st *ptr,
-                                  const sasl_callback_t *callbacks);
-
-LIBMEMCACHED_API
-memcached_return_t  memcached_set_sasl_auth_data(memcached_st *ptr,
-                                                 const char *username,
-                                                 const char *password);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *ptr);
-
-
-LIBMEMCACHED_API
-sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *ptr);
-
-#ifdef __cplusplus
-}
-#endif
-
-#include <libmemcached-1.0/struct/sasl.h>
diff --git a/libmemcached-1.0/server.h b/libmemcached-1.0/server.h
deleted file mode 100644 (file)
index abd0bfb..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#include <libmemcached-1.0/struct/server.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_server_cursor(const memcached_st *ptr,
-                                           const memcached_server_fn *callback,
-                                           void *context,
-                                           uint32_t number_of_callbacks);
-
-LIBMEMCACHED_API
-  const memcached_instance_st * memcached_server_by_key(memcached_st *ptr,
-                                                       const char *key,
-                                                       size_t key_length,
-                                                       memcached_return_t *error);
-
-LIBMEMCACHED_API
-void memcached_server_error_reset(memcached_server_st *ptr);
-
-LIBMEMCACHED_API
-void memcached_server_free(memcached_server_st *ptr);
-
-LIBMEMCACHED_API
-const memcached_instance_st * memcached_server_get_last_disconnect(const memcached_st *ptr);
-
-
-LIBMEMCACHED_API
-memcached_return_t memcached_server_add_udp(memcached_st *ptr,
-                                            const char *hostname,
-                                            in_port_t port);
-LIBMEMCACHED_API
-memcached_return_t memcached_server_add_unix_socket(memcached_st *ptr,
-                                                    const char *filename);
-LIBMEMCACHED_API
-memcached_return_t memcached_server_add(memcached_st *ptr,
-                                        const char *hostname, in_port_t port);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_server_add_udp_with_weight(memcached_st *ptr,
-                                                        const char *hostname,
-                                                        in_port_t port,
-                                                        uint32_t weight);
-LIBMEMCACHED_API
-memcached_return_t memcached_server_add_unix_socket_with_weight(memcached_st *ptr,
-                                                                const char *filename,
-                                                                uint32_t weight);
-LIBMEMCACHED_API
-memcached_return_t memcached_server_add_with_weight(memcached_st *ptr, const char *hostname,
-                                                    in_port_t port,
-                                                    uint32_t weight);
-
-/**
-  Operations on Single Servers.
-*/
-LIBMEMCACHED_API
-uint32_t memcached_server_response_count(const memcached_instance_st * self);
-
-LIBMEMCACHED_API
-const char *memcached_server_name(const memcached_instance_st * self);
-
-LIBMEMCACHED_API
-in_port_t memcached_server_port(const memcached_instance_st * self);
-
-LIBMEMCACHED_API
-in_port_t memcached_server_srcport(const memcached_instance_st * self);
-
-LIBMEMCACHED_API
-void memcached_instance_next_retry(const memcached_instance_st * self, const time_t absolute_time);
-
-LIBMEMCACHED_API
-const char *memcached_server_type(const memcached_instance_st * ptr);
-
-LIBMEMCACHED_API
-uint8_t memcached_server_major_version(const memcached_instance_st * ptr);
-
-LIBMEMCACHED_API
-uint8_t memcached_server_minor_version(const memcached_instance_st * ptr);
-
-LIBMEMCACHED_API
-uint8_t memcached_server_micro_version(const memcached_instance_st * ptr);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/libmemcached-1.0/server_list.h b/libmemcached-1.0/server_list.h
deleted file mode 100644 (file)
index 04bebab..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Server List Public functions */
-LIBMEMCACHED_API
-  void memcached_server_list_free(memcached_server_list_st ptr);
-
-LIBMEMCACHED_API
-  memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_server_list_st list);
-
-LIBMEMCACHED_API
-  memcached_server_list_st memcached_server_list_append(memcached_server_list_st ptr,
-                                                        const char *hostname,
-                                                        in_port_t port,
-                                                        memcached_return_t *error);
-LIBMEMCACHED_API
-  memcached_server_list_st memcached_server_list_append_with_weight(memcached_server_list_st ptr,
-                                                                    const char *hostname,
-                                                                    in_port_t port,
-                                                                    uint32_t weight,
-                                                                    memcached_return_t *error);
-LIBMEMCACHED_API
-  uint32_t memcached_server_list_count(const memcached_server_list_st ptr);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/libmemcached-1.0/stats.h b/libmemcached-1.0/stats.h
deleted file mode 100644 (file)
index 708064f..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached-1.0/struct/stat.h>
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-void memcached_stat_free(const memcached_st *, memcached_stat_st *);
-
-LIBMEMCACHED_API
-memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_stat_servername(memcached_stat_st *memc_stat, char *args,
-                                             const char *hostname, in_port_t port);
-
-LIBMEMCACHED_API
-char *memcached_stat_get_value(const memcached_st *ptr, memcached_stat_st *memc_stat,
-                               const char *key, memcached_return_t *error);
-
-LIBMEMCACHED_API
-char ** memcached_stat_get_keys(memcached_st *ptr, memcached_stat_st *memc_stat,
-                                memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_stat_execute(memcached_st *memc, const char *args,  memcached_stat_fn func, void *context);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/libmemcached-1.0/storage.h b/libmemcached-1.0/storage.h
deleted file mode 100644 (file)
index e634235..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* All of the functions for adding data to the server */
-LIBMEMCACHED_API
-memcached_return_t memcached_set(memcached_st *ptr, const char *key, size_t key_length,
-                                 const char *value, size_t value_length,
-                                 time_t expiration,
-                                 uint32_t  flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_add(memcached_st *ptr, const char *key, size_t key_length,
-                                 const char *value, size_t value_length,
-                                 time_t expiration,
-                                 uint32_t  flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_replace(memcached_st *ptr, const char *key, size_t key_length,
-                                     const char *value, size_t value_length,
-                                     time_t expiration,
-                                     uint32_t  flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_append(memcached_st *ptr,
-                                    const char *key, size_t key_length,
-                                    const char *value, size_t value_length,
-                                    time_t expiration,
-                                    uint32_t flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_prepend(memcached_st *ptr,
-                                     const char *key, size_t key_length,
-                                     const char *value, size_t value_length,
-                                     time_t expiration,
-                                     uint32_t flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_cas(memcached_st *ptr,
-                                 const char *key, size_t key_length,
-                                 const char *value, size_t value_length,
-                                 time_t expiration,
-                                 uint32_t flags,
-                                 uint64_t cas);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_set_by_key(memcached_st *ptr,
-                                        const char *group_key, size_t group_key_length,
-                                        const char *key, size_t key_length,
-                                        const char *value, size_t value_length,
-                                        time_t expiration,
-                                        uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_add_by_key(memcached_st *ptr,
-                                        const char *group_key, size_t group_key_length,
-                                        const char *key, size_t key_length,
-                                        const char *value, size_t value_length,
-                                        time_t expiration,
-                                        uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_replace_by_key(memcached_st *ptr,
-                                            const char *group_key, size_t group_key_length,
-                                            const char *key, size_t key_length,
-                                            const char *value, size_t value_length,
-                                            time_t expiration,
-                                            uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_prepend_by_key(memcached_st *ptr,
-                                            const char *group_key, size_t group_key_length,
-                                            const char *key, size_t key_length,
-                                            const char *value, size_t value_length,
-                                            time_t expiration,
-                                            uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_append_by_key(memcached_st *ptr,
-                                           const char *group_key, size_t group_key_length,
-                                           const char *key, size_t key_length,
-                                           const char *value, size_t value_length,
-                                           time_t expiration,
-                                           uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_cas_by_key(memcached_st *ptr,
-                                        const char *group_key, size_t group_key_length,
-                                        const char *key, size_t key_length,
-                                        const char *value, size_t value_length,
-                                        time_t expiration,
-                                        uint32_t flags,
-                                        uint64_t cas);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/strerror.h b/libmemcached-1.0/strerror.h
deleted file mode 100644 (file)
index 16bf424..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-const char *memcached_strerror(const memcached_st *ptr, memcached_return_t rc);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/struct/allocator.h b/libmemcached-1.0/struct/allocator.h
deleted file mode 100644 (file)
index 3ff6ade..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-struct memcached_allocator_t {
-  memcached_calloc_fn calloc;
-  memcached_free_fn free;
-  memcached_malloc_fn malloc;
-  memcached_realloc_fn realloc;
-  void *context;
-};
diff --git a/libmemcached-1.0/struct/analysis.h b/libmemcached-1.0/struct/analysis.h
deleted file mode 100644 (file)
index 09ccced..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-struct memcached_analysis_st {
-  memcached_st *root;
-  uint32_t average_item_size;
-  uint32_t longest_uptime;
-  uint32_t least_free_server;
-  uint32_t most_consumed_server;
-  uint32_t oldest_server;
-  double pool_hit_ratio;
-  uint64_t most_used_bytes;
-  uint64_t least_remaining_bytes;
-};
-
diff --git a/libmemcached-1.0/struct/callback.h b/libmemcached-1.0/struct/callback.h
deleted file mode 100644 (file)
index 21b9676..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-struct memcached_callback_st {
-  memcached_execute_fn *callback;
-  void *context;
-  uint32_t number_of_callback;
-};
diff --git a/libmemcached-1.0/struct/memcached.h b/libmemcached-1.0/struct/memcached.h
deleted file mode 100644 (file)
index a368bfe..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-struct memcached_st {
-  /**
-    @note these are static and should not change without a call to behavior.
-  */
-  struct {
-    bool is_purging:1;
-    bool is_processing_input:1;
-    bool is_time_for_rebuild:1;
-    bool is_parsing:1;
-  } state;
-
-  struct {
-    // Everything below here is pretty static.
-    bool auto_eject_hosts:1;
-    bool binary_protocol:1;
-    bool buffer_requests:1;
-    bool hash_with_namespace:1;
-    bool no_block:1; // Don't block
-    bool reply:1;
-    bool randomize_replica_read:1;
-    bool support_cas:1;
-    bool tcp_nodelay:1;
-    bool use_sort_hosts:1;
-    bool use_udp:1;
-    bool verify_key:1;
-    bool tcp_keepalive:1;
-    bool is_aes:1;
-    bool is_fetching_version:1;
-    bool not_used:1;
-  } flags;
-
-  memcached_server_distribution_t distribution;
-  hashkit_st hashkit;
-  struct {
-    unsigned int version;
-  } server_info;
-  uint32_t number_of_hosts;
-  memcached_instance_st *servers;
-  memcached_instance_st *last_disconnected_server;
-  int32_t snd_timeout;
-  int32_t rcv_timeout;
-  uint32_t server_failure_limit;
-  uint32_t server_timeout_limit;
-  uint32_t io_msg_watermark;
-  uint32_t io_bytes_watermark;
-  uint32_t io_key_prefetch;
-  uint32_t tcp_keepidle;
-  int32_t poll_timeout;
-  int32_t connect_timeout; // How long we will wait on connect() before we will timeout
-  int32_t retry_timeout;
-  int32_t dead_timeout;
-  int send_size;
-  int recv_size;
-  void *user_data;
-  uint64_t query_id;
-  uint32_t number_of_replicas;
-  memcached_result_st result;
-
-  struct {
-    bool weighted_;
-    uint32_t continuum_count; // Ketama
-    uint32_t continuum_points_counter; // Ketama
-    time_t next_distribution_rebuild; // Ketama
-    struct memcached_continuum_item_st *continuum; // Ketama
-  } ketama;
-
-  struct memcached_virtual_bucket_t *virtual_bucket;
-
-  struct memcached_allocator_t allocators;
-
-  memcached_clone_fn on_clone;
-  memcached_cleanup_fn on_cleanup;
-  memcached_trigger_key_fn get_key_failure;
-  memcached_trigger_delete_key_fn delete_trigger;
-  memcached_callback_st *callbacks;
-  struct memcached_sasl_st sasl;
-  struct memcached_error_t *error_messages;
-  struct memcached_array_st *_namespace;
-  struct {
-    uint32_t initial_pool_size;
-    uint32_t max_pool_size;
-    int32_t version; // This is used by pool and others to determine if the memcached_st is out of date.
-    struct memcached_array_st *filename;
-  } configure;
-  struct {
-    bool is_allocated:1;
-  } options;
-
-};
diff --git a/libmemcached-1.0/struct/result.h b/libmemcached-1.0/struct/result.h
deleted file mode 100644 (file)
index c3bfddb..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-struct memcached_result_st {
-  uint32_t item_flags;
-  time_t item_expiration;
-  size_t key_length;
-  uint64_t item_cas;
-  struct memcached_st *root;
-  memcached_string_st value;
-  uint64_t numeric_value;
-  uint64_t count;
-  char item_key[MEMCACHED_MAX_KEY];
-  struct {
-    bool is_allocated:1;
-    bool is_initialized:1;
-  } options;
-  /* Add result callback function */
-};
-
diff --git a/libmemcached-1.0/struct/sasl.h b/libmemcached-1.0/struct/sasl.h
deleted file mode 100644 (file)
index da9eed3..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
-#include <sasl/sasl.h>
-#else
-#define sasl_callback_t void
-#endif
-
-#pragma once
-
-struct memcached_sasl_st {
-  sasl_callback_t *callbacks;
-  /*
-   ** Did we allocate data inside the callbacks, or did the user
-   ** supply that.
- */
-  bool is_allocated;
-};
-
diff --git a/libmemcached-1.0/struct/server.h b/libmemcached-1.0/struct/server.h
deleted file mode 100644 (file)
index 9337938..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#ifdef HAVE_NETDB_H
-# include <netdb.h>
-#endif
-
-#ifdef NI_MAXHOST
-# define MEMCACHED_NI_MAXHOST NI_MAXHOST
-#else
-# define MEMCACHED_NI_MAXHOST 1025
-#endif
-
-#ifdef NI_MAXSERV
-# define MEMCACHED_NI_MAXSERV NI_MAXSERV
-#else
-# define MEMCACHED_NI_MAXSERV 32
-#endif
-
-enum memcached_server_state_t {
-  MEMCACHED_SERVER_STATE_NEW, // fd == -1, no address lookup has been done
-  MEMCACHED_SERVER_STATE_ADDRINFO, // ADDRRESS information has been gathered
-  MEMCACHED_SERVER_STATE_IN_PROGRESS,
-  MEMCACHED_SERVER_STATE_CONNECTED,
-  MEMCACHED_SERVER_STATE_IN_TIMEOUT,
-  MEMCACHED_SERVER_STATE_DISABLED
-};
-
-struct memcached_server_st {
-  struct {
-    bool is_allocated:1;
-    bool is_initialized:1;
-    bool is_shutting_down:1;
-    bool is_dead:1;
-  } options;
-  uint32_t number_of_hosts;
-  uint32_t cursor_active;
-  in_port_t port;
-  uint32_t io_bytes_sent; /* # bytes sent since last read */
-  uint32_t request_id;
-  uint32_t server_failure_counter;
-  uint64_t server_failure_counter_query_id;
-  uint32_t server_timeout_counter;
-  uint64_t server_timeout_counter_query_id;
-  uint32_t weight;
-  uint32_t version;
-  enum memcached_server_state_t state;
-  struct {
-    uint32_t read;
-    uint32_t write;
-    uint32_t timeouts;
-    size_t _bytes_read;
-  } io_wait_count;
-  uint8_t major_version; // Default definition of UINT8_MAX means that it has not been set.
-  uint8_t micro_version; // ditto, and note that this is the third, not second version bit
-  uint8_t minor_version; // ditto
-  memcached_connection_t type;
-  time_t next_retry;
-  struct memcached_st *root;
-  uint64_t limit_maxbytes;
-  struct memcached_error_t *error_messages;
-  char hostname[MEMCACHED_NI_MAXHOST];
-};
diff --git a/libmemcached-1.0/struct/stat.h b/libmemcached-1.0/struct/stat.h
deleted file mode 100644 (file)
index acd4e21..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-struct memcached_stat_st {
-  unsigned long connection_structures;
-  unsigned long curr_connections;
-  unsigned long curr_items;
-  pid_t pid;
-  unsigned long pointer_size;
-  unsigned long rusage_system_microseconds;
-  unsigned long rusage_system_seconds;
-  unsigned long rusage_user_microseconds;
-  unsigned long rusage_user_seconds;
-  unsigned long threads;
-  unsigned long time;
-  unsigned long total_connections;
-  unsigned long total_items;
-  unsigned long uptime;
-  unsigned long long bytes;
-  unsigned long long bytes_read;
-  unsigned long long bytes_written;
-  unsigned long long cmd_get;
-  unsigned long long cmd_set;
-  unsigned long long evictions;
-  unsigned long long get_hits;
-  unsigned long long get_misses;
-  unsigned long long limit_maxbytes;
-  char version[MEMCACHED_VERSION_STRING_LENGTH];
-  void *__future; // @todo create a new structure to place here for future usage
-  memcached_st *root;
-};
-
diff --git a/libmemcached-1.0/struct/string.h b/libmemcached-1.0/struct/string.h
deleted file mode 100644 (file)
index 9edb637..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-/**
-  Strings are always under our control so we make some assumptions
-  about them.
-
-  1) is_initialized is always valid.
-  2) A string once intialized will always be, until free where we
-     unset this flag.
-  3) A string always has a root.
-*/
-
-struct memcached_string_st {
-  char *end;
-  char *string;
-  size_t current_size;
-  struct memcached_st *root;
-  struct {
-    bool is_allocated:1;
-    bool is_initialized:1;
-  } options;
-};
diff --git a/libmemcached-1.0/t/c_sasl_test.c b/libmemcached-1.0/t/c_sasl_test.c
deleted file mode 100644 (file)
index 93f729d..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached C sasl test app
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * @file @brief C dummy test, aka testing C linking, etc
- */
-
-#include <stdlib.h>
-
-#ifdef HAVE_SASL_SASL_H
-#include <sasl/sasl.h>
-#endif
-
-#include <libmemcached-1.0/memcached.h>
-
-int main(void)
-{
-  memcached_st *memc= memcached_create(NULL);
-
-  if (memc == NULL)
-  {
-    return EXIT_FAILURE;
-  }
-  memcached_free(memc);
-
-  return EXIT_SUCCESS;
-}
-
diff --git a/libmemcached-1.0/t/c_test.c b/libmemcached-1.0/t/c_test.c
deleted file mode 100644 (file)
index 40935fa..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached C test app
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * @file @brief C dummy test, aka testing C linking, etc
- */
-
-#include <stdlib.h>
-
-#include <libmemcached-1.0/memcached.h>
-
-int main(void)
-{
-  (void)memcached_success(MEMCACHED_SUCCESS);
-  (void)memcached_failed(MEMCACHED_SUCCESS);
-  (void)memcached_continue(MEMCACHED_SUCCESS);
-
-  memcached_st *memc= memcached_create(NULL);
-  
-  if (memc == NULL)
-  {
-    return EXIT_FAILURE;
-  }
-  memcached_free(memc);
-
-  return EXIT_SUCCESS;
-}
-
diff --git a/libmemcached-1.0/t/cc_test.cc b/libmemcached-1.0/t/cc_test.cc
deleted file mode 100644 (file)
index 71ee8c3..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached C++ test app
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
- * @file @brief C dummy test, aka testing C linking, etc
- */
-
-#include <cstdlib>
-
-#include <libmemcached-1.0/memcached.h>
-
-int main(void)
-{
-  (void)memcached_success(MEMCACHED_SUCCESS);
-  (void)memcached_failed(MEMCACHED_SUCCESS);
-  (void)memcached_continue(MEMCACHED_SUCCESS);
-
-  memcached_st *memc= memcached_create(NULL);
-
-  if (memc == NULL)
-  {
-    return EXIT_FAILURE;
-  }
-
-  memcached_free(memc);
-
-  return EXIT_SUCCESS;
-}
-
diff --git a/libmemcached-1.0/touch.h b/libmemcached-1.0/touch.h
deleted file mode 100644 (file)
index e143c03..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-LIBMEMCACHED_API
-memcached_return_t memcached_touch(memcached_st *ptr,
-                                   const char *key, size_t key_length,
-                                   time_t expiration);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_touch_by_key(memcached_st *ptr,
-                                          const char *group_key, size_t group_key_length,
-                                          const char *key, size_t key_length,
-                                          time_t expiration);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/triggers.h b/libmemcached-1.0/triggers.h
deleted file mode 100644 (file)
index b331429..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef memcached_return_t (*memcached_clone_fn)(memcached_st *destination, const memcached_st *source);
-typedef memcached_return_t (*memcached_cleanup_fn)(const memcached_st *ptr);
-
-/**
-  Trigger functions.
-*/
-typedef memcached_return_t (*memcached_trigger_key_fn)(const memcached_st *ptr,
-                                                       const char *key, size_t key_length,
-                                                       memcached_result_st *result);
-typedef memcached_return_t (*memcached_trigger_delete_key_fn)(const memcached_st *ptr,
-                                                              const char *key, size_t key_length);
-
-typedef memcached_return_t (*memcached_dump_fn)(const memcached_st *ptr,
-                                                const char *key,
-                                                size_t key_length,
-                                                void *context);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/types.h b/libmemcached-1.0/types.h
deleted file mode 100644 (file)
index 2c3f87a..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#ifdef __cplusplus
-
-struct memcached_st;
-struct memcached_stat_st;
-struct memcached_analysis_st;
-struct memcached_result_st;
-struct memcached_array_st;
-struct memcached_error_t;
-
-// All of the flavors of memcache_server_st
-struct memcached_server_st;
-struct memcached_instance_st;
-typedef struct memcached_instance_st memcached_instance_st;
-typedef struct memcached_server_st *memcached_server_list_st;
-
-struct memcached_callback_st;
-
-// The following two structures are internal, and never exposed to users.
-struct memcached_string_st;
-struct memcached_string_t;
-struct memcached_continuum_item_st;
-
-#else
-
-typedef struct memcached_st memcached_st;
-typedef struct memcached_stat_st memcached_stat_st;
-typedef struct memcached_analysis_st memcached_analysis_st;
-typedef struct memcached_result_st memcached_result_st;
-typedef struct memcached_array_st memcached_array_st;
-typedef struct memcached_error_t memcached_error_t;
-
-// All of the flavors of memcache_server_st
-typedef struct memcached_server_st memcached_server_st;
-typedef struct memcached_instance_st memcached_instance_st;
-typedef struct memcached_server_st *memcached_server_list_st;
-
-typedef struct memcached_callback_st memcached_callback_st;
-
-// The following two structures are internal, and never exposed to users.
-typedef struct memcached_string_st memcached_string_st;
-typedef struct memcached_string_t memcached_string_t;
-
-#endif
diff --git a/libmemcached-1.0/types/behavior.h b/libmemcached-1.0/types/behavior.h
deleted file mode 100644 (file)
index a1bbfd2..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-enum memcached_behavior_t {
-  MEMCACHED_BEHAVIOR_NO_BLOCK,
-  MEMCACHED_BEHAVIOR_TCP_NODELAY,
-  MEMCACHED_BEHAVIOR_HASH,
-  MEMCACHED_BEHAVIOR_KETAMA,
-  MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE,
-  MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE,
-  MEMCACHED_BEHAVIOR_CACHE_LOOKUPS,
-  MEMCACHED_BEHAVIOR_SUPPORT_CAS,
-  MEMCACHED_BEHAVIOR_POLL_TIMEOUT,
-  MEMCACHED_BEHAVIOR_DISTRIBUTION,
-  MEMCACHED_BEHAVIOR_BUFFER_REQUESTS,
-  MEMCACHED_BEHAVIOR_USER_DATA,
-  MEMCACHED_BEHAVIOR_SORT_HOSTS,
-  MEMCACHED_BEHAVIOR_VERIFY_KEY,
-  MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT,
-  MEMCACHED_BEHAVIOR_RETRY_TIMEOUT,
-  MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED,
-  MEMCACHED_BEHAVIOR_KETAMA_HASH,
-  MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
-  MEMCACHED_BEHAVIOR_SND_TIMEOUT,
-  MEMCACHED_BEHAVIOR_RCV_TIMEOUT,
-  MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT,
-  MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK,
-  MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK,
-  MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH,
-  MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY,
-  MEMCACHED_BEHAVIOR_NOREPLY,
-  MEMCACHED_BEHAVIOR_USE_UDP,
-  MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS,
-  MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS,
-  MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ,
-  MEMCACHED_BEHAVIOR_CORK,
-  MEMCACHED_BEHAVIOR_TCP_KEEPALIVE,
-  MEMCACHED_BEHAVIOR_TCP_KEEPIDLE,
-  MEMCACHED_BEHAVIOR_LOAD_FROM_FILE,
-  MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS,
-  MEMCACHED_BEHAVIOR_DEAD_TIMEOUT,
-  MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT,
-  MEMCACHED_BEHAVIOR_MAX
-};
-
-#ifndef __cplusplus
-typedef enum memcached_behavior_t memcached_behavior_t;
-#endif
diff --git a/libmemcached-1.0/types/callback.h b/libmemcached-1.0/types/callback.h
deleted file mode 100644 (file)
index d5481f5..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-enum memcached_callback_t {
-  MEMCACHED_CALLBACK_PREFIX_KEY = 0,
-  MEMCACHED_CALLBACK_USER_DATA = 1,
-  MEMCACHED_CALLBACK_CLEANUP_FUNCTION = 2,
-  MEMCACHED_CALLBACK_CLONE_FUNCTION = 3,
-  MEMCACHED_CALLBACK_GET_FAILURE = 7,
-  MEMCACHED_CALLBACK_DELETE_TRIGGER = 8,
-  MEMCACHED_CALLBACK_MAX,
-  MEMCACHED_CALLBACK_NAMESPACE= MEMCACHED_CALLBACK_PREFIX_KEY
-};
-
-#ifndef __cplusplus
-typedef enum memcached_callback_t memcached_callback_t;
-#endif
diff --git a/libmemcached-1.0/types/connection.h b/libmemcached-1.0/types/connection.h
deleted file mode 100644 (file)
index d2a072b..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-enum memcached_connection_t {
-  MEMCACHED_CONNECTION_TCP,
-  MEMCACHED_CONNECTION_UDP,
-  MEMCACHED_CONNECTION_UNIX_SOCKET
-};
-
-#ifndef __cplusplus
-typedef enum memcached_connection_t memcached_connection_t;
-#endif
diff --git a/libmemcached-1.0/types/hash.h b/libmemcached-1.0/types/hash.h
deleted file mode 100644 (file)
index 8eee4df..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-enum memcached_hash_t {
-  MEMCACHED_HASH_DEFAULT= 0,
-  MEMCACHED_HASH_MD5,
-  MEMCACHED_HASH_CRC,
-  MEMCACHED_HASH_FNV1_64,
-  MEMCACHED_HASH_FNV1A_64,
-  MEMCACHED_HASH_FNV1_32,
-  MEMCACHED_HASH_FNV1A_32,
-  MEMCACHED_HASH_HSIEH,
-  MEMCACHED_HASH_MURMUR,
-  MEMCACHED_HASH_JENKINS,
-  MEMCACHED_HASH_MURMUR3,
-  MEMCACHED_HASH_CUSTOM,
-  MEMCACHED_HASH_MAX
-};
-
-#ifndef __cplusplus
-typedef enum memcached_hash_t memcached_hash_t;
-#endif
diff --git a/libmemcached-1.0/types/return.h b/libmemcached-1.0/types/return.h
deleted file mode 100644 (file)
index 80c9051..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-enum memcached_return_t {
-  MEMCACHED_SUCCESS,
-  MEMCACHED_FAILURE,
-  MEMCACHED_HOST_LOOKUP_FAILURE, // getaddrinfo() and getnameinfo() only
-  MEMCACHED_CONNECTION_FAILURE,
-  MEMCACHED_CONNECTION_BIND_FAILURE,  // DEPRECATED, see MEMCACHED_HOST_LOOKUP_FAILURE
-  MEMCACHED_WRITE_FAILURE,
-  MEMCACHED_READ_FAILURE,
-  MEMCACHED_UNKNOWN_READ_FAILURE,
-  MEMCACHED_PROTOCOL_ERROR,
-  MEMCACHED_CLIENT_ERROR,
-  MEMCACHED_SERVER_ERROR, // Server returns "SERVER_ERROR"
-  MEMCACHED_ERROR, // Server returns "ERROR"
-  MEMCACHED_DATA_EXISTS,
-  MEMCACHED_DATA_DOES_NOT_EXIST,
-  MEMCACHED_NOTSTORED,
-  MEMCACHED_STORED,
-  MEMCACHED_NOTFOUND,
-  MEMCACHED_MEMORY_ALLOCATION_FAILURE,
-  MEMCACHED_PARTIAL_READ,
-  MEMCACHED_SOME_ERRORS,
-  MEMCACHED_NO_SERVERS,
-  MEMCACHED_END,
-  MEMCACHED_DELETED,
-  MEMCACHED_VALUE,
-  MEMCACHED_STAT,
-  MEMCACHED_ITEM,
-  MEMCACHED_ERRNO,
-  MEMCACHED_FAIL_UNIX_SOCKET, // DEPRECATED
-  MEMCACHED_NOT_SUPPORTED,
-  MEMCACHED_NO_KEY_PROVIDED, /* Deprecated. Use MEMCACHED_BAD_KEY_PROVIDED! */
-  MEMCACHED_FETCH_NOTFINISHED,
-  MEMCACHED_TIMEOUT,
-  MEMCACHED_BUFFERED,
-  MEMCACHED_BAD_KEY_PROVIDED,
-  MEMCACHED_INVALID_HOST_PROTOCOL,
-  MEMCACHED_SERVER_MARKED_DEAD,
-  MEMCACHED_UNKNOWN_STAT_KEY,
-  MEMCACHED_E2BIG,
-  MEMCACHED_INVALID_ARGUMENTS,
-  MEMCACHED_KEY_TOO_BIG,
-  MEMCACHED_AUTH_PROBLEM,
-  MEMCACHED_AUTH_FAILURE,
-  MEMCACHED_AUTH_CONTINUE,
-  MEMCACHED_PARSE_ERROR,
-  MEMCACHED_PARSE_USER_ERROR,
-  MEMCACHED_DEPRECATED,
-  MEMCACHED_IN_PROGRESS,
-  MEMCACHED_SERVER_TEMPORARILY_DISABLED,
-  MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE,
-  MEMCACHED_UNIX_SOCKET_PATH_TOO_BIG,
-  MEMCACHED_MAXIMUM_RETURN, /* Always add new error code before */
-  MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE= MEMCACHED_ERROR
-};
-
-#ifndef __cplusplus
-typedef enum memcached_return_t memcached_return_t;
-#endif
diff --git a/libmemcached-1.0/types/server_distribution.h b/libmemcached-1.0/types/server_distribution.h
deleted file mode 100644 (file)
index 95e129f..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-enum memcached_server_distribution_t {
-  MEMCACHED_DISTRIBUTION_MODULA,
-  MEMCACHED_DISTRIBUTION_CONSISTENT,
-  MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA,
-  MEMCACHED_DISTRIBUTION_RANDOM,
-  MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY,
-  MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED,
-  MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET,
-  MEMCACHED_DISTRIBUTION_CONSISTENT_MAX
-};
-
-#ifndef __cplusplus
-typedef enum memcached_server_distribution_t memcached_server_distribution_t;
-#endif
diff --git a/libmemcached-1.0/verbosity.h b/libmemcached-1.0/verbosity.h
deleted file mode 100644 (file)
index 2994648..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_verbosity(memcached_st *ptr, uint32_t verbosity);
-
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/version.h b/libmemcached-1.0/version.h
deleted file mode 100644 (file)
index c443acc..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_version(memcached_st *ptr);
-
-LIBMEMCACHED_API
-const char * memcached_lib_version(void);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached-1.0/visibility.h b/libmemcached-1.0/visibility.h
deleted file mode 100644 (file)
index d4e4eea..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker 
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Interface for memcached server.
- *
- * Author: Trond Norbye
- *
- */
-
-/**
- * @file
- * @brief Visibility control macros
- */
-
-#pragma once
-
-/**
- *
- * LIBMEMCACHED_API is used for the public API symbols. It either DLL imports or
- * DLL exports (or does nothing for static build).
- *
- * LIBMEMCACHED_LOCAL is used for non-api symbols.
- */
-
-#if defined(BUILDING_LIBMEMCACHEDINTERNAL)
-# if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
-#  define LIBMEMCACHED_API __attribute__ ((visibility("default")))
-#  define LIBMEMCACHED_LOCAL  __attribute__ ((visibility("default")))
-# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
-#  define LIBMEMCACHED_API __global
-#  define LIBMEMCACHED_LOCAL __global
-# elif defined(_MSC_VER)
-#  define LIBMEMCACHED_API extern __declspec(dllexport) 
-#  define LIBMEMCACHED_LOCAL extern __declspec(dllexport)
-# else
-#  define LIBMEMCACHED_API
-#  define LIBMEMCACHED_LOCAL
-# endif
-#else
-# if defined(BUILDING_LIBMEMCACHED)
-#  if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
-#   define LIBMEMCACHED_API __attribute__ ((visibility("default")))
-#   define LIBMEMCACHED_LOCAL  __attribute__ ((visibility("hidden")))
-#  elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
-#   define LIBMEMCACHED_API __global
-#   define LIBMEMCACHED_LOCAL __hidden
-#  elif defined(_MSC_VER)
-#   define LIBMEMCACHED_API extern __declspec(dllexport) 
-#   define LIBMEMCACHED_LOCAL
-#  else
-#   define LIBMEMCACHED_API
-#   define LIBMEMCACHED_LOCAL
-#  endif /* defined(HAVE_VISIBILITY) */
-# else  /* defined(BUILDING_LIBMEMCACHED) */
-#  if defined(_MSC_VER)
-#   define LIBMEMCACHED_API extern __declspec(dllimport) 
-#   define LIBMEMCACHED_LOCAL
-#  else
-#   define LIBMEMCACHED_API
-#   define LIBMEMCACHED_LOCAL
-#  endif /* defined(_MSC_VER) */
-# endif /* defined(BUILDING_LIBMEMCACHED) */
-#endif /* defined(BUILDING_LIBMEMCACHEDINTERNAL) */
diff --git a/libmemcached/CMakeLists.txt b/libmemcached/CMakeLists.txt
deleted file mode 100644 (file)
index 2f8b018..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-
-find_package(FLEX)
-find_package(BISON)
-
-file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/csl)
-bison_target(CSL_PARSER csl/parser.yy ${CMAKE_CURRENT_BINARY_DIR}/csl/parser.cc
-        DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/csl/parser.h
-        )
-flex_target(CSL_SCANNER csl/scanner.l ${CMAKE_CURRENT_BINARY_DIR}/csl/scanner.cc
-        DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/csl/scanner.h
-        )
-add_flex_bison_dependency(CSL_SCANNER CSL_PARSER)
-
-set(LIBMEMCACHED_SOURCES
-        csl/context.cc
-        ${BISON_CSL_PARSER_OUTPUTS}
-        ${FLEX_CSL_SCANNER_OUTPUTS}
-        allocators.cc
-        analyze.cc
-        array.c
-        auto.cc
-        backtrace.cc
-        behavior.cc
-        byteorder.cc
-        callback.cc
-        connect.cc
-        delete.cc
-        do.cc
-        dump.cc
-        encoding_key.cc
-        error.cc
-        exist.cc
-        fetch.cc
-        flag.cc
-        flush.cc
-        flush_buffers.cc
-        get.cc
-        hash.cc
-        hosts.cc
-        initialize_query.cc
-        instance.cc
-        io.cc
-        key.cc
-        memcached.cc
-        namespace.cc
-        options.cc
-        parse.cc
-        poll.cc
-        purge.cc
-        quit.cc
-        response.cc
-        result.cc
-        sasl.cc
-        server.cc
-        server_list.cc
-        stats.cc
-        storage.cc
-        strerror.cc
-        string.cc
-        touch.cc
-        udp.cc
-        verbosity.cc
-        version.cc
-        virtual_bucket.c)
-
-add_library(libmemcached SHARED
-        ${LIBMEMCACHED_SOURCES})
-add_library(memcached ALIAS libmemcached)
-set_target_properties(libmemcached PROPERTIES LIBRARY_OUTPUT_NAME memcached)
-target_link_libraries(libmemcached libhashkit Threads::Threads ${LIBSASL_LIBRARIES} ${CMAKE_DL_LIBS})
-target_include_directories(libmemcached PRIVATE .. ${LIBSASL_INCLUDEDIR})
-target_compile_definitions(libmemcached PRIVATE -DBUILDING_LIBMEMCACHED)
-
-set_target_properties(libmemcached PROPERTIES SOVERSION ${LIBMEMCACHED_SO_VERSION})
-install(TARGETS libmemcached EXPORT libmemcached
-        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
-export(EXPORT libmemcached)
-install(EXPORT libmemcached DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake)
-
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
-        FILES_MATCHING REGEX "(memcached|util)\\.h(pp)?"
-        PATTERN csl EXCLUDE
-        PATTERN memcached EXCLUDE
-        PATTERN util EXCLUDE
-        )
-
-# FIXME: dtrace
-
-add_library(libmemcachedinternal STATIC
-        ${LIBMEMCACHED_SOURCES})
-add_library(memcachedinternal ALIAS libmemcachedinternal)
-set_target_properties(libmemcachedinternal PROPERTIES LIBRARY_OUTPUT_NAME memcachedinternal)
-target_link_libraries(libmemcachedinternal libhashkit Threads::Threads ${LIBSASL_LIBRARIES} ${CMAKE_DL_LIBS})
-target_include_directories(libmemcachedinternal PRIVATE .. ${LIBSASL_INCLUDEDIR})
-target_compile_definitions(libmemcachedinternal PRIVATE -DBUILDING_LIBMEMCACHEDINTERNAL)
diff --git a/libmemcached/allocators.cc b/libmemcached/allocators.cc
deleted file mode 100644 (file)
index f1caf71..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-void _libmemcached_free(const memcached_st*, void *mem, void*)
-{
-  if (mem)
-  {
-    std::free(mem);
-  }
-}
-
-void *_libmemcached_malloc(const memcached_st *, size_t size, void *)
-{
-  return std::malloc(size);
-}
-
-void *_libmemcached_realloc(const memcached_st*, void *mem, size_t size, void *)
-{
-  return std::realloc(mem, size);
-}
-
-void *_libmemcached_calloc(const memcached_st *self, size_t nelem, size_t size, void *context)
-{
-  if (self->allocators.malloc != _libmemcached_malloc)
-  {
-     void *ret= _libmemcached_malloc(self, nelem * size, context);
-     if (ret)
-     {
-       memset(ret, 0, nelem * size);
-     }
-
-     return ret;
-  }
-
-  return std::calloc(nelem, size);
-}
-
-struct memcached_allocator_t memcached_allocators_return_default(void)
-{
-  static struct memcached_allocator_t global_default_allocator= { _libmemcached_calloc, _libmemcached_free, _libmemcached_malloc, _libmemcached_realloc, 0 };
-  return global_default_allocator;
-}
-
-memcached_return_t memcached_set_memory_allocators(memcached_st *shell,
-                                                   memcached_malloc_fn mem_malloc,
-                                                   memcached_free_fn mem_free,
-                                                   memcached_realloc_fn mem_realloc,
-                                                   memcached_calloc_fn mem_calloc,
-                                                   void *context)
-{
-  Memcached* self= memcached2Memcached(shell);
-  if (self == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  /* All should be set, or none should be set */
-  if (mem_malloc == NULL and mem_free == NULL and mem_realloc == NULL and mem_calloc == NULL) 
-  {
-    self->allocators= memcached_allocators_return_default();
-  }
-  else if (mem_malloc == NULL or mem_free == NULL or mem_realloc == NULL or mem_calloc == NULL)
-  {
-    return memcached_set_error(*self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("NULL parameter provided for one or more allocators"));
-  }
-  else
-  {
-    self->allocators.malloc= mem_malloc;
-    self->allocators.free= mem_free;
-    self->allocators.realloc= mem_realloc;
-    self->allocators.calloc= mem_calloc;
-    self->allocators.context= context;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-void *memcached_get_memory_allocators_context(const memcached_st *shell)
-{
-  const Memcached* self= memcached2Memcached(shell);
-  if (self)
-  {
-    return self->allocators.context;
-  }
-
-  return NULL;
-}
-
-void memcached_get_memory_allocators(const memcached_st *shell,
-                                     memcached_malloc_fn *mem_malloc,
-                                     memcached_free_fn *mem_free,
-                                     memcached_realloc_fn *mem_realloc,
-                                     memcached_calloc_fn *mem_calloc)
-{
-  const Memcached* self= memcached2Memcached(shell);
-  if (self)
-  {
-    if (mem_malloc)
-    {
-      *mem_malloc= self->allocators.malloc;
-    }
-
-    if (mem_free)
-    {
-      *mem_free= self->allocators.free;
-    }
-
-    if (mem_realloc)
-    {
-      *mem_realloc= self->allocators.realloc;
-    }
-
-    if (mem_calloc)
-    {
-      *mem_calloc= self->allocators.calloc;
-    }
-  }
-}
diff --git a/libmemcached/allocators.hpp b/libmemcached/allocators.hpp
deleted file mode 100644 (file)
index 8f19624..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-void _libmemcached_free(const memcached_st *ptr, void *mem, void *context);
-
-void *_libmemcached_malloc(const memcached_st *ptr, const size_t size, void *context);
-
-void *_libmemcached_realloc(const memcached_st *ptr, void *mem, const size_t size, void *context);
-
-void *_libmemcached_calloc(const memcached_st *ptr, size_t nelem, size_t size, void *context);
-
-struct memcached_allocator_t memcached_allocators_return_default(void);
diff --git a/libmemcached/analyze.cc b/libmemcached/analyze.cc
deleted file mode 100644 (file)
index c6ac15c..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-#include <libmemcached/common.h>
-
-static void calc_largest_consumption(memcached_analysis_st *result,
-                                     const uint32_t server_num,
-                                     const uint64_t nbytes)
-{
-  if (result->most_used_bytes < nbytes)
-  {
-    result->most_used_bytes= nbytes;
-    result->most_consumed_server= server_num;
-  }
-}
-
-static void calc_oldest_node(memcached_analysis_st *result,
-                             const uint32_t server_num,
-                             const uint32_t uptime)
-{
-  if (result->longest_uptime < uptime)
-  {
-    result->longest_uptime= uptime;
-    result->oldest_server= server_num;
-  }
-}
-
-static void calc_least_free_node(memcached_analysis_st *result,
-                                 const uint32_t server_num,
-                                 const uint64_t max_allowed_bytes,
-                                 const uint64_t used_bytes)
-{
-  uint64_t remaining_bytes= max_allowed_bytes - used_bytes;
-
-  if (result->least_remaining_bytes == 0 ||
-      remaining_bytes < result->least_remaining_bytes)
-  {
-    result->least_remaining_bytes= remaining_bytes;
-    result->least_free_server= server_num;
-  }
-}
-
-static void calc_average_item_size(memcached_analysis_st *result,
-                                   const uint64_t total_items,
-                                   const uint64_t total_bytes)
-{
-  if (total_items > 0 && total_bytes > 0)
-  {
-    result->average_item_size= (uint32_t) (total_bytes / total_items);
-  }
-}
-
-static void calc_hit_ratio(memcached_analysis_st *result,
-                           const uint64_t total_get_hits,
-                           const uint64_t total_get_cmds)
-{
-  if (total_get_hits == 0 || total_get_cmds == 0)
-  {
-    result->pool_hit_ratio= 0;
-    return;
-  }
-
-  double temp= double(total_get_hits) / total_get_cmds;
-  result->pool_hit_ratio= temp * 100;
-}
-
-memcached_analysis_st *memcached_analyze(memcached_st *shell,
-                                         memcached_stat_st *memc_stat,
-                                         memcached_return_t *error)
-{
-  Memcached* memc= memcached2Memcached(shell);
-  uint64_t total_items= 0, total_bytes= 0;
-  uint64_t total_get_cmds= 0, total_get_hits= 0;
-
-  if (memc == NULL or memc_stat == NULL)
-  {
-    return NULL;
-  }
-
-  memcached_return_t not_used;
-  if (error == NULL)
-  {
-    error= &not_used;
-  }
-
-  *error= MEMCACHED_SUCCESS;
-  uint32_t server_count= memcached_server_count(memc);
-  memcached_analysis_st *result= (memcached_analysis_st*)libmemcached_xcalloc(memc,
-                                                                              memcached_server_count(memc),
-                                                                              memcached_analysis_st);
-
-  if (result == NULL)
-  {
-    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-    return NULL;
-  }
-
-  result->root= memc;
-
-  for (uint32_t x= 0; x < server_count; x++)
-  {
-    calc_largest_consumption(result, x, memc_stat[x].bytes);
-    calc_oldest_node(result, x, uint32_t(memc_stat[x].uptime));
-    calc_least_free_node(result, x,
-                         memc_stat[x].limit_maxbytes,
-                         memc_stat[x].bytes);
-
-    total_get_hits+= memc_stat[x].get_hits;
-    total_get_cmds+= memc_stat[x].cmd_get;
-    total_items+= memc_stat[x].curr_items;
-    total_bytes+= memc_stat[x].bytes;
-  }
-
-  calc_average_item_size(result, total_items, total_bytes);
-  calc_hit_ratio(result, total_get_hits, total_get_cmds);
-
-  return result;
-}
-
-void memcached_analyze_free(memcached_analysis_st *ptr)
-{
-  libmemcached_free(ptr->root, ptr);
-}
diff --git a/libmemcached/array.c b/libmemcached/array.c
deleted file mode 100644 (file)
index cd472c3..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-#include <assert.h>
-#include <iso646.h>
-
-struct memcached_array_st
-{
-  Memcached *root;
-  size_t size;
-  char c_str[];
-};
-
-
-memcached_array_st *memcached_array_clone(Memcached *memc, const memcached_array_st *original)
-{
-  if (original)
-  {
-    return memcached_strcpy(memc, original->c_str, original->size);
-  }
-
-  return NULL;
-}
-
-memcached_array_st *memcached_strcpy(Memcached *memc, const char *str, size_t str_length)
-{
-  assert(memc);
-  assert(str);
-  assert(str_length);
-
-  memcached_array_st *array= (struct memcached_array_st *)libmemcached_malloc(memc, sizeof(struct memcached_array_st) +str_length +1);
-
-  if (array)
-  {
-    array->root= memc;
-    array->size= str_length; // We don't count the NULL ending
-    memcpy(array->c_str, str, str_length);
-    array->c_str[str_length]= 0;
-  }
-
-  return array;
-}
-
-bool memcached_array_is_null(memcached_array_st *array)
-{
-  if (array)
-  {
-    return false;
-  }
-
-  return true;
-}
-
-memcached_string_t memcached_array_to_string(memcached_array_st *array)
-{
-  assert(array);
-  assert(array->c_str);
-  assert(array->size);
-  memcached_string_t tmp;
-  tmp.c_str= array->c_str;
-  tmp.size= array->size;
-
-  return tmp;
-}
-
-void memcached_array_free(memcached_array_st *array)
-{
-  if (array)
-  {
-    WATCHPOINT_ASSERT(array->root);
-    libmemcached_free(array->root, array);
-  }
-}
-
-size_t memcached_array_size(memcached_array_st *array)
-{
-  if (array)
-  {
-    return array->size;
-  }
-
-  return 0;
-}
-
-const char *memcached_array_string(memcached_array_st *array)
-{
-  if (array)
-  {
-    return array->c_str;
-  }
-
-  return NULL;
-}
diff --git a/libmemcached/array.h b/libmemcached/array.h
deleted file mode 100644 (file)
index afb3f91..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-memcached_array_st *memcached_array_clone(Memcached* memc, const memcached_array_st *original);
-
-memcached_array_st *memcached_strcpy(Memcached* memc, const char *str, size_t str_length);
-
-void memcached_array_free(memcached_array_st *array);
-
-size_t memcached_array_size(memcached_array_st *array);
-
-const char *memcached_array_string(memcached_array_st *array);
-
-memcached_string_t memcached_array_to_string(memcached_array_st *array);
-
-bool memcached_array_is_null(memcached_array_st *array);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#ifdef __cplusplus
-#define memcached_print_array(X) static_cast<int>(memcached_array_size(X)), memcached_array_string(X)
-#define memcached_param_array(X) memcached_array_string(X), memcached_array_size(X)
-#else
-#define memcached_print_array(X) (int)memcached_array_size((X)), memcached_array_string((X))
-#define memcached_param_array(X) memcached_array_string(X), memcached_array_size(X)
-#endif
diff --git a/libmemcached/assert.hpp b/libmemcached/assert.hpp
deleted file mode 100644 (file)
index cd4a194..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  libmcachedd client library.
- *
- *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-# include <cassert>
-#else
-# include <assert.h>
-#endif // __cplusplus
-
-#ifdef NDEBUG
-# define assert_msg(__expr, __mesg) (void)(__expr); (void)(__mesg);
-# define assert_vmsg(__expr, __mesg, ...) (void)(__expr); (void)(__mesg);
-#else
-
-# ifdef _WIN32
-#  include <malloc.h>
-# else
-#  include <alloca.h>
-# endif
-
-#ifdef __cplusplus
-# include <cstdarg>
-# include <cstdio>
-#else
-# include <stdarg.h>
-# include <stdio.h>
-#endif
-
-# include <libmemcached/backtrace.hpp>
-
-# define assert_msg(__expr, __mesg) \
-do \
-{ \
-  if (not (__expr)) \
-  { \
-    fprintf(stderr, "\n%s:%d Assertion \"%s\" failed for function \"%s\" likely for %s\n", __FILE__, __LINE__, #__expr, __func__, (#__mesg));\
-    custom_backtrace(); \
-    abort(); \
-  } \
-} while (0)
-
-# define assert_vmsg(__expr, __mesg, ...) \
-do \
-{ \
-  if (not (__expr)) \
-  { \
-    size_t ask= snprintf(0, 0, (__mesg), __VA_ARGS__); \
-    ask++; \
-    char *_error_message= (char*)alloca(sizeof(char) * ask); \
-    size_t _error_message_size= snprintf(_error_message, ask, (__mesg), __VA_ARGS__); \
-    fprintf(stderr, "\n%s:%d Assertion '%s' failed for function '%s' [ %.*s ]\n", __FILE__, __LINE__, #__expr, __func__, int(_error_message_size), _error_message);\
-    custom_backtrace(); \
-    abort(); \
-  } \
-} while (0)
-
-#endif // NDEBUG
diff --git a/libmemcached/auto.cc b/libmemcached/auto.cc
deleted file mode 100644 (file)
index 06e7ab6..0000000
+++ /dev/null
@@ -1,385 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-static void auto_response(memcached_instance_st* instance, const bool reply,  memcached_return_t& rc, uint64_t* value)
-{
-  // If the message was successfully sent, then get the response, otherwise
-  // fail.
-  if (memcached_success(rc))
-  {
-    if (reply == false)
-    {
-      *value= UINT64_MAX;
-      return;
-    }
-
-    rc= memcached_response(instance, &instance->root->result);
-  }
-
-  if (memcached_fatal(rc))
-  {
-    assert(memcached_last_error(instance->root) != MEMCACHED_SUCCESS);
-    *value= UINT64_MAX;
-  }
-  else if (memcached_failed(rc))
-  {
-    *value= UINT64_MAX;
-  }
-  else
-  {
-    assert(memcached_last_error(instance->root) != MEMCACHED_NOTFOUND);
-    *value= instance->root->result.numeric_value;
-  }
-}
-
-static memcached_return_t text_incr_decr(memcached_instance_st* instance,
-                                         const bool is_incr,
-                                         const char *key, size_t key_length,
-                                         const uint64_t offset,
-                                         const bool reply)
-{
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-
-  int send_length= snprintf(buffer, sizeof(buffer), " %" PRIu64, offset);
-  if (size_t(send_length) >= sizeof(buffer) or send_length < 0)
-  {
-    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                               memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
-  }
-
-  libmemcached_io_vector_st vector[]=
-  {
-    { NULL, 0 },
-    { memcached_literal_param("incr ") },
-    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
-    { key, key_length },
-    { buffer, size_t(send_length) },
-    { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
-    { memcached_literal_param("\r\n") }
-  };
-
-  if (is_incr == false)
-  {
-    vector[1].buffer= "decr ";
-  }
-
-  return memcached_vdo(instance, vector, 7, true);
-}
-
-static memcached_return_t binary_incr_decr(memcached_instance_st* instance,
-                                           protocol_binary_command cmd,
-                                           const char *key, const size_t key_length,
-                                           const uint64_t offset,
-                                           const uint64_t initial,
-                                           const uint32_t expiration,
-                                           const bool reply)
-{
-  if (reply == false)
-  {
-    if(cmd == PROTOCOL_BINARY_CMD_DECREMENT)
-    {
-      cmd= PROTOCOL_BINARY_CMD_DECREMENTQ;
-    }
-
-    if(cmd == PROTOCOL_BINARY_CMD_INCREMENT)
-    {
-      cmd= PROTOCOL_BINARY_CMD_INCREMENTQ;
-    }
-  }
-  protocol_binary_request_incr request= {}; // = {.bytes= {0}};
-
-  initialize_binary_request(instance, request.message.header);
-
-  request.message.header.request.opcode= cmd;
-  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(instance->root->_namespace)));
-  request.message.header.request.extlen= 20;
-  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-  request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(instance->root->_namespace) +request.message.header.request.extlen));
-  request.message.body.delta= memcached_htonll(offset);
-  request.message.body.initial= memcached_htonll(initial);
-  request.message.body.expiration= htonl((uint32_t) expiration);
-
-  libmemcached_io_vector_st vector[]=
-  {
-    { NULL, 0 },
-    { request.bytes, sizeof(request.bytes) },
-    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
-    { key, key_length }
-  };
-
-  return memcached_vdo(instance, vector, 4, true);
-}
-
-memcached_return_t memcached_increment(memcached_st *memc,
-                                       const char *key, size_t key_length,
-                                       uint32_t offset,
-                                       uint64_t *value)
-{
-  return memcached_increment_by_key(memc, key, key_length, key, key_length, offset, value);
-}
-
-static memcached_return_t increment_decrement_by_key(const protocol_binary_command command,
-                                                     Memcached *memc,
-                                                     const char *group_key, size_t group_key_length,
-                                                     const char *key, size_t key_length,
-                                                     uint64_t offset,
-                                                     uint64_t *value)
-{
-  uint64_t local_value;
-  if (value == NULL)
-  {
-    value= &local_value;
-  }
-
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(memc, true)))
-  {
-    return rc;
-  }
-
-  if (memcached_is_encrypted(memc))
-  {
-    return memcached_set_error(*memc, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, 
-                               memcached_literal_param("Operation not allowed while encyrption is enabled"));
-  }
-
-  if (memcached_failed(rc= memcached_key_test(*memc, (const char **)&key, &key_length, 1)))
-  {
-    return memcached_last_error(memc);
-  }
-
-  uint32_t server_key= memcached_generate_hash_with_redistribution(memc, group_key, group_key_length);
-  memcached_instance_st* instance= memcached_instance_fetch(memc, server_key);
-
-  bool reply= memcached_is_replying(instance->root);
-
-  if (memcached_is_binary(memc))
-  {
-    rc= binary_incr_decr(instance, command,
-                         key, key_length,
-                         uint64_t(offset), 0, MEMCACHED_EXPIRATION_NOT_ADD,
-                         reply);
-  }
-  else
-  {
-    rc= text_incr_decr(instance,
-                       command == PROTOCOL_BINARY_CMD_INCREMENT ? true : false,
-                       key, key_length,
-                       offset, reply);
-  }
-
-  auto_response(instance, reply, rc, value);
-
-  return rc;
-}
-
-static memcached_return_t increment_decrement_with_initial_by_key(const protocol_binary_command command,
-                                                                  Memcached *memc,
-                                                                  const char *group_key,
-                                                                  size_t group_key_length,
-                                                                  const char *key,
-                                                                  size_t key_length,
-                                                                  uint64_t offset,
-                                                                  uint64_t initial,
-                                                                  time_t expiration,
-                                                                  uint64_t *value)
-{
-  uint64_t local_value;
-  if (value == NULL)
-  {
-    value= &local_value;
-  }
-
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(memc, true)))
-  {
-    return rc;
-  }
-
-  if (memcached_is_encrypted(memc))
-  {
-    return memcached_set_error(*memc, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, 
-                               memcached_literal_param("Operation not allowed while encryption is enabled"));
-  }
-
-  if (memcached_failed(rc= memcached_key_test(*memc, (const char **)&key, &key_length, 1)))
-  {
-    return memcached_last_error(memc);
-  }
-
-  uint32_t server_key= memcached_generate_hash_with_redistribution(memc, group_key, group_key_length);
-  memcached_instance_st* instance= memcached_instance_fetch(memc, server_key);
-
-  bool reply= memcached_is_replying(instance->root);
-
-  if (memcached_is_binary(memc))
-  {
-    rc= binary_incr_decr(instance, command,
-                         key, key_length,
-                         offset, initial, uint32_t(expiration),
-                         reply);
-        
-  }
-  else
-  {
-    rc=  memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
-                             memcached_literal_param("memcached_increment_with_initial_by_key() is not supported via the ASCII protocol"));
-  }
-
-  auto_response(instance, reply, rc, value);
-
-  return rc;
-}
-
-memcached_return_t memcached_decrement(memcached_st *memc,
-                                       const char *key, size_t key_length,
-                                       uint32_t offset,
-                                       uint64_t *value)
-{
-  return memcached_decrement_by_key(memc, key, key_length, key, key_length, offset, value);
-}
-
-
-memcached_return_t memcached_increment_by_key(memcached_st *shell,
-                                              const char *group_key, size_t group_key_length,
-                                              const char *key, size_t key_length,
-                                              uint64_t offset,
-                                              uint64_t *value)
-{
-  Memcached* memc= memcached2Memcached(shell);
-  LIBMEMCACHED_MEMCACHED_INCREMENT_START();
-  memcached_return_t rc= increment_decrement_by_key(PROTOCOL_BINARY_CMD_INCREMENT,
-                                                    memc,
-                                                    group_key, group_key_length,
-                                                    key, key_length,
-                                                    offset, value);
-
-  LIBMEMCACHED_MEMCACHED_INCREMENT_END();
-
-  return rc;
-}
-
-memcached_return_t memcached_decrement_by_key(memcached_st *shell,
-                                              const char *group_key, size_t group_key_length,
-                                              const char *key, size_t key_length,
-                                              uint64_t offset,
-                                              uint64_t *value)
-{
-  Memcached* memc= memcached2Memcached(shell);
-  LIBMEMCACHED_MEMCACHED_DECREMENT_START();
-  memcached_return_t rc= increment_decrement_by_key(PROTOCOL_BINARY_CMD_DECREMENT,
-                                                    memc,
-                                                    group_key, group_key_length,
-                                                    key, key_length,
-                                                    offset, value);
-  LIBMEMCACHED_MEMCACHED_DECREMENT_END();
-
-  return rc;
-}
-
-memcached_return_t memcached_increment_with_initial(memcached_st *memc,
-                                                    const char *key,
-                                                    size_t key_length,
-                                                    uint64_t offset,
-                                                    uint64_t initial,
-                                                    time_t expiration,
-                                                    uint64_t *value)
-{
-  return memcached_increment_with_initial_by_key(memc, key, key_length,
-                                                 key, key_length,
-                                                 offset, initial, expiration, value);
-}
-
-memcached_return_t memcached_increment_with_initial_by_key(memcached_st *shell,
-                                                           const char *group_key,
-                                                           size_t group_key_length,
-                                                           const char *key,
-                                                           size_t key_length,
-                                                           uint64_t offset,
-                                                           uint64_t initial,
-                                                           time_t expiration,
-                                                           uint64_t *value)
-{
-  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
-  Memcached* memc= memcached2Memcached(shell);
-  memcached_return_t rc= increment_decrement_with_initial_by_key(PROTOCOL_BINARY_CMD_INCREMENT, 
-                                                                 memc,
-                                                                 group_key, group_key_length,
-                                                                 key, key_length,
-                                                                 offset, initial, expiration, value);
-  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
-
-  return rc;
-}
-
-memcached_return_t memcached_decrement_with_initial(memcached_st *memc,
-                                                    const char *key,
-                                                    size_t key_length,
-                                                    uint64_t offset,
-                                                    uint64_t initial,
-                                                    time_t expiration,
-                                                    uint64_t *value)
-{
-  return memcached_decrement_with_initial_by_key(memc, key, key_length,
-                                                 key, key_length,
-                                                 offset, initial, expiration, value);
-}
-
-memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *shell,
-                                                           const char *group_key,
-                                                           size_t group_key_length,
-                                                           const char *key,
-                                                           size_t key_length,
-                                                           uint64_t offset,
-                                                           uint64_t initial,
-                                                           time_t expiration,
-                                                           uint64_t *value)
-{
-  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
-  Memcached* memc= memcached2Memcached(shell);
-  memcached_return_t rc= increment_decrement_with_initial_by_key(PROTOCOL_BINARY_CMD_DECREMENT, 
-                                                                 memc,
-                                                                 group_key, group_key_length,
-                                                                 key, key_length,
-                                                                 offset, initial, expiration, value);
-
-  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
-
-  return rc;
-}
diff --git a/libmemcached/backtrace.cc b/libmemcached/backtrace.cc
deleted file mode 100644 (file)
index e171fbe..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached client library.
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "mem_config.h"
-
-#include "libmemcached/backtrace.hpp"
-
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-
-#if defined(HAVE_SHARED_ENABLED) && HAVE_SHARED_ENABLED
-
-#ifdef HAVE_EXECINFO_H
-#include <execinfo.h>
-#endif
-
-#ifdef HAVE_GCC_ABI_DEMANGLE
-# include <cxxabi.h>
-# define USE_DEMANGLE 1
-#else
-# define USE_DEMANGLE 0
-#endif
-
-#ifdef HAVE_DLFCN_H
-# include <dlfcn.h>
-#endif   
-
-const int MAX_DEPTH= 50;
-
-void custom_backtrace(void)
-{
-#ifdef HAVE_EXECINFO_H
-  void *backtrace_buffer[MAX_DEPTH +1];
-
-  int stack_frames= backtrace(backtrace_buffer, MAX_DEPTH);
-  if (stack_frames)
-  {
-    char **symbollist= backtrace_symbols(backtrace_buffer, stack_frames);
-    if (symbollist)
-    {
-      for (int x= 0; x < stack_frames; x++) 
-      {
-        bool was_demangled= false;
-
-        if (USE_DEMANGLE)
-        {
-#ifdef HAVE_DLFCN_H
-          Dl_info dlinfo;
-          if (dladdr(backtrace_buffer[x], &dlinfo))
-          {
-            char demangled_buffer[1024];
-            const char *called_in= "<unresolved>";
-            if (dlinfo.dli_sname)
-            {
-              size_t demangled_size= sizeof(demangled_buffer);
-              int status;
-              char* demangled;
-              if ((demangled= abi::__cxa_demangle(dlinfo.dli_sname, demangled_buffer, &demangled_size, &status)))
-              {
-                called_in= demangled;
-                fprintf(stderr, "---> demangled: %s -> %s\n", demangled_buffer, demangled);
-              }
-              else
-              {
-                called_in= dlinfo.dli_sname;
-              }
-
-              was_demangled= true;
-              fprintf(stderr, "#%d  %p in %s at %s\n",
-                      x, backtrace_buffer[x],
-                      called_in,
-                      dlinfo.dli_fname);
-            }
-          }
-#endif
-        }
-
-        if (was_demangled == false)
-        {
-          fprintf(stderr, "?%d  %p in %s\n", x, backtrace_buffer[x], symbollist[x]);
-        }
-      }
-
-      ::free(symbollist);
-    }
-  }
-#endif // HAVE_EXECINFO_H
-}
-
-#else // HAVE_SHARED_ENABLED
-
-void custom_backtrace(void)
-{
-  fprintf(stderr, "Backtrace null function called\n");
-}
-#endif // AX_ENABLE_BACKTRACE
diff --git a/libmemcached/backtrace.hpp b/libmemcached/backtrace.hpp
deleted file mode 100644 (file)
index a83d3ea..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  libmcachedd client library.
- *
- *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void custom_backtrace(void);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached/behavior.cc b/libmemcached/behavior.cc
deleted file mode 100644 (file)
index 7536248..0000000
+++ /dev/null
@@ -1,727 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-#include <libmemcached/options.hpp>
-#include <libmemcached/virtual_bucket.h>
-
-#include <ctime>
-#include <sys/types.h>
-
-bool memcached_is_consistent_distribution(const Memcached* memc)
-{
-  switch (memc->distribution)
-  {
-  case MEMCACHED_DISTRIBUTION_CONSISTENT:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED:
-    return true;
-
-  case MEMCACHED_DISTRIBUTION_MODULA:
-  case MEMCACHED_DISTRIBUTION_RANDOM:
-  case MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX:
-    break;
-  }
-
-  return false;
-}
-
-/*
-  This function is used to modify the behavior of running client.
-
-  We quit all connections so we can reset the sockets.
-*/
-
-memcached_return_t memcached_behavior_set(memcached_st *shell,
-                                          const memcached_behavior_t flag,
-                                          uint64_t data)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  if (ptr == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  switch (flag)
-  {
-  case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
-    ptr->number_of_replicas= (uint32_t)data;
-    break;
-
-  case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK:
-    ptr->io_msg_watermark= (uint32_t) data;
-    break;
-
-  case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK:
-    ptr->io_bytes_watermark= (uint32_t)data;
-    break;
-
-  case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH:
-    ptr->io_key_prefetch = (uint32_t)data;
-    break;
-
-  case MEMCACHED_BEHAVIOR_SND_TIMEOUT:
-    ptr->snd_timeout= (int32_t)data;
-    break;
-
-  case MEMCACHED_BEHAVIOR_RCV_TIMEOUT:
-    ptr->rcv_timeout= (int32_t)data;
-    break;
-
-  case MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS:
-    ptr->flags.auto_eject_hosts= bool(data);
-    break;
-
-  case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
-    if (data == 0)
-    {
-      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
-                                        memcached_literal_param("MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT requires a value greater then zero."));
-    }
-    ptr->server_failure_limit= uint32_t(data);
-    break;
-
-  case MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT:
-    ptr->server_timeout_limit= uint32_t(data);
-    break;
-
-  case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL:
-    send_quit(ptr); // We need t shutdown all of the connections to make sure we do the correct protocol
-    if (data)
-    {
-      ptr->flags.verify_key= false;
-    }
-    ptr->flags.binary_protocol= bool(data);
-    break;
-
-  case MEMCACHED_BEHAVIOR_SUPPORT_CAS:
-    ptr->flags.support_cas= bool(data);
-    break;
-
-  case MEMCACHED_BEHAVIOR_NO_BLOCK:
-    ptr->flags.no_block= bool(data);
-    send_quit(ptr);
-    break;
-
-  case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS:
-    if (memcached_is_udp(ptr))
-    {
-      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
-                                 memcached_literal_param("MEMCACHED_BEHAVIOR_BUFFER_REQUESTS cannot be set while MEMCACHED_BEHAVIOR_USE_UDP is enabled."));
-    }
-    ptr->flags.buffer_requests= bool(data);
-    send_quit(ptr);
-    break;
-
-  case MEMCACHED_BEHAVIOR_USE_UDP:
-    send_quit(ptr); // We need t shutdown all of the connections to make sure we do the correct protocol
-    ptr->flags.use_udp= bool(data);
-    if (bool(data))
-    {
-      ptr->flags.reply= false;
-      ptr->flags.buffer_requests= false;
-    }
-    else
-    {
-      ptr->flags.reply= true;
-    }
-    break;
-
-  case MEMCACHED_BEHAVIOR_TCP_NODELAY:
-    ptr->flags.tcp_nodelay= bool(data);
-    send_quit(ptr);
-    break;
-
-  case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE:
-    ptr->flags.tcp_keepalive= bool(data);
-    send_quit(ptr);
-    break;
-
-  case MEMCACHED_BEHAVIOR_DISTRIBUTION:
-    return memcached_behavior_set_distribution(ptr, (memcached_server_distribution_t)data);
-
-  case MEMCACHED_BEHAVIOR_KETAMA:
-    {
-      if (data) // Turn on
-      {
-        return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA);
-      }
-
-      return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_MODULA);
-    }
-
-  case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED:
-    {
-      if (bool(data) == false)
-      {
-        return memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_KETAMA, true);
-      }
-
-      (void)memcached_behavior_set_key_hash(ptr, MEMCACHED_HASH_MD5);
-      (void)memcached_behavior_set_distribution_hash(ptr, MEMCACHED_HASH_MD5);
-      /**
-        @note We try to keep the same distribution going. This should be deprecated and rewritten.
-      */
-      return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED);
-    }
-
-  case MEMCACHED_BEHAVIOR_HASH:
-    return memcached_behavior_set_key_hash(ptr, (memcached_hash_t)(data));
-
-  case MEMCACHED_BEHAVIOR_KETAMA_HASH:
-    return memcached_behavior_set_distribution_hash(ptr, (memcached_hash_t)(data));
-
-  case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS:
-    return memcached_set_error(*ptr, MEMCACHED_DEPRECATED, MEMCACHED_AT,
-                                      memcached_literal_param("MEMCACHED_BEHAVIOR_CACHE_LOOKUPS has been deprecated."));
-
-  case MEMCACHED_BEHAVIOR_VERIFY_KEY:
-    if (ptr->flags.binary_protocol)
-    {
-      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
-                                        memcached_literal_param("MEMCACHED_BEHAVIOR_VERIFY_KEY if the binary protocol has been enabled."));
-    }
-    ptr->flags.verify_key= bool(data);
-    break;
-
-  case MEMCACHED_BEHAVIOR_SORT_HOSTS:
-    {
-      ptr->flags.use_sort_hosts= bool(data);
-      return run_distribution(ptr);
-    }
-
-  case MEMCACHED_BEHAVIOR_POLL_TIMEOUT:
-    ptr->poll_timeout= (int32_t)data;
-    break;
-
-  case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT:
-    ptr->connect_timeout= (int32_t)data;
-    break;
-
-  case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT:
-    ptr->retry_timeout= int32_t(data);
-    break;
-
-  case MEMCACHED_BEHAVIOR_DEAD_TIMEOUT:
-    ptr->dead_timeout= int32_t(data);
-    break;
-
-  case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE:
-    ptr->send_size= (int32_t)data;
-    send_quit(ptr);
-    break;
-
-  case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE:
-    ptr->recv_size= (int32_t)data;
-    send_quit(ptr);
-    break;
-
-  case MEMCACHED_BEHAVIOR_TCP_KEEPIDLE:
-    ptr->tcp_keepidle= (uint32_t)data;
-    send_quit(ptr);
-    break;
-
-  case MEMCACHED_BEHAVIOR_USER_DATA:
-    return memcached_set_error(*ptr, MEMCACHED_DEPRECATED, MEMCACHED_AT,
-                               memcached_literal_param("MEMCACHED_BEHAVIOR_USER_DATA deprecated."));
-
-  case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY:
-    ptr->flags.hash_with_namespace= bool(data);
-    break;
-
-  case MEMCACHED_BEHAVIOR_NOREPLY:
-    if (memcached_is_udp(ptr) and bool(data) == false)
-    {
-      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
-                                 memcached_literal_param("MEMCACHED_BEHAVIOR_NOREPLY cannot be disabled while MEMCACHED_BEHAVIOR_USE_UDP is enabled."));
-    }
-    // We reverse the logic here to make it easier to understand throughout the
-    // code.
-    ptr->flags.reply= bool(data) ? false : true;
-    break;
-
-  case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
-    ptr->flags.auto_eject_hosts= bool(data);
-    break;
-
-  case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ:
-      srandom((uint32_t) time(NULL));
-      ptr->flags.randomize_replica_read= bool(data);
-      break;
-
-  case MEMCACHED_BEHAVIOR_CORK:
-      return memcached_set_error(*ptr, MEMCACHED_DEPRECATED, MEMCACHED_AT,
-                                 memcached_literal_param("MEMCACHED_BEHAVIOR_CORK is now incorporated into the driver by default."));
-
-  case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE:
-      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
-                                 memcached_literal_param("MEMCACHED_BEHAVIOR_LOAD_FROM_FILE can not be set with memcached_behavior_set()"));
-
-  case MEMCACHED_BEHAVIOR_MAX:
-  default:
-      /* Shouldn't get here */
-      assert_msg(0, "Invalid behavior passed to memcached_behavior_set()");
-      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
-                                 memcached_literal_param("Invalid behavior passed to memcached_behavior_set()"));
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-bool _is_auto_eject_host(const memcached_st *ptr)
-{
-  return ptr->flags.auto_eject_hosts;
-}
-
-uint64_t memcached_behavior_get(memcached_st *shell,
-                                const memcached_behavior_t flag)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  if (ptr == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  switch (flag)
-  {
-  case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
-    return ptr->number_of_replicas;
-
-  case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK:
-    return ptr->io_msg_watermark;
-
-  case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK:
-    return ptr->io_bytes_watermark;
-
-  case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH:
-    return ptr->io_key_prefetch;
-
-  case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL:
-    return ptr->flags.binary_protocol;
-
-  case MEMCACHED_BEHAVIOR_SUPPORT_CAS:
-    return ptr->flags.support_cas;
-
-  case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS:
-    return true;
-
-  case MEMCACHED_BEHAVIOR_NO_BLOCK:
-    return ptr->flags.no_block;
-
-  case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS:
-    return ptr->flags.buffer_requests;
-
-  case MEMCACHED_BEHAVIOR_USE_UDP:
-    return memcached_is_udp(ptr);
-
-  case MEMCACHED_BEHAVIOR_TCP_NODELAY:
-    return ptr->flags.tcp_nodelay;
-
-  case MEMCACHED_BEHAVIOR_VERIFY_KEY:
-    return ptr->flags.verify_key;
-
-  case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED:
-    if (memcached_is_consistent_distribution(ptr))
-    {
-      return memcached_is_weighted_ketama(ptr);
-    }
-    return false;
-
-  case MEMCACHED_BEHAVIOR_DISTRIBUTION:
-    return ptr->distribution;
-
-  case MEMCACHED_BEHAVIOR_KETAMA:
-    return memcached_is_consistent_distribution(ptr);
-
-  case MEMCACHED_BEHAVIOR_HASH:
-    return hashkit_get_function(&ptr->hashkit);
-
-  case MEMCACHED_BEHAVIOR_KETAMA_HASH:
-    return hashkit_get_function(&ptr->hashkit);
-
-  case MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS:
-    return ptr->flags.auto_eject_hosts;
-
-  case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
-    return ptr->server_failure_limit;
-
-  case MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT:
-    return ptr->server_timeout_limit;
-
-  case MEMCACHED_BEHAVIOR_SORT_HOSTS:
-    return ptr->flags.use_sort_hosts;
-
-  case MEMCACHED_BEHAVIOR_POLL_TIMEOUT:
-    return (uint64_t)ptr->poll_timeout;
-
-  case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT:
-    return (uint64_t)ptr->connect_timeout;
-
-  case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT:
-    return (uint64_t)ptr->retry_timeout;
-
-  case MEMCACHED_BEHAVIOR_DEAD_TIMEOUT:
-    return uint64_t(ptr->dead_timeout);
-
-  case MEMCACHED_BEHAVIOR_SND_TIMEOUT:
-    return (uint64_t)ptr->snd_timeout;
-
-  case MEMCACHED_BEHAVIOR_RCV_TIMEOUT:
-    return (uint64_t)ptr->rcv_timeout;
-
-  case MEMCACHED_BEHAVIOR_TCP_KEEPIDLE:
-    return (uint64_t)ptr->tcp_keepidle;
-
-  case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE:
-    {
-      int sock_size= 0;
-      socklen_t sock_length= sizeof(int);
-
-      if (ptr->send_size != -1) // If value is -1 then we are using the default
-      {
-        return (uint64_t) ptr->send_size;
-      }
-
-      memcached_instance_st* instance= memcached_instance_fetch(ptr, 0);
-
-      if (instance) // If we have an instance we test, otherwise we just set and pray
-      {
-        /* REFACTOR */
-        /* We just try the first host, and if it is down we return zero */
-        if (memcached_failed(memcached_connect(instance)))
-        {
-          return 0;
-        }
-
-        if (memcached_failed(memcached_io_wait_for_write(instance)))
-        {
-          return 0;
-        }
-
-        if (getsockopt(instance->fd, SOL_SOCKET, SO_SNDBUF, (char*)&sock_size, &sock_length) < 0)
-        {
-          memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
-          return 0; /* Zero means error */
-        }
-      }
-
-      return (uint64_t) sock_size;
-    }
-
-  case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE:
-    {
-      int sock_size= 0;
-      socklen_t sock_length= sizeof(int);
-
-      if (ptr->recv_size != -1) // If value is -1 then we are using the default
-        return (uint64_t) ptr->recv_size;
-
-      memcached_instance_st* instance= memcached_instance_fetch(ptr, 0);
-
-      /**
-        @note REFACTOR
-      */
-      if (instance)
-      {
-        /* We just try the first host, and if it is down we return zero */
-        if (memcached_failed(memcached_connect(instance)))
-        {
-          return 0;
-        }
-
-        if (memcached_failed(memcached_io_wait_for_write(instance)))
-        {
-          return 0;
-        }
-
-        if (getsockopt(instance->fd, SOL_SOCKET, SO_RCVBUF, (char*)&sock_size, &sock_length) < 0)
-        {
-          memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
-          return 0; /* Zero means error */
-        }
-      }
-
-      return (uint64_t) sock_size;
-    }
-
-  case MEMCACHED_BEHAVIOR_USER_DATA:
-    memcached_set_error(*ptr, MEMCACHED_DEPRECATED, MEMCACHED_AT,
-                        memcached_literal_param("MEMCACHED_BEHAVIOR_USER_DATA deprecated."));
-    return 0;
-
-  case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY:
-    return ptr->flags.hash_with_namespace;
-
-  case MEMCACHED_BEHAVIOR_NOREPLY:
-    return ptr->flags.reply ? false : true;
-
-  case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
-    return ptr->flags.auto_eject_hosts;
-
-  case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ:
-    return ptr->flags.randomize_replica_read;
-
-  case MEMCACHED_BEHAVIOR_CORK:
-#ifdef HAVE_MSG_MORE
-    return true;
-#else
-    return false;
-#endif
-
-  case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE:
-    return ptr->flags.tcp_keepalive;
-
-  case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE:
-    return bool(memcached_parse_filename(ptr));
-
-  case MEMCACHED_BEHAVIOR_MAX:
-  default:
-    assert_msg(0, "Invalid behavior passed to memcached_behavior_get()");
-    return 0;
-  }
-
-  /* NOTREACHED */
-}
-
-
-memcached_return_t memcached_behavior_set_distribution(memcached_st *shell, memcached_server_distribution_t type)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  if (ptr)
-  {
-    switch (type)
-    {
-    case MEMCACHED_DISTRIBUTION_MODULA:
-      break;
-
-    case MEMCACHED_DISTRIBUTION_CONSISTENT:
-    case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
-      memcached_set_weighted_ketama(ptr, false);
-      break;
-
-    case MEMCACHED_DISTRIBUTION_RANDOM:
-      break;
-
-    case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
-      break;
-
-    case MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED:
-      memcached_set_weighted_ketama(ptr, true);
-      break;
-
-    case MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET:
-      break;
-
-    default:
-    case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX:
-      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
-                                 memcached_literal_param("Invalid memcached_server_distribution_t"));
-    }
-    ptr->distribution= type;
-
-    return run_distribution(ptr);
-  }
-
-  return MEMCACHED_INVALID_ARGUMENTS;
-}
-
-
-memcached_server_distribution_t memcached_behavior_get_distribution(memcached_st *shell)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  if (ptr)
-  {
-    return ptr->distribution;
-  }
-
-  return MEMCACHED_DISTRIBUTION_CONSISTENT_MAX;
-}
-
-memcached_return_t memcached_behavior_set_key_hash(memcached_st *shell, memcached_hash_t type)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  if (ptr)
-  {
-    if (hashkit_success(hashkit_set_function(&ptr->hashkit, (hashkit_hash_algorithm_t)type)))
-    {
-      return MEMCACHED_SUCCESS;
-    }
-
-    return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
-                               memcached_literal_param("Invalid memcached_hash_t()"));
-  }
-
-  return MEMCACHED_INVALID_ARGUMENTS;
-}
-
-memcached_hash_t memcached_behavior_get_key_hash(memcached_st *shell)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  if (ptr)
-  {
-    return (memcached_hash_t)hashkit_get_function(&ptr->hashkit);
-  }
-
-  return MEMCACHED_HASH_MAX;
-}
-
-memcached_return_t memcached_behavior_set_distribution_hash(memcached_st *shell, memcached_hash_t type)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  if (ptr)
-  {
-    if (hashkit_success(hashkit_set_distribution_function(&ptr->hashkit, (hashkit_hash_algorithm_t)type)))
-    {
-      return MEMCACHED_SUCCESS;
-    }
-
-    return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
-                               memcached_literal_param("Invalid memcached_hash_t()"));
-  }
-
-  return MEMCACHED_INVALID_ARGUMENTS;
-}
-
-memcached_hash_t memcached_behavior_get_distribution_hash(memcached_st *shell)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  if (ptr)
-  {
-    return (memcached_hash_t)hashkit_get_function(&ptr->hashkit);
-  }
-
-  return MEMCACHED_HASH_MAX;
-}
-
-const char *libmemcached_string_behavior(const memcached_behavior_t flag)
-{
-  switch (flag)
-  {
-  case MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT: return "MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT";
-  case MEMCACHED_BEHAVIOR_NO_BLOCK: return "MEMCACHED_BEHAVIOR_NO_BLOCK";
-  case MEMCACHED_BEHAVIOR_TCP_NODELAY: return "MEMCACHED_BEHAVIOR_TCP_NODELAY";
-  case MEMCACHED_BEHAVIOR_HASH: return "MEMCACHED_BEHAVIOR_HASH";
-  case MEMCACHED_BEHAVIOR_KETAMA: return "MEMCACHED_BEHAVIOR_KETAMA";
-  case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: return "MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE";
-  case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE: return "MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE";
-  case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS: return "MEMCACHED_BEHAVIOR_CACHE_LOOKUPS";
-  case MEMCACHED_BEHAVIOR_SUPPORT_CAS: return "MEMCACHED_BEHAVIOR_SUPPORT_CAS";
-  case MEMCACHED_BEHAVIOR_POLL_TIMEOUT: return "MEMCACHED_BEHAVIOR_POLL_TIMEOUT";
-  case MEMCACHED_BEHAVIOR_DISTRIBUTION: return "MEMCACHED_BEHAVIOR_DISTRIBUTION";
-  case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS: return "MEMCACHED_BEHAVIOR_BUFFER_REQUESTS";
-  case MEMCACHED_BEHAVIOR_USER_DATA: return "MEMCACHED_BEHAVIOR_USER_DATA";
-  case MEMCACHED_BEHAVIOR_SORT_HOSTS: return "MEMCACHED_BEHAVIOR_SORT_HOSTS";
-  case MEMCACHED_BEHAVIOR_VERIFY_KEY: return "MEMCACHED_BEHAVIOR_VERIFY_KEY";
-  case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT: return "MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT";
-  case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT: return "MEMCACHED_BEHAVIOR_RETRY_TIMEOUT";
-  case MEMCACHED_BEHAVIOR_DEAD_TIMEOUT: return "MEMCACHED_BEHAVIOR_DEAD_TIMEOUT";
-  case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED: return "MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED";
-  case MEMCACHED_BEHAVIOR_KETAMA_HASH: return "MEMCACHED_BEHAVIOR_KETAMA_HASH";
-  case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL: return "MEMCACHED_BEHAVIOR_BINARY_PROTOCOL";
-  case MEMCACHED_BEHAVIOR_SND_TIMEOUT: return "MEMCACHED_BEHAVIOR_SND_TIMEOUT";
-  case MEMCACHED_BEHAVIOR_RCV_TIMEOUT: return "MEMCACHED_BEHAVIOR_RCV_TIMEOUT";
-  case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT: return "MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT";
-  case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK: return "MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK";
-  case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK: return "MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK";
-  case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH: return "MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH";
-  case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY: return "MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY";
-  case MEMCACHED_BEHAVIOR_NOREPLY: return "MEMCACHED_BEHAVIOR_NOREPLY";
-  case MEMCACHED_BEHAVIOR_USE_UDP: return "MEMCACHED_BEHAVIOR_USE_UDP";
-  case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS: return "MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS";
-  case MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS: return "MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS";
-  case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS: return "MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS";
-  case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ: return "MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ";
-  case MEMCACHED_BEHAVIOR_CORK: return "MEMCACHED_BEHAVIOR_CORK";
-  case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE: return "MEMCACHED_BEHAVIOR_TCP_KEEPALIVE";
-  case MEMCACHED_BEHAVIOR_TCP_KEEPIDLE: return "MEMCACHED_BEHAVIOR_TCP_KEEPIDLE";
-  case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE: return "MEMCACHED_BEHAVIOR_LOAD_FROM_FILE";
-  default:
-  case MEMCACHED_BEHAVIOR_MAX: return "INVALID memcached_behavior_t";
-  }
-}
-
-const char *libmemcached_string_distribution(const memcached_server_distribution_t flag)
-{
-  switch (flag)
-  {
-  case MEMCACHED_DISTRIBUTION_MODULA: return "MEMCACHED_DISTRIBUTION_MODULA";
-  case MEMCACHED_DISTRIBUTION_CONSISTENT: return "MEMCACHED_DISTRIBUTION_CONSISTENT";
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA: return "MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA";
-  case MEMCACHED_DISTRIBUTION_RANDOM: return "MEMCACHED_DISTRIBUTION_RANDOM";
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY: return "MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY";
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED: return "MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED";
-  case MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET: return "MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET";
-  default:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX: return "INVALID memcached_server_distribution_t";
-  }
-}
-
-memcached_return_t memcached_bucket_set(memcached_st *shell,
-                                        const uint32_t *host_map,
-                                        const uint32_t *forward_map,
-                                        const uint32_t buckets,
-                                        const uint32_t replicas)
-{
-  Memcached* self= memcached2Memcached(shell);
-  memcached_return_t rc;
-
-  if (self == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  if (host_map == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  memcached_server_distribution_t old= memcached_behavior_get_distribution(self);
-
-  if (memcached_failed(rc =memcached_behavior_set_distribution(self, MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET)))
-  {
-    return rc;
-  }
-
-  if (memcached_failed(rc= memcached_virtual_bucket_create(self, host_map, forward_map, buckets, replicas)))
-  {
-    memcached_behavior_set_distribution(self, old);
-  }
-
-  return rc;
-}
diff --git a/libmemcached/behavior.hpp b/libmemcached/behavior.hpp
deleted file mode 100644 (file)
index 0b06c0c..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-bool memcached_is_consistent_distribution(const memcached_st*);
-bool _is_auto_eject_host(const memcached_st *ptr);
diff --git a/libmemcached/byteorder.cc b/libmemcached/byteorder.cc
deleted file mode 100644 (file)
index 44500ad..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "mem_config.h"
-#include "libmemcached/byteorder.h"
-
-/* Byte swap a 64-bit number. */
-#ifndef swap64
-static inline uint64_t swap64(uint64_t in)
-{
-#ifndef WORDS_BIGENDIAN
-  /* Little endian, flip the bytes around until someone makes a faster/better
-   * way to do this. */
-  uint64_t rv= 0;
-  for (uint8_t x= 0; x < 8; ++x)
-  {
-    rv= (rv << 8) | (in & 0xff);
-    in >>= 8;
-  }
-  return rv;
-#else
-  /* big-endian machines don't need byte swapping */
-  return in;
-#endif // WORDS_BIGENDIAN
-}
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-uint64_t memcached_ntohll(uint64_t value)
-{
-#ifdef HAVE_HTONLL
-  return ntohll(value);
-#else
-  return swap64(value);
-#endif
-}
-
-uint64_t memcached_htonll(uint64_t value)
-{
-#ifdef HAVE_HTONLL
-  return htonll(value);
-#else
-  return swap64(value);
-#endif
-}
diff --git a/libmemcached/byteorder.h b/libmemcached/byteorder.h
deleted file mode 100644 (file)
index a7d108d..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-uint64_t memcached_ntohll(uint64_t);
-
-uint64_t memcached_htonll(uint64_t);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached/callback.cc b/libmemcached/callback.cc
deleted file mode 100644 (file)
index a43eef9..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Change any of the possible callbacks.
- *
- */
-
-#include <libmemcached/common.h>
-#include <sys/types.h>
-
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wstrict-aliasing"
-#endif
-
-/*
-  These functions provide data and function callback support
-*/
-
-memcached_return_t memcached_callback_set(memcached_st *shell,
-                                          const memcached_callback_t flag,
-                                          const void *data)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  if (ptr)
-  {
-    switch (flag)
-    {
-    case MEMCACHED_CALLBACK_PREFIX_KEY:
-      {
-        return memcached_set_namespace(*ptr, (char*)data, data ? strlen((char*)data) : 0);
-      }
-
-    case MEMCACHED_CALLBACK_USER_DATA:
-      {
-        ptr->user_data= const_cast<void *>(data);
-        break;
-      }
-
-    case MEMCACHED_CALLBACK_CLEANUP_FUNCTION:
-      {
-        memcached_cleanup_fn func= *(memcached_cleanup_fn *)&data;
-        ptr->on_cleanup= func;
-        break;
-      }
-
-    case MEMCACHED_CALLBACK_CLONE_FUNCTION:
-      {
-        memcached_clone_fn func= *(memcached_clone_fn *)&data;
-        ptr->on_clone= func;
-        break;
-      }
-
-    case MEMCACHED_CALLBACK_GET_FAILURE:
-      {
-        memcached_trigger_key_fn func= *(memcached_trigger_key_fn *)&data;
-        ptr->get_key_failure= func;
-        break;
-      }
-
-    case MEMCACHED_CALLBACK_DELETE_TRIGGER:
-      {
-        if (data) // NULL would mean we are disabling.
-        {
-          if (memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS)) 
-          {
-            return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Delete triggers cannot be used if buffering is enabled"));
-          }
-
-          if (memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_NOREPLY)) 
-          {
-            return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Delete triggers cannot be used if MEMCACHED_BEHAVIOR_NOREPLY is set"));
-          }
-        }
-
-        memcached_trigger_delete_key_fn func= *(memcached_trigger_delete_key_fn *)&data;
-        ptr->delete_trigger= func;
-        break;
-      }
-
-    case MEMCACHED_CALLBACK_MAX:
-      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid callback supplied"));
-    }
-
-    return MEMCACHED_SUCCESS;
-  }
-
-  return MEMCACHED_INVALID_ARGUMENTS;
-}
-
-void *memcached_callback_get(memcached_st *shell,
-                             const memcached_callback_t flag,
-                             memcached_return_t *error)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  memcached_return_t local_error;
-  if (error == NULL)
-  {
-    error = &local_error;
-  }
-
-  if (ptr == NULL)
-  {
-    *error= MEMCACHED_INVALID_ARGUMENTS;
-    return NULL;
-  }
-
-  switch (flag)
-  {
-  case MEMCACHED_CALLBACK_PREFIX_KEY:
-    {
-      *error= MEMCACHED_SUCCESS;
-      if (ptr->_namespace)
-      {
-        return (void *)memcached_array_string(ptr->_namespace);
-      }
-      return NULL;
-    }
-
-  case MEMCACHED_CALLBACK_USER_DATA:
-    {
-      *error= ptr->user_data ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
-      return (void *)ptr->user_data;
-    }
-
-  case MEMCACHED_CALLBACK_CLEANUP_FUNCTION:
-    {
-      *error= ptr->on_cleanup ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
-      return *(void **)&ptr->on_cleanup;
-    }
-
-  case MEMCACHED_CALLBACK_CLONE_FUNCTION:
-    {
-      *error= ptr->on_clone ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
-      return *(void **)&ptr->on_clone;
-    }
-
-  case MEMCACHED_CALLBACK_GET_FAILURE:
-    {
-      *error= ptr->get_key_failure ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
-      return *(void **)&ptr->get_key_failure;
-    }
-
-  case MEMCACHED_CALLBACK_DELETE_TRIGGER:
-    {
-      *error= ptr->delete_trigger ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
-      return *(void **)&ptr->delete_trigger;
-    }
-
-  case MEMCACHED_CALLBACK_MAX:
-    break;
-  }
-
-  assert_msg(0, "Invalid callback passed to memcached_callback_get()");
-  *error= MEMCACHED_FAILURE;
-  return NULL;
-}
diff --git a/libmemcached/callback.h b/libmemcached/callback.h
deleted file mode 100644 (file)
index 3949ea3..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached Client and Server 
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-test_return_t test_MEMCACHED_CALLBACK_DELETE_TRIGGER(memcached_st *);
-
-test_return_t test_MEMCACHED_CALLBACK_DELETE_TRIGGER_and_MEMCACHED_BEHAVIOR_NOREPLY(memcached_st *);
diff --git a/libmemcached/common.h b/libmemcached/common.h
deleted file mode 100644 (file)
index 8cedc52..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
-  Common include file for libmemached
-*/
-
-#pragma once
-
-#include <mem_config.h>
-
-#ifdef __cplusplus
-# include <cstddef>
-# include <cstdio>
-# include <cstdlib>
-# include <cstring>
-# include <ctime>
-# include <cctype>
-# include <cerrno>
-# include <climits>
-#else
-# ifdef HAVE_STDDEF_H
-#  include <stddef.h>
-# endif
-# ifdef HAVE_STDLIB_H
-#  include <stdio.h>
-# endif
-# ifdef HAVE_STDLIB_H
-#  include <stdlib.h>
-# endif
-# include <string.h>
-# ifdef HAVE_TIME_H
-#  include <time.h>
-# endif
-# ifdef HAVE_ERRNO_H
-#  include <errno.h>
-# endif
-# ifdef HAVE_LIMITS_H
-#  include <limits.h>
-# endif
-#endif
-
-#ifdef HAVE_SYS_UN_H
-# include <sys/un.h>
-#endif
-
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-
-#ifdef HAVE_DLFCN_H
-# include <dlfcn.h>
-#endif
-
-#if defined(_WIN32)
-# include "libmemcached/windows.hpp"
-#endif
-
-#include <libmemcached-1.0/memcached.h>
-#include "libmemcached/watchpoint.h"
-#include "libmemcached/is.h"
-typedef struct memcached_st Memcached;
-
-#ifdef HAVE_POLL_H
-# include <poll.h>
-#else
-# include "libmemcached/poll.h"
-#endif
-
-#ifdef __cplusplus
-memcached_instance_st* memcached_instance_fetch(memcached_st *ptr, uint32_t server_key);
-#endif
-
-/* These are private not to be installed headers */
-#include "libmemcached/error.hpp"
-#include "libmemcached/memory.h"
-#include "libmemcached/io.h"
-#ifdef __cplusplus
-# include "libmemcached/string.hpp"
-# include "libmemcachedprotocol-0.0/binary.h"
-# include "libmemcached/io.hpp"
-# include "libmemcached/udp.hpp"
-# include "libmemcached/do.hpp"
-# include "libmemcached/socket.hpp"
-# include "libmemcached/connect.hpp"
-# include "libmemcached/allocators.hpp"
-# include "libmemcached/hash.hpp"
-# include "libmemcached/quit.hpp"
-# include "libmemcached/instance.hpp"
-# include "libmemcached/server_instance.h"
-# include "libmemcached/server.hpp"
-# include "libmemcached/flag.hpp"
-# include "libmemcached/behavior.hpp"
-# include "libmemcached/sasl.hpp"
-# include "libmemcached/server_list.hpp"
-#endif
-
-#include "libmemcached/internal.h"
-#include "libmemcached/array.h"
-#include "libmemcached/libmemcached_probes.h"
-#include "libmemcached/byteorder.h"
-#include "libmemcached/initialize_query.h"
-
-#ifdef __cplusplus
-# include "libmemcached/response.h"
-# include "libmemcached/namespace.h"
-#else
-# include "libmemcached/virtual_bucket.h"
-#endif
-
-#ifdef __cplusplus
-# include "libmemcached/backtrace.hpp"
-# include "libmemcached/assert.hpp"
-# include "libmemcached/server.hpp"
-# include "libmemcached/key.hpp"
-# include "libmemcached/encoding_key.h"
-# include "libmemcached/result.h"
-# include "libmemcached/version.hpp"
-#endif
-
-#include "libmemcached/continuum.hpp"
-
-#if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
-
-#define likely(x)       if((x))
-#define unlikely(x)     if((x))
-
-#else
-
-#define likely(x)       if(__builtin_expect((x) != 0, 1))
-#define unlikely(x)     if(__builtin_expect((x) != 0, 0))
-#endif
-
-#define MEMCACHED_BLOCK_SIZE 1024
-#define MEMCACHED_DEFAULT_COMMAND_SIZE 350
-#define SMALL_STRING_LEN 1024
-#define HUGE_STRING_LEN 8196
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-memcached_return_t run_distribution(memcached_st *ptr);
-
-#ifdef __cplusplus
-static inline void memcached_server_response_increment(memcached_instance_st* instance)
-{
-  instance->events(POLLIN);
-  instance->cursor_active_++;
-}
-#endif
-
-#define memcached_server_response_decrement(A) (A)->cursor_active_--
-#define memcached_server_response_reset(A) (A)->cursor_active_=0
-
-#define memcached_instance_response_increment(A) (A)->cursor_active_++
-#define memcached_instance_response_decrement(A) (A)->cursor_active_--
-#define memcached_instance_response_reset(A) (A)->cursor_active_=0
-
-#ifdef __cplusplus
-}
-#endif
-
-#ifdef __cplusplus
-bool memcached_purge(memcached_instance_st*);
-memcached_instance_st* memcached_instance_by_position(const memcached_st *ptr, uint32_t server_key);
-#endif
diff --git a/libmemcached/connect.cc b/libmemcached/connect.cc
deleted file mode 100644 (file)
index 1cfe794..0000000
+++ /dev/null
@@ -1,818 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libmemcached/common.h>
-
-#include <cassert>
-
-#ifndef SOCK_CLOEXEC 
-#  define SOCK_CLOEXEC 0
-#endif
-
-#ifndef SOCK_NONBLOCK 
-# define SOCK_NONBLOCK 0
-#endif
-
-#ifndef FD_CLOEXEC
-# define FD_CLOEXEC 0
-#endif
-
-#ifndef SO_NOSIGPIPE
-# define SO_NOSIGPIPE 0
-#endif
-
-#ifndef TCP_NODELAY
-# define TCP_NODELAY 0
-#endif
-
-#ifndef TCP_KEEPIDLE
-# define TCP_KEEPIDLE 0
-#endif
-
-static memcached_return_t connect_poll(memcached_instance_st* server, const int connection_error)
-{
-  struct pollfd fds[1];
-  fds[0].fd= server->fd;
-  fds[0].events= server->events();
-  fds[0].revents= 0;
-
-  size_t loop_max= 5;
-
-  if (server->root->poll_timeout == 0)
-  {
-    return memcached_set_error(*server, MEMCACHED_TIMEOUT, MEMCACHED_AT,
-                               memcached_literal_param("The time to wait for a connection to be established was set to zero which produces a timeout to every call to poll()."));
-  }
-
-  while (--loop_max) // Should only loop on cases of ERESTART or EINTR
-  {
-    int number_of;
-    if ((number_of= poll(fds, 1, server->root->connect_timeout)) == -1)
-    {
-      int local_errno= get_socket_errno(); // We cache in case closesocket() modifies errno
-      switch (local_errno)
-      {
-#ifdef __linux__
-      case ERESTART:
-#endif
-      case EINTR:
-        continue;
-
-      case EFAULT:
-      case ENOMEM:
-        return memcached_set_error(*server, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-
-      case EINVAL:
-        return memcached_set_error(*server, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
-                                   memcached_literal_param("RLIMIT_NOFILE exceeded, or if OSX the timeout value was invalid"));
-
-      default: // This should not happen
-        break;
-      }
-
-      assert_msg(server->fd != INVALID_SOCKET, "poll() was passed an invalid file descriptor");
-      server->reset_socket();
-      server->state= MEMCACHED_SERVER_STATE_NEW;
-
-      return memcached_set_errno(*server, local_errno, MEMCACHED_AT);
-    }
-
-    if (number_of == 0)
-    {
-      if (connection_error == EINPROGRESS)
-      {
-        int err;
-        socklen_t len= sizeof(err);
-        if (getsockopt(server->fd, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == -1)
-        {
-          return memcached_set_errno(*server, errno, MEMCACHED_AT, memcached_literal_param("getsockopt() error'ed while looking for error connect_poll(EINPROGRESS)"));
-        }
-
-        // If Zero, my hero, we just fail to a generic MEMCACHED_TIMEOUT error
-        if (err != 0)
-        {
-          return memcached_set_errno(*server, err, MEMCACHED_AT, memcached_literal_param("getsockopt() found the error from poll() after connect() returned EINPROGRESS."));
-        }
-      }
-
-      return  memcached_set_error(*server, MEMCACHED_TIMEOUT, MEMCACHED_AT, memcached_literal_param("(number_of == 0)"));
-    }
-
-    assert (number_of == 1);
-
-    if (fds[0].revents & POLLERR or
-        fds[0].revents & POLLHUP or 
-        fds[0].revents & POLLNVAL)
-    {
-      int err;
-      socklen_t len= sizeof (err);
-      if (getsockopt(fds[0].fd, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == -1)
-      {
-        return memcached_set_errno(*server, errno, MEMCACHED_AT, memcached_literal_param("getsockopt() errored while looking up error state from poll()"));
-      }
-
-      // We check the value to see what happened with the socket.
-      if (err == 0) // Should not happen
-      {
-        return MEMCACHED_SUCCESS;
-      }
-      errno= err;
-
-      return memcached_set_errno(*server, err, MEMCACHED_AT, memcached_literal_param("getsockopt() found the error from poll() during connect."));
-    }
-    assert(fds[0].revents & POLLOUT);
-
-    if (fds[0].revents & POLLOUT and connection_error == EINPROGRESS)
-    {
-      int err;
-      socklen_t len= sizeof(err);
-      if (getsockopt(server->fd, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == -1)
-      {
-        return memcached_set_errno(*server, errno, MEMCACHED_AT);
-      }
-
-      if (err == 0)
-      {
-        return MEMCACHED_SUCCESS;
-      }
-
-      return memcached_set_errno(*server, err, MEMCACHED_AT, memcached_literal_param("getsockopt() found the error from poll() after connect() returned EINPROGRESS."));
-    }
-
-    break; // We only have the loop setup for errno types that require restart
-  }
-
-  // This should only be possible from ERESTART or EINTR;
-  return memcached_set_errno(*server, connection_error, MEMCACHED_AT, memcached_literal_param("connect_poll() was exhausted"));
-}
-
-static memcached_return_t set_hostinfo(memcached_instance_st* server)
-{
-  assert(server->type != MEMCACHED_CONNECTION_UNIX_SOCKET);
-  server->clear_addrinfo();
-
-  char str_port[MEMCACHED_NI_MAXSERV]= { 0 };
-  errno= 0;
-  int length= snprintf(str_port, MEMCACHED_NI_MAXSERV, "%u", uint32_t(server->port()));
-  if (length >= MEMCACHED_NI_MAXSERV or length <= 0 or errno != 0)
-  {
-    return memcached_set_error(*server, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                               memcached_literal_param("snprintf(NI_MAXSERV)"));
-  }
-
-  struct addrinfo hints;
-  memset(&hints, 0, sizeof(struct addrinfo));
-
-  hints.ai_family= AF_UNSPEC;
-  if (memcached_is_udp(server->root))
-  {
-    hints.ai_protocol= IPPROTO_UDP;
-    hints.ai_socktype= SOCK_DGRAM;
-  }
-  else
-  {
-    hints.ai_socktype= SOCK_STREAM;
-    hints.ai_protocol= IPPROTO_TCP;
-  }
-
-  assert(server->address_info == NULL);
-  assert(server->address_info_next == NULL);
-  int errcode;
-  assert(server->hostname());
-  switch(errcode= getaddrinfo(server->hostname(), str_port, &hints, &server->address_info))
-  {
-  case 0:
-    server->address_info_next= server->address_info;
-    server->state= MEMCACHED_SERVER_STATE_ADDRINFO;
-    break;
-
-  case EAI_AGAIN:
-    return memcached_set_error(*server, MEMCACHED_TIMEOUT, MEMCACHED_AT, memcached_string_make_from_cstr(gai_strerror(errcode)));
-
-  case EAI_SYSTEM:
-    server->clear_addrinfo();
-    return memcached_set_errno(*server, errno, MEMCACHED_AT, memcached_literal_param("getaddrinfo(EAI_SYSTEM)"));
-
-  case EAI_BADFLAGS:
-    server->clear_addrinfo();
-    return memcached_set_error(*server, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("getaddrinfo(EAI_BADFLAGS)"));
-
-  case EAI_MEMORY:
-    server->clear_addrinfo();
-    return memcached_set_error(*server, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, memcached_literal_param("getaddrinfo(EAI_MEMORY)"));
-
-  default:
-    {
-      server->clear_addrinfo();
-      return memcached_set_error(*server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT, memcached_string_make_from_cstr(gai_strerror(errcode)));
-    }
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-static inline void set_socket_nonblocking(memcached_instance_st* server)
-{
-#if defined(_WIN32)
-  u_long arg= 1;
-  if (ioctlsocket(server->fd, FIONBIO, &arg) == SOCKET_ERROR)
-  {
-    memcached_set_errno(*server, get_socket_errno(), NULL);
-  }
-#else
-  int flags;
-
-  if (SOCK_NONBLOCK == 0)
-  {
-    do
-    {
-      flags= fcntl(server->fd, F_GETFL, 0);
-    } while (flags == -1 && (errno == EINTR || errno == EAGAIN));
-
-    if (flags == -1)
-    {
-      memcached_set_errno(*server, errno, NULL);
-    }
-    else if ((flags & O_NONBLOCK) == 0)
-    {
-      int rval;
-
-      do
-      {
-        rval= fcntl(server->fd, F_SETFL, flags | O_NONBLOCK);
-      } while (rval == -1 && (errno == EINTR or errno == EAGAIN));
-
-      if (rval == -1)
-      {
-        memcached_set_errno(*server, errno, NULL);
-      }
-    }
-  }
-#endif
-}
-
-static bool set_socket_options(memcached_instance_st* server)
-{
-  assert_msg(server->fd != INVALID_SOCKET, "invalid socket was passed to set_socket_options()");
-
-#ifdef HAVE_FCNTL
-  // If SOCK_CLOEXEC exists then we don't need to call the following
-  if (SOCK_CLOEXEC == 0)
-  {
-    if (FD_CLOEXEC != 0)
-    {
-      int flags;
-      do
-      { 
-        flags= fcntl(server->fd, F_GETFD, 0);
-      } while (flags == -1 and (errno == EINTR or errno == EAGAIN));
-
-      if (flags != -1)
-      { 
-        int rval;
-        do
-        { 
-          rval= fcntl (server->fd, F_SETFD, flags | FD_CLOEXEC);
-        } while (rval == -1 && (errno == EINTR or errno == EAGAIN));
-        // we currently ignore the case where rval is -1
-      }
-    }
-  }
-#endif
-
-  if (memcached_is_udp(server->root))
-  {
-    return true;
-  }
-
-#ifdef HAVE_SNDTIMEO
-  if (server->root->snd_timeout > 0)
-  {
-    struct timeval waittime;
-
-    waittime.tv_sec= server->root->snd_timeout / 1000000;
-    waittime.tv_usec= server->root->snd_timeout % 1000000;
-
-    int error= setsockopt(server->fd, SOL_SOCKET, SO_SNDTIMEO,
-                          (char*)&waittime, (socklen_t)sizeof(struct timeval));
-    (void)error;
-    assert(error == 0);
-  }
-#endif
-
-#ifdef HAVE_RCVTIMEO
-  if (server->root->rcv_timeout > 0)
-  {
-    struct timeval waittime;
-
-    waittime.tv_sec= server->root->rcv_timeout / 1000000;
-    waittime.tv_usec= server->root->rcv_timeout % 1000000;
-
-    int error= setsockopt(server->fd, SOL_SOCKET, SO_RCVTIMEO,
-                          (char*)&waittime, (socklen_t)sizeof(struct timeval));
-    (void)(error);
-    assert(error == 0);
-  }
-#endif
-
-
-#if defined(_WIN32)
-#else
-# if defined(SO_NOSIGPIPE)
-  if (SO_NOSIGPIPE)
-  {
-    int set= 1;
-    int error= setsockopt(server->fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
-
-    assert(error == 0);
-
-    // This is not considered a fatal error
-    if (error == -1)
-    {
-#if 0
-      perror("setsockopt(SO_NOSIGPIPE)");
-#endif
-    }
-  }
-# endif // SO_NOSIGPIPE
-#endif // _WIN32
-
-  if (server->root->flags.no_block)
-  {
-    struct linger linger;
-
-    linger.l_onoff= 1;
-    linger.l_linger= 0; /* By default on close() just drop the socket */
-    int error= setsockopt(server->fd, SOL_SOCKET, SO_LINGER,
-                          (char*)&linger, (socklen_t)sizeof(struct linger));
-    (void)(error);
-    assert(error == 0);
-  }
-
-  if (TCP_NODELAY)
-  {
-    if (server->root->flags.tcp_nodelay)
-    {
-      int flag= 1;
-
-      int error= setsockopt(server->fd, IPPROTO_TCP, TCP_NODELAY,
-                            (char*)&flag, (socklen_t)sizeof(int));
-      (void)(error);
-      assert(error == 0);
-    }
-  }
-
-  if (server->root->flags.tcp_keepalive)
-  {
-    int flag= 1;
-
-    int error= setsockopt(server->fd, SOL_SOCKET, SO_KEEPALIVE,
-                          (char*)&flag, (socklen_t)sizeof(int));
-    (void)(error);
-    assert(error == 0);
-  }
-
-  if (TCP_KEEPIDLE)
-  {
-    if (server->root->tcp_keepidle > 0)
-    {
-      int error= setsockopt(server->fd, IPPROTO_TCP, TCP_KEEPIDLE,
-                            (char*)&server->root->tcp_keepidle, (socklen_t)sizeof(int));
-      (void)(error);
-      assert(error == 0);
-    }
-  }
-
-  if (server->root->send_size > 0)
-  {
-    int error= setsockopt(server->fd, SOL_SOCKET, SO_SNDBUF,
-                          (char*)&server->root->send_size, (socklen_t)sizeof(int));
-    (void)(error);
-    assert(error == 0);
-  }
-
-  if (server->root->recv_size > 0)
-  {
-    int error= setsockopt(server->fd, SOL_SOCKET, SO_RCVBUF,
-                          (char*)&server->root->recv_size, (socklen_t)sizeof(int));
-    (void)(error);
-    assert(error == 0);
-  }
-
-  /* libmemcached will always use nonblocking IO to avoid write deadlocks */
-  set_socket_nonblocking(server);
-
-  return true;
-}
-
-static memcached_return_t unix_socket_connect(memcached_instance_st* server)
-{
-#ifndef _WIN32
-  WATCHPOINT_ASSERT(server->fd == INVALID_SOCKET);
-
-  do {
-    int type= SOCK_STREAM;
-    if (SOCK_CLOEXEC != 0)
-    {
-      type|= SOCK_CLOEXEC;
-    }
-
-    if (SOCK_NONBLOCK != 0)
-    {
-      type|= SOCK_NONBLOCK;
-    }
-
-    if ((server->fd= socket(AF_UNIX, type, 0)) == -1)
-    {
-      return memcached_set_errno(*server, errno, NULL);
-    }
-
-    struct sockaddr_un servAddr;
-
-    memset(&servAddr, 0, sizeof (struct sockaddr_un));
-    servAddr.sun_family= AF_UNIX;
-    if (strlen(server->hostname()) >= sizeof(servAddr.sun_path)) {
-        return memcached_set_error(*server, MEMCACHED_UNIX_SOCKET_PATH_TOO_BIG, MEMCACHED_AT);
-    }
-    strncpy(servAddr.sun_path, server->hostname(), sizeof(servAddr.sun_path)-1); /* Copy filename */
-
-    if (connect(server->fd, (struct sockaddr *)&servAddr, sizeof(servAddr)) == -1)
-    {
-      switch (errno)
-      {
-      case EINPROGRESS:
-      case EALREADY:
-      case EAGAIN:
-        server->events(POLLOUT);
-        break;
-
-      case EINTR:
-        server->reset_socket();
-        continue;
-
-      case EISCONN: /* We were spinning waiting on connect */
-        {
-          assert(0); // Programmer error
-          server->reset_socket();
-          continue;
-        }
-
-      default:
-        WATCHPOINT_ERRNO(errno);
-        server->reset_socket();
-        return memcached_set_errno(*server, errno, MEMCACHED_AT);
-      }
-    }
-  } while (0);
-  server->state= MEMCACHED_SERVER_STATE_CONNECTED;
-
-  WATCHPOINT_ASSERT(server->fd != INVALID_SOCKET);
-
-  return MEMCACHED_SUCCESS;
-#else
-  (void)server;
-  return MEMCACHED_NOT_SUPPORTED;
-#endif
-}
-
-static memcached_return_t network_connect(memcached_instance_st* server)
-{
-  bool timeout_error_occured= false;
-
-  WATCHPOINT_ASSERT(server->fd == INVALID_SOCKET);
-  WATCHPOINT_ASSERT(server->cursor_active_ == 0);
-
-  /*
-    We want to check both of these because if address_info_next has been fully tried, we want to do a new lookup to make sure we have picked up on any new DNS information.
-  */
-  if (server->address_info == NULL or server->address_info_next == NULL)
-  {
-    WATCHPOINT_ASSERT(server->state == MEMCACHED_SERVER_STATE_NEW);
-    server->address_info_next= NULL;
-    memcached_return_t rc= set_hostinfo(server);
-
-    if (memcached_failed(rc))
-    {
-      return rc;
-    }
-  }
-
-  assert(server->address_info_next);
-  assert(server->address_info);
-
-  /* Create the socket */
-  while (server->address_info_next and server->fd == INVALID_SOCKET)
-  {
-    int type= server->address_info_next->ai_socktype;
-    if (SOCK_CLOEXEC != 0)
-    {
-      type|= SOCK_CLOEXEC;
-    }
-
-    if (SOCK_NONBLOCK != 0)
-    {
-      type|= SOCK_NONBLOCK;
-    }
-
-    server->fd= socket(server->address_info_next->ai_family,
-                       type,
-                       server->address_info_next->ai_protocol);
-
-    if (int(server->fd) == SOCKET_ERROR)
-    {
-      return memcached_set_errno(*server, get_socket_errno(), NULL);
-    }
-
-    if (set_socket_options(server) == false)
-    {
-      server->reset_socket();
-      return MEMCACHED_CONNECTION_FAILURE;
-    }
-
-    /* connect to server */
-    if ((connect(server->fd, server->address_info_next->ai_addr, server->address_info_next->ai_addrlen) != SOCKET_ERROR))
-    {
-      server->state= MEMCACHED_SERVER_STATE_CONNECTED;
-      return MEMCACHED_SUCCESS;
-    }
-
-    /* An error occurred */
-    int local_error= get_socket_errno();
-    switch (local_error)
-    {
-    case ETIMEDOUT:
-      timeout_error_occured= true;
-      break;
-
-#if EWOULDBLOCK != EAGAIN
-    case EWOULDBLOCK:
-#endif
-    case EINPROGRESS: // nonblocking mode - first return
-    case EALREADY: // nonblocking mode - subsequent returns
-      {
-        server->events(POLLOUT);
-        server->state= MEMCACHED_SERVER_STATE_IN_PROGRESS;
-        memcached_return_t rc= connect_poll(server, local_error);
-
-        if (memcached_success(rc))
-        {
-          server->state= MEMCACHED_SERVER_STATE_CONNECTED;
-          return MEMCACHED_SUCCESS;
-        }
-
-        // A timeout here is treated as an error, we will not retry
-        if (rc == MEMCACHED_TIMEOUT)
-        {
-          timeout_error_occured= true;
-        }
-      }
-      break;
-
-    case EISCONN: // we are connected :-)
-      WATCHPOINT_ASSERT(0); // This is a programmer's error
-      break;
-
-    case EINTR: // Special case, we retry ai_addr
-      WATCHPOINT_ASSERT(server->fd != INVALID_SOCKET);
-      server->reset_socket();
-      continue;
-
-    case ECONNREFUSED:
-      // Probably not running service
-
-    default:
-      memcached_set_errno(*server, local_error, MEMCACHED_AT);
-      break;
-    }
-
-    WATCHPOINT_ASSERT(server->fd != INVALID_SOCKET);
-    server->reset_socket();
-    server->address_info_next= server->address_info_next->ai_next;
-  }
-
-  WATCHPOINT_ASSERT(server->fd == INVALID_SOCKET);
-
-  if (timeout_error_occured)
-  {
-    server->reset_socket();
-  }
-
-  WATCHPOINT_STRING("Never got a good file descriptor");
-
-  if (memcached_has_current_error(*server))
-  {
-    return memcached_instance_error_return(server);
-  }
-
-  if (timeout_error_occured and server->state < MEMCACHED_SERVER_STATE_IN_PROGRESS)
-  {
-    return memcached_set_error(*server, MEMCACHED_TIMEOUT, MEMCACHED_AT,
-                               memcached_literal_param("if (timeout_error_occured and server->state < MEMCACHED_SERVER_STATE_IN_PROGRESS)"));
-  }
-
-  return memcached_set_error(*server, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT); /* The last error should be from connect() */
-}
-
-
-/*
-  backoff_handling()
-
-  Based on time/failure count fail the connect without trying. This prevents waiting in a state where
-  we get caught spending cycles just waiting.
-*/
-static memcached_return_t backoff_handling(memcached_instance_st* server, bool& in_timeout)
-{
-  struct timeval curr_time;
-  bool _gettime_success= (gettimeofday(&curr_time, NULL) == 0);
-
-  /* 
-    If we hit server_failure_limit then something is completely wrong about the server.
-
-    1) If autoeject is enabled we do that.
-    2) If not? We go into timeout again, there is much else to do :(
-  */
-  if (server->server_failure_counter >= server->root->server_failure_limit)
-  {
-    /*
-      We just auto_eject if we hit this point 
-    */
-    if (_is_auto_eject_host(server->root))
-    {
-      set_last_disconnected_host(server);
-
-      // Retry dead servers if requested
-      if (_gettime_success and server->root->dead_timeout > 0)
-      {
-        server->next_retry= curr_time.tv_sec +server->root->dead_timeout;
-
-        // We only retry dead servers once before assuming failure again
-        server->server_failure_counter= server->root->server_failure_limit -1;
-      }
-
-      memcached_return_t rc;
-      if (memcached_failed(rc= run_distribution((memcached_st *)server->root)))
-      {
-        return memcached_set_error(*server, rc, MEMCACHED_AT, memcached_literal_param("Backoff handling failed during run_distribution"));
-      }
-
-      return memcached_set_error(*server, MEMCACHED_SERVER_MARKED_DEAD, MEMCACHED_AT);
-    }
-
-    server->state= MEMCACHED_SERVER_STATE_IN_TIMEOUT;
-
-    // Sanity check/setting
-    if (server->next_retry == 0)
-    {
-      server->next_retry= 1;
-    }
-  }
-
-  if (server->state == MEMCACHED_SERVER_STATE_IN_TIMEOUT)
-  {
-    /*
-      If next_retry is less then our current time, then we reset and try everything again.
-    */
-    if (_gettime_success and server->next_retry < curr_time.tv_sec)
-    {
-      server->state= MEMCACHED_SERVER_STATE_NEW;
-      server->server_timeout_counter= 0;
-    }
-    else
-    {
-      return memcached_set_error(*server, MEMCACHED_SERVER_TEMPORARILY_DISABLED, MEMCACHED_AT);
-    }
-
-    in_timeout= true;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-static memcached_return_t _memcached_connect(memcached_instance_st* server, const bool set_last_disconnected)
-{
-  assert(server);
-  if (server->fd != INVALID_SOCKET)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  LIBMEMCACHED_MEMCACHED_CONNECT_START();
-
-  bool in_timeout= false;
-  memcached_return_t rc;
-  if (memcached_failed(rc= backoff_handling(server, in_timeout)))
-  {
-    set_last_disconnected_host(server);
-    return rc;
-  }
-
-  if (LIBMEMCACHED_WITH_SASL_SUPPORT and server->root->sasl.callbacks and memcached_is_udp(server->root))
-  {
-    return memcached_set_error(*server, MEMCACHED_INVALID_HOST_PROTOCOL, MEMCACHED_AT, memcached_literal_param("SASL is not supported for UDP connections"));
-  }
-
-  if (server->hostname()[0] == '/')
-  {
-    server->type= MEMCACHED_CONNECTION_UNIX_SOCKET;
-  }
-
-  /* We need to clean up the multi startup piece */
-  switch (server->type)
-  {
-  case MEMCACHED_CONNECTION_UDP:
-  case MEMCACHED_CONNECTION_TCP:
-    rc= network_connect(server);
-
-#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT)
-    if (LIBMEMCACHED_WITH_SASL_SUPPORT)
-    {
-      if (server->fd != INVALID_SOCKET and server->root->sasl.callbacks)
-      {
-        rc= memcached_sasl_authenticate_connection(server);
-        if (memcached_failed(rc) and server->fd != INVALID_SOCKET)
-        {
-          WATCHPOINT_ASSERT(server->fd != INVALID_SOCKET);
-          server->reset_socket();
-        }
-      }
-    }
-#endif
-    break;
-
-  case MEMCACHED_CONNECTION_UNIX_SOCKET:
-    rc= unix_socket_connect(server);
-    break;
-  }
-
-  if (memcached_success(rc))
-  {
-    server->mark_server_as_clean();
-    memcached_version_instance(server);
-    return rc;
-  }
-  else if (set_last_disconnected)
-  {
-    set_last_disconnected_host(server);
-    if (memcached_has_current_error(*server))
-    {
-      memcached_mark_server_for_timeout(server);
-      assert(memcached_failed(memcached_instance_error_return(server)));
-    }
-    else
-    {
-      memcached_set_error(*server, rc, MEMCACHED_AT);
-      memcached_mark_server_for_timeout(server);
-    }
-
-    LIBMEMCACHED_MEMCACHED_CONNECT_END();
-
-    if (in_timeout)
-    {
-      char buffer[1024];
-      int snprintf_length= snprintf(buffer, sizeof(buffer), "%s:%d", server->hostname(), int(server->port()));
-      return memcached_set_error(*server, MEMCACHED_SERVER_TEMPORARILY_DISABLED, MEMCACHED_AT, buffer, snprintf_length);
-    }
-  }
-
-  return rc;
-}
-
-memcached_return_t memcached_connect(memcached_instance_st* server)
-{
-  return _memcached_connect(server, true);
-}
diff --git a/libmemcached/connect.hpp b/libmemcached/connect.hpp
deleted file mode 100644 (file)
index d1dafe5..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-memcached_return_t memcached_connect(memcached_instance_st*);
diff --git a/libmemcached/continuum.hpp b/libmemcached/continuum.hpp
deleted file mode 100644 (file)
index e39fcdc..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-/* string value */
-struct memcached_continuum_item_st
-{
-  uint32_t index;
-  uint32_t value;
-};
diff --git a/libmemcached/csl/common.h b/libmemcached/csl/common.h
deleted file mode 100644 (file)
index 60b27d6..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Configure Scripting Language
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#ifndef YY_EXTRA_TYPE
-# define YY_EXTRA_TYPE Context*
-#endif
-
-#ifndef YY_TYPEDEF_YY_SCANNER_T
-# define YY_TYPEDEF_YY_SCANNER_T
-typedef void* yyscan_t;
-#endif
-
-#include <libmemcached/common.h>
-#include <libmemcached/csl/server.h>
-
diff --git a/libmemcached/csl/context.cc b/libmemcached/csl/context.cc
deleted file mode 100644 (file)
index fa2500b..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Configure Scripting Language
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/csl/common.h>
-#include <libmemcached/csl/context.h>
-
-void Context::abort(const char *error_arg, config_tokentype last_token, const char *last_token_str)
-{
-  rc= MEMCACHED_PARSE_ERROR;
-  (void)last_token;
-
-  if (error_arg)
-  {
-    memcached_set_parser_error(*memc, MEMCACHED_AT, "%s", error_arg);
-    return;
-  }
-
-  if (last_token_str)
-  {
-    memcached_set_parser_error(*memc, MEMCACHED_AT, "%s", last_token_str);
-    return;
-  }
-
-  memcached_set_parser_error(*memc, MEMCACHED_AT, "unknown parsing error");
-}
-
-void Context::error(const char *error_arg, config_tokentype last_token, const char *last_token_str)
-{
-  rc= MEMCACHED_PARSE_ERROR;
-  if (not error_arg)
-  {
-    memcached_set_parser_error(*memc, MEMCACHED_AT, "Unknown error occured during parsing (%s)", last_token_str ? last_token_str : " ");
-    return;
-  }
-
-  if (strcmp(error_arg, "memory exhausted") == 0)
-  {
-    (void)memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, memcached_string_make_from_cstr(error_arg));
-    return;
-  }
-
-  // We now test if it is something other then a syntax error, if it  we
-  // return a generic message 
-  if (strcmp(error_arg, "syntax error") != 0)
-  {
-    memcached_set_parser_error(*memc, MEMCACHED_AT, "Error occured during parsing (%s)", error_arg);
-    return;
-  }
-
-  if (last_token == UNKNOWN_OPTION and begin)
-  {
-    memcached_set_parser_error(*memc, MEMCACHED_AT, "Unknown option: %s", begin);
-  }
-  else if (last_token == UNKNOWN)
-  {
-    memcached_set_parser_error(*memc, MEMCACHED_AT, "Error occured durring parsing, an unknown token was found.");
-  }
-  else
-  {
-    memcached_set_parser_error(*memc, MEMCACHED_AT, "Error occured while parsing (%s)", last_token_str ? last_token_str : " ");
-  }
-}
-
-void Context::hostname(const char *str, size_t size, server_t& server_)
-{
-  size_t copy_length= size_t(NI_MAXHOST) > size ? size : size_t(NI_MAXHOST);
-  memcpy(_hostname, str, copy_length);
-  _hostname[copy_length]= 0;
-
-  server_.port= MEMCACHED_DEFAULT_PORT;
-  server_.weight= 1;
-  server_.c_str= _hostname;
-  server_.size= size;
-}
-
-bool Context::string_buffer(const char *str, size_t size, memcached_string_t& string_)
-{
-  if (memcached_string_set(_string_buffer, str, size))
-  {
-    string_.c_str= memcached_string_value(_string_buffer);
-    string_.size= memcached_string_length(_string_buffer);
-
-    return true;
-  }
-
-  return false;
-}
-
-bool Context::set_hash(memcached_hash_t hash)
-{
-  if (_has_hash)
-  {
-    return false;
-  }
-
-  if ((memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash)) != MEMCACHED_SUCCESS)
-  {
-    return false;
-  }
-
-  return _has_hash= true;
-}
diff --git a/libmemcached/csl/context.h b/libmemcached/csl/context.h
deleted file mode 100644 (file)
index 64d1f2f..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Configure Scripting Language
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include "libmemcached/csl/common.h"
-#include "libmemcached/csl/parser.h"
-
-class Context
-{
-public:
-  Context(const char *option_string, size_t option_string_length, memcached_st *memc_,
-          memcached_return_t &rc_arg) :
-    previous_token(END),
-    scanner(NULL),
-    buf(option_string),
-    begin(NULL),
-    pos(0),
-    length(option_string_length),
-    memc(memc_),
-    rc(rc_arg),
-    _is_server(false),
-    _end(false),
-    _has_hash(false)
-  {
-    _hostname[0]= 0;
-    init_scanner();
-    rc= MEMCACHED_SUCCESS;
-
-    memc->state.is_parsing= true;
-    memcached_string_create(memc,
-                            &_string_buffer,
-                            1024);
-  }
-
-  bool end()
-  {
-    return _end;
-  }
-
-  void start();
-
-  void set_end()
-  {
-    rc= MEMCACHED_SUCCESS;
-    _end= true;
-  }
-
-  bool set_hash(memcached_hash_t hash);
-
-  void set_server()
-  {
-    _is_server= true;
-  }
-
-  void unset_server()
-  {
-    _is_server= false;
-  }
-
-  bool is_server() const
-  {
-    return _is_server;
-  }
-
-  void hostname(const char*, size_t, server_t&);
-
-  bool string_buffer(const char*, size_t, memcached_string_t&);
-
-  const char *hostname() const
-  {
-    return _hostname;
-  }
-
-  void abort(const char *, config_tokentype, const char *);
-  void error(const char *, config_tokentype, const char* );
-
-  ~Context()
-  {
-    memcached_string_free(&_string_buffer);
-    destroy_scanner();
-    memc->state.is_parsing= false;
-  }
-
-  config_tokentype previous_token;
-  void *scanner;
-  const char *buf;
-  const char *begin;
-  size_t pos;
-  size_t length;
-  memcached_st *memc;
-  memcached_return_t &rc;
-
-protected:
-  void init_scanner();   
-  void destroy_scanner();
-
-private:
-  bool _is_server;
-  bool _end;
-  char _hostname[NI_MAXHOST];
-  bool _has_hash;
-  memcached_string_st _string_buffer;
-}; 
diff --git a/libmemcached/csl/parser.yy b/libmemcached/csl/parser.yy
deleted file mode 100644 (file)
index 87fe4f3..0000000
+++ /dev/null
@@ -1,542 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Libmemcached library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-%{
-
-#include <libmemcached/csl/common.h>
-
-class Context;
-
-%}
-
-%define parse.error verbose
-%define api.pure
-%define api.prefix {config_}
-%define api.value.type {union CONFIG_STYPE}
-%debug
-%defines
-%expect 0
-%lex-param { yyscan_t *scanner }
-%parse-param { class Context *context }
-%parse-param { yyscan_t *scanner }
-%require "2.5"
-%start begin
-%verbose
-
-%{
-
-#include <libmemcached/options.hpp>
-
-#include <libmemcached/csl/context.h>
-#include <libmemcached/csl/symbol.h>
-#include <libmemcached/csl/scanner.h>
-
-#ifndef __INTEL_COMPILER
-# pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
-
-#ifndef __INTEL_COMPILER
-# ifndef __clang__
-#  pragma GCC diagnostic ignored "-Wlogical-op"
-#  pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"
-# endif
-#endif
-
-int config_lex(YYSTYPE* lvalp, void* scanner);
-
-#define select_yychar(__context) yychar == UNKNOWN ? ( (__context)->previous_token == END ? UNKNOWN : (__context)->previous_token ) : yychar   
-
-#define stryytname(__yytokentype) ((__yytokentype) <  YYNTOKENS ) ? yytname[(__yytokentype)] : ""
-
-#define parser_abort(__context, __error_message) do { (__context)->abort((__error_message), config_tokentype(select_yychar(__context)), stryytname(YYTRANSLATE(select_yychar(__context)))); YYABORT; } while (0)
-
-// This is bison calling error.
-inline void __config_error(Context *context, yyscan_t *scanner, const char *error, int last_token, const char *last_token_str)
-{
-  if (not context->end())
-  {
-    context->error(error, config_tokentype(last_token), last_token_str);
-  }
-  else
-  {
-    context->error(error, config_tokentype(last_token), last_token_str);
-  }
-}
-
-#define config_error(__context, __scanner, __error_msg) do { __config_error((__context), (__scanner), (__error_msg), select_yychar(__context), stryytname(YYTRANSLATE(select_yychar(__context)))); } while (0)
-
-
-%}
-
-%token COMMENT
-%token END
-%token CSL_ERROR
-%token RESET
-%token PARSER_DEBUG
-%token INCLUDE
-%token CONFIGURE_FILE
-%token EMPTY_LINE
-%token SERVER
-%token CSL_SOCKET
-%token SERVERS
-%token SERVERS_OPTION
-%token UNKNOWN_OPTION
-%token UNKNOWN
-
-/* All behavior options */
-%token BINARY_PROTOCOL
-%token BUFFER_REQUESTS
-%token CONNECT_TIMEOUT
-%token DISTRIBUTION
-%token HASH
-%token HASH_WITH_NAMESPACE
-%token IO_BYTES_WATERMARK
-%token IO_KEY_PREFETCH
-%token IO_MSG_WATERMARK
-%token KETAMA_HASH
-%token KETAMA_WEIGHTED
-%token NOREPLY
-%token NUMBER_OF_REPLICAS
-%token POLL_TIMEOUT
-%token RANDOMIZE_REPLICA_READ
-%token RCV_TIMEOUT
-%token REMOVE_FAILED_SERVERS
-%token RETRY_TIMEOUT
-%token SND_TIMEOUT
-%token SOCKET_RECV_SIZE
-%token SOCKET_SEND_SIZE
-%token SORT_HOSTS
-%token SUPPORT_CAS
-%token USER_DATA
-%token USE_UDP
-%token VERIFY_KEY
-%token _TCP_KEEPALIVE
-%token _TCP_KEEPIDLE
-%token _TCP_NODELAY
-%token FETCH_VERSION
-
-/* Callbacks */
-%token NAMESPACE
-
-/* Pool */
-%token POOL_MIN
-%token POOL_MAX
-
-/* Hash types */
-%token MD5
-%token CRC
-%token FNV1_64
-%token FNV1A_64
-%token FNV1_32
-%token FNV1A_32
-%token HSIEH
-%token MURMUR
-%token JENKINS
-
-/* Distributions */
-%token CONSISTENT
-%token MODULA
-%token RANDOM
-
-/* Boolean values */
-%token <boolean> CSL_TRUE
-%token <boolean> CSL_FALSE
-
-%nonassoc ','
-%nonassoc '='
-
-%token <number> CSL_FLOAT
-%token <number> NUMBER
-%token <number> PORT
-%token <number> WEIGHT_START
-%token <server> IPADDRESS
-%token <server> HOSTNAME
-%token <string> STRING
-%token <string> QUOTED_STRING
-%token <string> FILE_PATH
-
-%type <behavior> behavior_boolean
-%type <behavior> behavior_number
-%type <distribution> distribution
-%type <hash> hash
-%type <number> optional_port
-%type <number> optional_weight
-%type <string> string
-
-%%
-
-begin:
-          statement
-        | begin ' ' statement
-        ;
-
-statement:
-         expression
-          { }
-        | COMMENT
-          { }
-        | EMPTY_LINE
-          { }
-        | END
-          {
-            context->set_end();
-            YYACCEPT;
-          }
-        | CSL_ERROR
-          {
-            context->rc= MEMCACHED_PARSE_USER_ERROR;
-            parser_abort(context, "ERROR called directly");
-          }
-        | RESET
-          {
-            memcached_reset(context->memc);
-          }
-        | PARSER_DEBUG
-          {
-            yydebug= 1;
-          }
-        | INCLUDE ' ' string
-          {
-            if ((context->rc= memcached_parse_configure_file(*context->memc, $3.c_str, $3.size)) != MEMCACHED_SUCCESS)
-            {
-              parser_abort(context, "Failed to parse configuration file");
-            }
-          }
-        ;
-
-
-expression:
-          SERVER HOSTNAME optional_port optional_weight
-          {
-            if (memcached_failed(context->rc= memcached_server_add_with_weight(context->memc, $2.c_str, $3, uint32_t($4))))
-            {
-              char buffer[1024];
-              snprintf(buffer, sizeof(buffer), "Failed to add server: %s:%u", $2.c_str, uint32_t($3));
-              parser_abort(context, buffer);
-            }
-            context->unset_server();
-          }
-        | SERVER IPADDRESS optional_port optional_weight
-          {
-            if (memcached_failed(context->rc= memcached_server_add_with_weight(context->memc, $2.c_str, $3, uint32_t($4))))
-            {
-              char buffer[1024];
-              snprintf(buffer, sizeof(buffer), "Failed to add server: %s:%u", $2.c_str, uint32_t($3));
-              parser_abort(context, buffer);
-            }
-            context->unset_server();
-          }
-        | CSL_SOCKET string optional_weight
-          {
-            if (memcached_failed(context->rc= memcached_server_add_unix_socket_with_weight(context->memc, $2.c_str, uint32_t($3))))
-            {
-              char buffer[1024];
-              snprintf(buffer, sizeof(buffer), "Failed to add socket: %s", $2.c_str);
-              parser_abort(context, buffer);
-            }
-          }
-        | CONFIGURE_FILE string
-          {
-            memcached_set_configuration_file(context->memc, $2.c_str, $2.size);
-          }
-        | POOL_MIN NUMBER
-          {
-            context->memc->configure.initial_pool_size= uint32_t($2);
-          }
-        | POOL_MAX NUMBER
-          {
-            context->memc->configure.max_pool_size= uint32_t($2);
-          }
-        | behaviors
-        ;
-
-behaviors:
-          NAMESPACE string
-          {
-            if (memcached_callback_get(context->memc, MEMCACHED_CALLBACK_PREFIX_KEY, NULL))
-            {
-              parser_abort(context, "--NAMESPACE can only be called once");
-            }
-
-            if ((context->rc= memcached_set_namespace(*context->memc, $2.c_str, $2.size)) != MEMCACHED_SUCCESS)
-            {
-              parser_abort(context, memcached_last_error_message(context->memc));
-            }
-          }
-        | FETCH_VERSION
-          {
-            memcached_flag(*context->memc, MEMCACHED_FLAG_IS_FETCHING_VERSION, true);
-          }
-        | DISTRIBUTION distribution
-          {
-            // Check to see if DISTRIBUTION has already been set
-            if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
-            {
-              parser_abort(context, "--DISTRIBUTION can only be called once");
-            }
-
-            if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
-            {
-              parser_abort(context, memcached_last_error_message(context->memc));;
-            }
-          }
-        | DISTRIBUTION distribution ',' hash
-          {
-            // Check to see if DISTRIBUTION has already been set
-            if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
-            {
-              parser_abort(context, "--DISTRIBUTION can only be called once");
-            }
-
-            if ((context->rc= memcached_behavior_set_distribution_hash(context->memc, $4)) != MEMCACHED_SUCCESS)
-            {
-              parser_abort(context, "Unable to set the hash for the DISTRIBUTION requested");
-            }
-          }
-        | HASH hash
-          {
-            if (context->set_hash($2) == false)
-            {
-              parser_abort(context, "--HASH can only be set once");
-            }
-          }
-        | behavior_number NUMBER
-          {
-            if ((context->rc= memcached_behavior_set(context->memc, $1, $2)) != MEMCACHED_SUCCESS)
-            {
-              parser_abort(context, "Unable to set behavior");
-            }
-          }
-        | behavior_boolean
-          {
-            if ((context->rc= memcached_behavior_set(context->memc, $1, true)) != MEMCACHED_SUCCESS)
-            {
-              char buffer[1024];
-              snprintf(buffer, sizeof(buffer), "Could not set: %s", libmemcached_string_behavior($1));
-              parser_abort(context, buffer);
-            }
-          }
-        |  USER_DATA
-          {
-          }
-        ;
-
-behavior_number:
-          REMOVE_FAILED_SERVERS
-          {
-            $$= MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS;
-          }
-        | CONNECT_TIMEOUT
-          {
-            $$= MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT;
-          }
-        | IO_MSG_WATERMARK
-          {
-            $$= MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK;
-          }
-        | IO_BYTES_WATERMARK
-          {
-            $$= MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK;
-          }
-        | IO_KEY_PREFETCH
-          {
-            $$= MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH;
-          }
-        | NUMBER_OF_REPLICAS
-          {
-            $$= MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS;
-          }
-        | POLL_TIMEOUT
-          {
-            $$= MEMCACHED_BEHAVIOR_POLL_TIMEOUT;
-          }
-        |  RCV_TIMEOUT
-          {
-            $$= MEMCACHED_BEHAVIOR_RCV_TIMEOUT;
-          }
-        |  RETRY_TIMEOUT
-          {
-            $$= MEMCACHED_BEHAVIOR_RETRY_TIMEOUT;
-          }
-        |  SND_TIMEOUT
-          {
-            $$= MEMCACHED_BEHAVIOR_SND_TIMEOUT;
-          }
-        |  SOCKET_RECV_SIZE
-          {
-            $$= MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE;
-          }
-        |  SOCKET_SEND_SIZE
-          {
-            $$= MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE;
-          }
-        ;
-
-behavior_boolean: 
-          BINARY_PROTOCOL
-          {
-            $$= MEMCACHED_BEHAVIOR_BINARY_PROTOCOL;
-          }
-        | BUFFER_REQUESTS
-          {
-            $$= MEMCACHED_BEHAVIOR_BUFFER_REQUESTS;
-          }
-        | HASH_WITH_NAMESPACE
-          {
-            $$= MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY;
-          }
-        | NOREPLY
-          {
-            $$= MEMCACHED_BEHAVIOR_NOREPLY;
-          }
-        |  RANDOMIZE_REPLICA_READ
-          {
-            $$= MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ;
-          }
-        |  SORT_HOSTS
-          {
-            $$= MEMCACHED_BEHAVIOR_SORT_HOSTS;
-          }
-        |  SUPPORT_CAS
-          {
-            $$= MEMCACHED_BEHAVIOR_SUPPORT_CAS;
-          }
-        |  _TCP_NODELAY
-          {
-            $$= MEMCACHED_BEHAVIOR_TCP_NODELAY;
-          }
-        |  _TCP_KEEPALIVE
-          {
-            $$= MEMCACHED_BEHAVIOR_TCP_KEEPALIVE;
-          }
-        |  _TCP_KEEPIDLE
-          {
-            $$= MEMCACHED_BEHAVIOR_TCP_KEEPIDLE;
-          }
-        |  USE_UDP
-          {
-            $$= MEMCACHED_BEHAVIOR_USE_UDP;
-          }
-        |  VERIFY_KEY
-          {
-            $$= MEMCACHED_BEHAVIOR_VERIFY_KEY;
-          }
-
-
-optional_port:
-          { $$= MEMCACHED_DEFAULT_PORT;}
-        | PORT
-          { };
-        ;
-
-optional_weight:
-          { $$= 1; }
-        | WEIGHT_START
-          { }
-        ;
-
-hash:
-          MD5
-          {
-            $$= MEMCACHED_HASH_MD5;
-          }
-        | CRC
-          {
-            $$= MEMCACHED_HASH_CRC;
-          }
-        | FNV1_64
-          {
-            $$= MEMCACHED_HASH_FNV1_64;
-          }
-        | FNV1A_64
-          {
-            $$= MEMCACHED_HASH_FNV1A_64;
-          }
-        | FNV1_32
-          {
-            $$= MEMCACHED_HASH_FNV1_32;
-          }
-        | FNV1A_32
-          {
-            $$= MEMCACHED_HASH_FNV1A_32;
-          }
-        | HSIEH
-          {
-            $$= MEMCACHED_HASH_HSIEH;
-          }
-        | MURMUR
-          {
-            $$= MEMCACHED_HASH_MURMUR;
-          }
-        | JENKINS
-          {
-            $$= MEMCACHED_HASH_JENKINS;
-          }
-        ;
-
-string:
-          STRING
-          {
-            $$= $1;
-          }
-        | QUOTED_STRING
-          {
-            $$= $1;
-          }
-        ;
-
-distribution:
-          CONSISTENT
-          {
-            $$= MEMCACHED_DISTRIBUTION_CONSISTENT;
-          }
-        | MODULA
-          {
-            $$= MEMCACHED_DISTRIBUTION_MODULA;
-          }
-        | RANDOM
-          {
-            $$= MEMCACHED_DISTRIBUTION_RANDOM;
-          }
-        ;
-
-%% 
-
-void Context::start() 
-{
-  config_parse(this, (void **)scanner);
-}
-
diff --git a/libmemcached/csl/scanner.l b/libmemcached/csl/scanner.l
deleted file mode 100644 (file)
index d82af27..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Libmemcached library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-%top{
-
-#include <libmemcached/csl/common.h>
-#include <libmemcached/csl/context.h>
-#include <libmemcached/csl/parser.h>
-#include <libmemcached/csl/symbol.h>
-
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#pragma GCC diagnostic ignored "-Wsign-compare"
-#pragma GCC diagnostic ignored "-Wunused-parameter"
-#pragma GCC diagnostic ignored "-Wmissing-declarations"
-#pragma GCC diagnostic ignored "-Wunused-result"
-#pragma GCC diagnostic ignored "-Wmissing-noreturn"
-#endif
-
-#ifdef __clang__
-#pragma GCC diagnostic ignored "-Wshorten-64-to-32"
-#endif
-
-#ifndef __INTEL_COMPILER
-#ifndef __clang__
-#pragma GCC diagnostic ignored "-Wlogical-op"
-#endif
-#endif
-
-}
-
-
-%{
-#define PARAM yyget_extra(yyscanner)
-
-#define get_lex_chars(buffer, result, max_size, context) \
-{ \
-  if (context->pos >= context->length) \
-  { \
-    result= YY_NULL; \
-  } \
-  else \
-  { \
-    result= (int)(context->length - context->pos); \
-    (size_t)result > (size_t)max_size ? result= max_size : 0; \
-    memcpy(buffer, context->buf + context->pos, result); \
-    context->pos += result; \
-  } \
-}
-
-#define YY_FATAL_ERROR(msg) \
-{ \
-}
-
-#define YYSTYPE CONFIG_STYPE
-
-#define YY_INPUT(buffer, result, max_size) get_lex_chars(buffer, result, max_size, PARAM)
-
-%}
-
-%option nostdinit
-%option 8bit
-%option warn
-%option bison-bridge
-%option never-interactive
-%option case-insensitive
-%option nodefault
-%option noinput
-%option nounput
-%option noyywrap
-%option perf-report
-%option prefix="config_"
-%option reentrant
-
-%%
-
-
-=|,|[ ]       { return yytext[0];}
-
-[[:digit:]]+ { yylval->number= atoi(yytext); return (NUMBER); }
-
-:[[:digit:]]{1,5} { yylval->number= atoi(yytext +1); return PORT; }
-
-"/?"[[:digit:]]{1,5} { yylval->number= atoi(yytext +2); return WEIGHT_START; }
-
-[\t\r\n] ; /* skip whitespace */
-
-
-^#.*$ {
-      return COMMENT;
-    }
-
-"--SERVER="                          { yyextra->begin= yytext; yyextra->set_server(); return yyextra->previous_token= SERVER; }
-
-"--SOCKET="                          { yyextra->begin= yytext; return yyextra->previous_token= CSL_SOCKET; }
-
-"--BINARY-PROTOCOL"                    { yyextra->begin= yytext; return yyextra->previous_token= BINARY_PROTOCOL; }
-"--BUFFER-REQUESTS"                    { yyextra->begin= yytext; return yyextra->previous_token= BUFFER_REQUESTS; }
-"--CONFIGURE-FILE="                    { yyextra->begin= yytext; return yyextra->previous_token= CONFIGURE_FILE; }
-"--CONNECT-TIMEOUT="                   { yyextra->begin= yytext; return yyextra->previous_token= CONNECT_TIMEOUT; }
-"--DISTRIBUTION="                      { yyextra->begin= yytext; return yyextra->previous_token= DISTRIBUTION; }
-"--HASH-WITH-NAMESPACE"                { yyextra->begin= yytext; return yyextra->previous_token= HASH_WITH_NAMESPACE; }
-"--HASH="                              { yyextra->begin= yytext; return yyextra->previous_token= HASH; }
-"--IO-BYTES-WATERMARK="                { yyextra->begin= yytext; return yyextra->previous_token= IO_BYTES_WATERMARK; }
-"--IO-KEY-PREFETCH="                   { yyextra->begin= yytext; return yyextra->previous_token= IO_KEY_PREFETCH; }
-"--IO-MSG-WATERMARK="          { yyextra->begin= yytext; return yyextra->previous_token= IO_MSG_WATERMARK; }
-"--NOREPLY"                         { yyextra->begin= yytext; return yyextra->previous_token= NOREPLY; }
-"--NUMBER-OF-REPLICAS="                { yyextra->begin= yytext; return yyextra->previous_token= NUMBER_OF_REPLICAS; }
-"--POLL-TIMEOUT="                      { yyextra->begin= yytext; return yyextra->previous_token= POLL_TIMEOUT; }
-"--RANDOMIZE-REPLICA-READ"             { yyextra->begin= yytext; return yyextra->previous_token= RANDOMIZE_REPLICA_READ; }
-"--RCV-TIMEOUT="                       { yyextra->begin= yytext; return yyextra->previous_token= RCV_TIMEOUT; }
-"--REMOVE-FAILED-SERVERS="                     { yyextra->begin= yytext; return yyextra->previous_token= REMOVE_FAILED_SERVERS; }
-"--RETRY-TIMEOUT="                     { yyextra->begin= yytext; return yyextra->previous_token= RETRY_TIMEOUT; }
-"--SND-TIMEOUT="                       { yyextra->begin= yytext; return yyextra->previous_token= SND_TIMEOUT; }
-"--SOCKET-RECV-SIZE="          { yyextra->begin= yytext; return yyextra->previous_token= SOCKET_RECV_SIZE; }
-"--SOCKET-SEND-SIZE="          { yyextra->begin= yytext; return yyextra->previous_token= SOCKET_SEND_SIZE; }
-"--SORT-HOSTS"                 { yyextra->begin= yytext; return yyextra->previous_token= SORT_HOSTS; }
-"--SUPPORT-CAS"                        { yyextra->begin= yytext; return yyextra->previous_token= SUPPORT_CAS; }
-"--TCP-KEEPALIVE"                      { yyextra->begin= yytext; return yyextra->previous_token= _TCP_KEEPALIVE; }
-"--TCP-KEEPIDLE"                       { yyextra->begin= yytext; return yyextra->previous_token= _TCP_KEEPIDLE; }
-"--TCP-NODELAY"                        { yyextra->begin= yytext; return yyextra->previous_token= _TCP_NODELAY; }
-"--USE-UDP"                            { yyextra->begin= yytext; return yyextra->previous_token= USE_UDP; }
-"--USER-DATA"                  { yyextra->begin= yytext; return yyextra->previous_token= USER_DATA; }
-"--VERIFY-KEY"                      { yyextra->begin= yytext; return yyextra->previous_token= VERIFY_KEY; }
-
-"--POOL-MIN="                          { yyextra->begin= yytext; return yyextra->previous_token= POOL_MIN; }
-"--POOL-MAX="                          { yyextra->begin= yytext; return yyextra->previous_token= POOL_MAX; }
-
-"--NAMESPACE="                         { yyextra->begin= yytext; return yyextra->previous_token= NAMESPACE; }
-
-"--FETCH-VERSION"                              { yyextra->begin= yytext; return yyextra->previous_token= FETCH_VERSION; }
-
-INCLUDE           { yyextra->begin= yytext; return yyextra->previous_token= INCLUDE; }
-RESET           { yyextra->begin= yytext; return yyextra->previous_token= RESET; }
-DEBUG           { yyextra->begin= yytext; return yyextra->previous_token= PARSER_DEBUG; }
-SERVERS           { yyextra->begin= yytext; return yyextra->previous_token= SERVERS; }
-END           { yyextra->begin= yytext; return yyextra->previous_token= END; }
-CSL_ERROR           { yyextra->begin= yytext; return yyextra->previous_token= CSL_ERROR; }
-
-TRUE           { return yyextra->previous_token= CSL_TRUE; }
-FALSE           { return yyextra->previous_token= CSL_FALSE; }
-
-
-"--"[[:alnum:]]*   {
-      yyextra->begin= yytext;
-      return UNKNOWN_OPTION;
-    }
-
-CONSISTENT      { return CONSISTENT; }
-MODULA          { return MODULA; }
-RANDOM          { return RANDOM; }
-
-MD5                    { return MD5; }
-CRC                    { return CRC; }
-FNV1_64                        { return FNV1_64; }
-FNV1A_64                       { return FNV1A_64; }
-FNV1_32                        { return FNV1_32; }
-FNV1A_32                       { return FNV1A_32; }
-HSIEH                  { return HSIEH; }
-MURMUR                 { return MURMUR; }
-JENKINS                        { return JENKINS; }
-
-(([[:digit:]]{1,3}"."){3}([[:digit:]]{1,3})) {
-      yyextra->hostname(yytext, yyleng, yylval->server);
-      return IPADDRESS;
-    }
-
-[[:alnum:]]["."[:alnum:]_-]+[[:alnum:]] {
-      if (yyextra->is_server())
-      {
-        yyextra->hostname(yytext, yyleng, yylval->server);
-
-        return HOSTNAME;
-      }
-
-      yyextra->string_buffer(yytext, yyleng, yylval->string);
-
-      return STRING;
-    }
-
-L?\"(\\.|[^\\"])*\" {
-      yyget_text(yyscanner)[yyleng -1]= 0;
-      yyextra->string_buffer(yytext +1, yyleng -2, yylval->string);
-      return QUOTED_STRING;
-    }
-
-.   {
-      yyextra->begin= yytext;
-      return UNKNOWN;
-    }
-
-%%
-
-void Context::init_scanner()
-{
-  yylex_init(&scanner);
-  yyset_extra(this, scanner);
-}
-
-void Context::destroy_scanner()
-{
-  (void)yy_fatal_error; // Removes warning about unused yy_fatal_error()
-  yylex_destroy(scanner);
-}
-
diff --git a/libmemcached/csl/server.h b/libmemcached/csl/server.h
deleted file mode 100644 (file)
index 21915d6..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Configure Scripting Language
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <cstdlib>
-
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif
-
-struct server_t
-{
-  const char *c_str;
-  size_t size;
-  in_port_t port;
-  uint32_t weight;
-};
diff --git a/libmemcached/csl/symbol.h b/libmemcached/csl/symbol.h
deleted file mode 100644 (file)
index 10ff603..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Configure Scripting Language
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <libmemcached/csl/common.h>
-
-union CONFIG_STYPE
-{
-  long long number;  
-  memcached_string_t string;
-  memcached_string_t option;
-  double double_number;
-  memcached_server_distribution_t distribution;
-  memcached_hash_t hash;
-  memcached_behavior_t behavior;
-  bool boolean;
-  server_t server;
-};
-
-typedef union CONFIG_STYPE CONFIG_STYPE;
diff --git a/libmemcached/delete.cc b/libmemcached/delete.cc
deleted file mode 100644 (file)
index ef1d847..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-memcached_return_t memcached_delete(memcached_st *shell, const char *key, size_t key_length,
-                                    time_t expiration)
-{
-  return memcached_delete_by_key(shell, key, key_length, key, key_length, expiration);
-}
-
-static inline memcached_return_t ascii_delete(memcached_instance_st* instance,
-                                              uint32_t ,
-                                              const char *key,
-                                              const size_t key_length,
-                                              const bool reply,
-                                              const bool is_buffering)
-{
-  libmemcached_io_vector_st vector[]=
-  {
-    { NULL, 0 },
-    { memcached_literal_param("delete ") },
-    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
-    { key, key_length },
-    { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
-    { memcached_literal_param("\r\n") }
-  };
-
-  /* Send command header, only flush if we are NOT buffering */
-  return memcached_vdo(instance, vector, 6, is_buffering ? false : true);
-}
-
-static inline memcached_return_t binary_delete(memcached_instance_st* instance,
-                                               uint32_t server_key,
-                                               const char *key,
-                                               const size_t key_length,
-                                               const bool reply,
-                                               const bool is_buffering)
-{
-  protocol_binary_request_delete request= {};
-
-  bool should_flush= is_buffering ? false : true;
-
-  initialize_binary_request(instance, request.message.header);
-
-  if (reply)
-  {
-    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETE;
-  }
-  else
-  {
-    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
-  }
-  request.message.header.request.keylen= htons(uint16_t(key_length + memcached_array_size(instance->root->_namespace)));
-  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-  request.message.header.request.bodylen= htonl(uint32_t(key_length + memcached_array_size(instance->root->_namespace)));
-
-  libmemcached_io_vector_st vector[]=
-  {
-    { NULL, 0 },
-    { request.bytes, sizeof(request.bytes) },
-    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
-    { key, key_length }
-  };
-
-  memcached_return_t rc= memcached_vdo(instance, vector,  4, should_flush);
-
-  if (memcached_has_replicas(instance))
-  {
-    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
-
-    for (uint32_t x= 0; x < memcached_has_replicas(instance); ++x)
-    {
-      ++server_key;
-
-      if (server_key == memcached_server_count(instance->root))
-      {
-        server_key= 0;
-      }
-
-      memcached_instance_st* replica= memcached_instance_fetch(instance->root, server_key);
-
-      if (memcached_success(memcached_vdo(replica, vector, 4, should_flush)))
-      {
-        memcached_server_response_decrement(replica);
-      }
-    }
-  }
-
-  return rc;
-}
-
-memcached_return_t memcached_delete_by_key(memcached_st *shell,
-                                           const char *group_key, size_t group_key_length,
-                                           const char *key, size_t key_length,
-                                           time_t expiration)
-{
-  Memcached* memc= memcached2Memcached(shell);
-  LIBMEMCACHED_MEMCACHED_DELETE_START();
-
-  memcached_return_t rc;
-  if (memcached_fatal(rc= initialize_query(memc, true)))
-  {
-    return rc;
-  }
-
-  if (memcached_fatal(rc= memcached_key_test(*memc, (const char **)&key, &key_length, 1)))
-  {
-    return memcached_last_error(memc);
-  }
-
-  if (expiration)
-  {
-    return memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, 
-                               memcached_literal_param("Memcached server version does not allow expiration of deleted items"));
-  }
-
-  uint32_t server_key= memcached_generate_hash_with_redistribution(memc, group_key, group_key_length);
-  memcached_instance_st* instance= memcached_instance_fetch(memc, server_key);
-  
-  bool is_buffering= memcached_is_buffering(instance->root);
-  bool is_replying= memcached_is_replying(instance->root);
-
-  // If a delete trigger exists, we need a response, so no buffering/noreply
-  if (memc->delete_trigger)
-  {
-    if (is_buffering)
-    {
-      return memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, 
-                                 memcached_literal_param("Delete triggers cannot be used if buffering is enabled"));
-    }
-
-    if (is_replying == false)
-    {
-      return memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, 
-                                 memcached_literal_param("Delete triggers cannot be used if MEMCACHED_BEHAVIOR_NOREPLY is set"));
-    }
-  }
-
-  if (memcached_is_binary(memc))
-  {
-    rc= binary_delete(instance, server_key, key, key_length, is_replying, is_buffering);
-  }
-  else
-  {
-    rc= ascii_delete(instance, server_key, key, key_length, is_replying, is_buffering);
-  }
-
-  if (rc == MEMCACHED_SUCCESS)
-  {
-    if (is_buffering == true)
-    {
-      rc= MEMCACHED_BUFFERED;
-    }
-    else if (is_replying == false)
-    {
-      rc= MEMCACHED_SUCCESS;
-    }
-    else
-    {
-      char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-      rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
-      if (rc == MEMCACHED_DELETED)
-      {
-        rc= MEMCACHED_SUCCESS;
-        if (memc->delete_trigger)
-        {
-          memc->delete_trigger(memc, key, key_length);
-        }
-      }
-    }
-  }
-
-  LIBMEMCACHED_MEMCACHED_DELETE_END();
-  return rc;
-}
diff --git a/libmemcached/do.cc b/libmemcached/do.cc
deleted file mode 100644 (file)
index 59f9d5a..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2010 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-#include <libmemcached/common.h>
-
-static memcached_return_t _vdo_udp(memcached_instance_st* instance,
-                                   libmemcached_io_vector_st vector[],
-                                   const size_t count)
-{
-#ifndef __MINGW32__
-  if (vector[0].buffer or vector[0].length)
-  {
-    return memcached_set_error(*instance->root, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, 
-                               memcached_literal_param("UDP messages was attempted, but vector was not setup for it"));
-  }
-
-  struct msghdr msg;
-  memset(&msg, 0, sizeof(msg));
-
-  increment_udp_message_id(instance);
-  vector[0].buffer= instance->write_buffer;
-  vector[0].length= UDP_DATAGRAM_HEADER_LENGTH;
-
-  msg.msg_iov= (struct iovec*)vector;
-#ifdef __APPLE__
-  msg.msg_iovlen= int(count);
-#else
-  msg.msg_iovlen= count;
-#endif
-
-  uint32_t retry= 5;
-  while (--retry)
-  {
-    ssize_t sendmsg_length= ::sendmsg(instance->fd, &msg, 0);
-    if (sendmsg_length > 0)
-    {
-      break;
-    }
-    else if (sendmsg_length < 0)
-    {
-      if (errno == EMSGSIZE)
-      {
-        return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
-      }
-
-      return memcached_set_errno(*instance, errno, MEMCACHED_AT);
-    }
-  }
-
-  return MEMCACHED_SUCCESS;
-#else
-  (void)instance;
-  (void)vector;
-  (void)count;
-  return MEMCACHED_FAILURE;
-#endif
-}
-
-memcached_return_t memcached_vdo(memcached_instance_st* instance,
-                                 libmemcached_io_vector_st vector[],
-                                 const size_t count,
-                                 const bool with_flush)
-{
-  memcached_return_t rc;
-
-  assert_msg(vector, "Invalid vector passed");
-
-  if (memcached_failed(rc= memcached_connect(instance)))
-  {
-    WATCHPOINT_ERROR(rc);
-    assert_msg(instance->error_messages, "memcached_connect() returned an error but the Instance showed none.");
-    return rc;
-  }
-
-  /*
-  ** Since non buffering ops in UDP mode dont check to make sure they will fit
-  ** before they start writing, if there is any data in buffer, clear it out,
-  ** otherwise we might get a partial write.
-  **/
-  bool sent_success;
-  if (memcached_is_udp(instance->root))
-  {
-    sent_success= memcached_success(rc= _vdo_udp(instance, vector, count));
-  } else {
-    sent_success= memcached_io_writev(instance, vector, count, with_flush);
-  }
-  if (sent_success == false)
-  {
-    rc= memcached_last_error(instance->root);
-    if (rc == MEMCACHED_SUCCESS)
-    {
-      memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
-    }
-    memcached_io_reset(instance);
-  }
-  else if (memcached_is_replying(instance->root) && !memcached_is_udp(instance->root))
-  {
-    memcached_server_response_increment(instance);
-  }
-
-  return rc;
-}
diff --git a/libmemcached/do.hpp b/libmemcached/do.hpp
deleted file mode 100644 (file)
index d2dc667..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-memcached_return_t memcached_vdo(memcached_instance_st*,
-                                 libmemcached_io_vector_st vector[],
-                                 const size_t count,
-                                 const bool with_flush);
diff --git a/libmemcached/dump.cc b/libmemcached/dump.cc
deleted file mode 100644 (file)
index c0c4ed6..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
-  We use this to dump all keys.
-
-  At this point we only support a callback method. This could be optimized by first
-  calling items and finding active slabs. For the moment though we just loop through
-  all slabs on servers and "grab" the keys.
-*/
-
-#include <libmemcached/common.h>
-
-static memcached_return_t ascii_dump(Memcached *memc, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
-{
-  memcached_version(memc);
-  /* MAX_NUMBER_OF_SLAB_CLASSES is defined to 200 in Memcached 1.4.10 */
-  for (uint32_t x= 0; x < 200; x++)
-  {
-    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-    int buffer_length= snprintf(buffer, sizeof(buffer), "%u", x);
-    if (size_t(buffer_length) >= sizeof(buffer) or buffer_length < 0)
-    {
-      return memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                                 memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
-    }
-
-    // @NOTE the hard coded zero means "no limit"
-    libmemcached_io_vector_st vector[]=
-    {
-      { memcached_literal_param("stats cachedump ") },
-      { buffer, size_t(buffer_length) },
-      { memcached_literal_param(" 0\r\n") }
-    };
-
-    // Send message to all servers
-    for (uint32_t server_key= 0; server_key < memcached_server_count(memc); server_key++)
-    {
-      memcached_instance_st* instance= memcached_instance_fetch(memc, server_key);
-
-      // skip slabs >63 for server versions >= 1.4.23
-      if (x < 64 || memcached_version_instance_cmp(instance, 1, 4, 23) < 0) {
-        memcached_return_t vdo_rc;
-        if (memcached_failed((vdo_rc= memcached_vdo(instance, vector, 3, true))))
-        {
-          return vdo_rc;
-        }
-      }
-    }
-
-    // Collect the returned items
-    memcached_instance_st* instance;
-    memcached_return_t read_ret= MEMCACHED_SUCCESS;
-    while ((instance= memcached_io_get_readable_server(memc, read_ret)))
-    {
-      memcached_return_t response_rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
-      if (response_rc == MEMCACHED_ITEM)
-      {
-        char *string_ptr, *end_ptr;
-
-        string_ptr= buffer;
-        string_ptr+= 5; /* Move past ITEM */
-
-        for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++) {} ;
-
-        char *key= string_ptr;
-        key[(size_t)(end_ptr-string_ptr)]= 0;
-
-        for (uint32_t callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++)
-        {
-          memcached_return_t callback_rc= (*callback[callback_counter])(memc, key, (size_t)(end_ptr-string_ptr), context);
-          if (callback_rc != MEMCACHED_SUCCESS)
-          {
-            // @todo build up a message for the error from the value
-            memcached_set_error(*instance, callback_rc, MEMCACHED_AT);
-            break;
-          }
-        }
-      }
-      else if (response_rc == MEMCACHED_END)
-      { 
-        // All items have been returned
-      }
-      else if (response_rc == MEMCACHED_SERVER_ERROR)
-      {
-        /* If we try to request stats cachedump for a slab class that is too big
-         * the server will return an incorrect error message:
-         * "MEMCACHED_SERVER_ERROR failed to allocate memory"
-         * This isn't really a fatal error, so let's just skip it. I want to
-         * fix the return value from the memcached server to a CLIENT_ERROR,
-         * so let's add support for that as well right now.
-       */
-        assert(response_rc == MEMCACHED_SUCCESS); // Just fail
-        return response_rc;
-      }
-      else if (response_rc == MEMCACHED_CLIENT_ERROR)
-      {
-        /* The maximum number of slabs has changed in the past (currently 1<<6-1),
-         * so ignore any client errors complaining about an illegal slab id.
-         */
-        if (0 == strncmp(buffer, "CLIENT_ERROR Illegal slab id", sizeof("CLIENT_ERROR Illegal slab id") - 1)) {
-          memcached_error_free(*instance);
-          memcached_error_free(*memc);
-        } else {
-          return response_rc;
-        }
-      }
-      else
-      {
-        // IO error of some sort must have occurred
-        return response_rc;
-      }
-    }
-  }
-
-  return memcached_has_current_error(*memc) ? MEMCACHED_SOME_ERRORS : MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_dump(memcached_st *shell, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr, true)))
-  {
-    return rc;
-  }
-
-  /* 
-    No support for Binary protocol yet
-    @todo Fix this so that we just flush, switch to ascii, and then go back to binary.
-  */
-  if (memcached_is_binary(ptr))
-  {
-    return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, memcached_literal_param("Binary protocol is not supported for memcached_dump()"));
-  }
-
-  return ascii_dump(ptr, callback, context, number_of_callbacks);
-}
diff --git a/libmemcached/encoding_key.cc b/libmemcached/encoding_key.cc
deleted file mode 100644 (file)
index 1e17d50..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-#include <libmemcached/assert.hpp>
-
-static void _set_encoding_key(Memcached& memc, const char *key, size_t key_length)
-{
-  hashkit_key(&memc.hashkit, key, key_length);
-}
-
-memcached_return_t memcached_set_encoding_key(memcached_st* shell, const char *key, size_t key_length)
-{
-  Memcached* memc= memcached2Memcached(shell);
-  if (memc)
-  {
-    _set_encoding_key(*memc, key, key_length);
-    return MEMCACHED_SUCCESS;
-  }
-
-  return MEMCACHED_INVALID_ARGUMENTS;
-}
diff --git a/libmemcached/encoding_key.h b/libmemcached/encoding_key.h
deleted file mode 100644 (file)
index a2c47b0..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-  memcached_string_t memcached_encoding_key(Memcached&);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached/error.cc b/libmemcached/error.cc
deleted file mode 100644 (file)
index 3de8ece..0000000
+++ /dev/null
@@ -1,675 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-#include "libmemcached/assert.hpp"
-
-#include <cerrno>
-#include <cstdarg>
-#include <cstdio>
-
-#define MAX_ERROR_LENGTH 2048
-struct memcached_error_t
-{
-  Memcached *root;
-  uint64_t query_id;
-  struct memcached_error_t *next;
-  memcached_return_t rc;
-  int local_errno;
-  size_t size;
-  char message[MAX_ERROR_LENGTH];
-};
-
-static void _set(memcached_instance_st& server, Memcached& memc)
-{
-  if (server.error_messages and server.error_messages->query_id != server.root->query_id)
-  {
-    memcached_error_free(server);
-  }
-
-  if (memc.error_messages)
-  {
-    if (memc.error_messages->rc == MEMCACHED_TIMEOUT)
-    {
-      server.io_wait_count.timeouts++;
-    }
-
-    memcached_error_t *error= libmemcached_xmalloc(&memc, memcached_error_t);
-    if (error)
-    {
-      memcpy(error, memc.error_messages, sizeof(memcached_error_t));
-      error->next= server.error_messages;
-      server.error_messages= error;
-    }
-  }
-}
-
-#if 0
-static int error_log_fd= -1;
-#endif
-
-static void _set(Memcached& memc, memcached_string_t *str, memcached_return_t &rc, const char *at, int local_errno= 0)
-{
-  if (memc.error_messages && memc.error_messages->query_id != memc.query_id)
-  {
-    memcached_error_free(memc);
-  }
-
-  if (memcached_fatal(rc) or rc == MEMCACHED_CLIENT_ERROR)
-  {
-    // For memory allocation we use our error since it is a bit more specific
-    if (local_errno == ENOMEM and rc == MEMCACHED_ERRNO)
-    {
-      rc= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-    }
-
-    if (rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
-    {
-      local_errno= ENOMEM;
-    }
-
-    if (rc == MEMCACHED_ERRNO and not local_errno)
-    {
-      local_errno= errno;
-      rc= MEMCACHED_ERRNO;
-    }
-
-    if (rc == MEMCACHED_ERRNO and local_errno == ENOTCONN)
-    {
-      rc= MEMCACHED_CONNECTION_FAILURE;
-    }
-
-    if (rc == MEMCACHED_ERRNO and local_errno == ECONNRESET)
-    {
-      rc= MEMCACHED_CONNECTION_FAILURE;
-    }
-
-    if (local_errno == EINVAL)
-    {
-      rc= MEMCACHED_INVALID_ARGUMENTS;
-    }
-
-    if (local_errno == ECONNREFUSED)
-    {
-      rc= MEMCACHED_CONNECTION_FAILURE;
-    }
-
-    if (rc == MEMCACHED_TIMEOUT)
-    {
-    }
-
-    memcached_error_t *error= libmemcached_xmalloc(&memc, memcached_error_t);
-    if (error == NULL) // Bad business if this happens
-    {
-      assert_msg(error, "libmemcached_xmalloc() failed to allocate a memcached_error_t");
-      return;
-    }
-
-    error->root= &memc;
-    error->query_id= memc.query_id;
-    error->rc= rc;
-    error->local_errno= local_errno;
-
-    // MEMCACHED_CLIENT_ERROR is a special case because it is an error coming from the server
-    if (rc == MEMCACHED_CLIENT_ERROR)
-    {
-      assert(str);
-      assert(str->size);
-      if (str and str->size)
-      {
-        assert(error->local_errno == 0);
-        error->local_errno= 0;
-
-        error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%p) %.*s", 
-                                   error->root,
-                                   int(str->size), str->c_str);
-      }
-    }
-    else if (local_errno)
-    {
-      const char *errmsg_ptr;
-      char errmsg[MAX_ERROR_LENGTH];
-      errmsg[0]= 0;
-      errmsg_ptr= errmsg;
-
-#if defined(STRERROR_R_CHAR_P) && STRERROR_R_CHAR_P
-      errmsg_ptr= strerror_r(local_errno, errmsg, sizeof(errmsg));
-#elif defined(HAVE_STRERROR_R) && HAVE_STRERROR_R
-      strerror_r(local_errno, errmsg, sizeof(errmsg));
-      errmsg_ptr= errmsg;
-#elif defined(HAVE_STRERROR) && HAVE_STRERROR
-      snprintf(errmsg, sizeof(errmsg), "%s", strerror(local_errno));
-      errmsg_ptr= errmsg;
-#endif
-
-      if (str and str->size and local_errno)
-      {
-        error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%p) %s(%s), %.*s -> %s", 
-                                   error->root,
-                                   memcached_strerror(&memc, rc), 
-                                   errmsg_ptr,
-                                   memcached_string_printf(*str), at);
-      }
-      else
-      {
-        error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%p) %s(%s) -> %s", 
-                                   error->root,
-                                   memcached_strerror(&memc, rc), 
-                                   errmsg_ptr,
-                                   at);
-      }
-    }
-    else if (rc == MEMCACHED_PARSE_ERROR and str and str->size)
-    {
-      error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%p) %.*s -> %s", 
-                                 error->root,
-                                 int(str->size), str->c_str, at);
-    }
-    else if (str and str->size)
-    {
-      error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%p) %s, %.*s -> %s", 
-                                 error->root,
-                                 memcached_strerror(&memc, rc), 
-                                 int(str->size), str->c_str, at);
-    }
-    else
-    {
-      error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%p) %s -> %s", 
-                                 error->root,
-                                 memcached_strerror(&memc, rc), at);
-    }
-
-    error->next= memc.error_messages;
-    memc.error_messages= error;
-#if 0
-    if (error_log_fd == -1)
-    {
-  //    unlink("/tmp/libmemcachd.log");
-      if ((error_log_fd= open("/tmp/libmemcachd.log", O_CREAT | O_WRONLY | O_APPEND, 0644)) < 0)
-      {
-        perror("open");
-        error_log_fd= -1;
-      }
-    }
-    ::write(error_log_fd, error->message, error->size);
-    ::write(error_log_fd, "\n", 1);
-#endif
-  }
-}
-
-memcached_return_t memcached_set_error(Memcached& memc, memcached_return_t rc, const char *at, const char *str, size_t length)
-{
-  assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
-  memcached_string_t tmp= { str, length };
-  return memcached_set_error(memc, rc, at, tmp);
-}
-
-memcached_return_t memcached_set_error(memcached_instance_st& self, memcached_return_t rc, const char *at, const char *str, size_t length)
-{
-  assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
-  assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a Instance");
-
-  memcached_string_t tmp= { str, length };
-  return memcached_set_error(self, rc, at, tmp);
-}
-
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
-#endif
-
-memcached_return_t memcached_set_error(Memcached& memc, memcached_return_t rc, const char *at, memcached_string_t& str)
-{
-  assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
-  if (memcached_fatal(rc))
-  {
-    _set(memc, &str, rc, at);
-  }
-
-  return rc;
-}
-
-memcached_return_t memcached_set_parser_error(Memcached& memc,
-                                              const char *at,
-                                              const char *format, ...)
-{
-  va_list args;
-
-  char buffer[BUFSIZ];
-  va_start(args, format);
-  int length= vsnprintf(buffer, sizeof(buffer), format, args);
-  va_end(args);
-
-  return memcached_set_error(memc, MEMCACHED_PARSE_ERROR, at, buffer, length);
-}
-
-static inline size_t append_host_to_string(memcached_instance_st& self, char* buffer, const size_t buffer_length)
-{
-  size_t size= 0;
-  switch (self.type)
-  {
-  case MEMCACHED_CONNECTION_TCP:
-  case MEMCACHED_CONNECTION_UDP:
-    size+= snprintf(buffer, buffer_length, " host: %s:%d",
-                    self.hostname(), int(self.port()));
-    break;
-
-  case MEMCACHED_CONNECTION_UNIX_SOCKET:
-    size+= snprintf(buffer, buffer_length, " socket: %s",
-                    self.hostname());
-    break;
-  }
-
-  return size;
-}
-
-memcached_return_t memcached_set_error(memcached_instance_st& self, memcached_return_t rc, const char *at, memcached_string_t& str)
-{
-  assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
-  assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_instance_st");
-  if (memcached_fatal(rc) == false and rc != MEMCACHED_CLIENT_ERROR)
-  {
-    return rc;
-  }
-
-  char hostname_port_message[MAX_ERROR_LENGTH];
-  char* hostname_port_message_ptr= hostname_port_message;
-  int size= 0;
-  if (str.size)
-  {
-    size= snprintf(hostname_port_message_ptr, sizeof(hostname_port_message), "%.*s, ",
-                   memcached_string_printf(str));
-    hostname_port_message_ptr+= size;
-  }
-
-  size+= append_host_to_string(self, hostname_port_message_ptr, sizeof(hostname_port_message) -size);
-
-  memcached_string_t error_host= { hostname_port_message, size_t(size) };
-
-  assert_msg(self.root, "Programmer error, root was not set on instance");
-  if (self.root)
-  {
-    _set(*self.root, &error_host, rc, at);
-    _set(self, (*self.root));
-    assert(self.error_messages);
-    assert(self.root->error_messages);
-    assert(self.error_messages->rc == self.root->error_messages->rc);
-  }
-
-  return rc;
-}
-
-memcached_return_t memcached_set_error(memcached_instance_st& self, memcached_return_t rc, const char *at)
-{
-  assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_instance_st");
-  if (memcached_fatal(rc) == false)
-  {
-    return rc;
-  }
-
-  char hostname_port[MEMCACHED_NI_MAXHOST +MEMCACHED_NI_MAXSERV + sizeof("host : ")];
-  size_t size= append_host_to_string(self, hostname_port, sizeof(hostname_port));
-
-  memcached_string_t error_host= { hostname_port, size};
-
-  if (self.root)
-  {
-    _set(*self.root, &error_host, rc, at);
-    _set(self, *self.root);
-  }
-
-  return rc;
-}
-
-memcached_return_t memcached_set_error(Memcached& self, memcached_return_t rc, const char *at)
-{
-  assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
-  if (memcached_fatal(rc) == false)
-  {
-    return rc;
-  }
-
-  _set(self, NULL, rc, at);
-
-  return rc;
-}
-
-memcached_return_t memcached_set_errno(Memcached& self, int local_errno, const char *at, const char *str, size_t length)
-{
-  memcached_string_t tmp= { str, length };
-  return memcached_set_errno(self, local_errno, at, tmp);
-}
-
-memcached_return_t memcached_set_errno(memcached_instance_st& self, int local_errno, const char *at, const char *str, size_t length)
-{
-  memcached_string_t tmp= { str, length };
-  return memcached_set_errno(self, local_errno, at, tmp);
-}
-
-memcached_return_t memcached_set_errno(Memcached& self, int local_errno, const char *at)
-{
-  if (local_errno == 0)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  memcached_return_t rc= MEMCACHED_ERRNO;
-  _set(self, NULL, rc, at, local_errno);
-
-  return rc;
-}
-
-memcached_return_t memcached_set_errno(Memcached& memc, int local_errno, const char *at, memcached_string_t& str)
-{
-  if (local_errno == 0)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  memcached_return_t rc= MEMCACHED_ERRNO;
-  _set(memc, &str, rc, at, local_errno);
-
-  return rc;
-}
-
-memcached_return_t memcached_set_errno(memcached_instance_st& self, int local_errno, const char *at, memcached_string_t& str)
-{
-  if (local_errno == 0)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  char hostname_port_message[MAX_ERROR_LENGTH];
-  char* hostname_port_message_ptr= hostname_port_message;
-  size_t size= 0;
-  if (str.size)
-  {
-    size= snprintf(hostname_port_message_ptr, sizeof(hostname_port_message), "%.*s, ", memcached_string_printf(str));
-  }
-  size+= append_host_to_string(self, hostname_port_message_ptr, sizeof(hostname_port_message) -size);
-
-  memcached_string_t error_host= { hostname_port_message, size };
-
-  memcached_return_t rc= MEMCACHED_ERRNO;
-  if (self.root == NULL)
-  {
-    return rc;
-  }
-
-  _set(*self.root, &error_host, rc, at, local_errno);
-  _set(self, (*self.root));
-
-#if 0
-  if (self.root->error_messages->rc != self.error_messages->rc)
-  {
-    fprintf(stderr, "%s:%d %s != %s\n", __FILE__, __LINE__,
-            memcached_strerror(NULL, self.root->error_messages->rc),
-            memcached_strerror(NULL, self.error_messages->rc));
-  }
-#endif
-
-  return rc;
-}
-
-memcached_return_t memcached_set_errno(memcached_instance_st& self, int local_errno, const char *at)
-{
-  if (local_errno == 0)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  char hostname_port_message[MAX_ERROR_LENGTH];
-  size_t size= append_host_to_string(self, hostname_port_message, sizeof(hostname_port_message));
-
-  memcached_string_t error_host= { hostname_port_message, size };
-
-  memcached_return_t rc= MEMCACHED_ERRNO;
-  if (self.root == NULL)
-  {
-    return rc;
-  }
-
-  _set(*self.root, &error_host, rc, at, local_errno);
-  _set(self, (*self.root));
-
-  return rc;
-}
-
-static void _error_print(const memcached_error_t *error)
-{
-  if (error == NULL)
-  {
-    return;
-  }
-
-  if (error->size == 0)
-  {
-    fprintf(stderr, "\t%s\n", memcached_strerror(NULL, error->rc) );
-  }
-  else
-  {
-    fprintf(stderr, "\t%s %s\n", memcached_strerror(NULL, error->rc), error->message);
-  }
-
-  _error_print(error->next);
-}
-
-void memcached_error_print(const Memcached *shell)
-{
-  const Memcached* self= memcached2Memcached(shell);
-  if (self == NULL)
-  {
-    return;
-  }
-
-  _error_print(self->error_messages);
-
-  for (uint32_t x= 0; x < memcached_server_count(self); x++)
-  {
-    memcached_instance_st* instance= memcached_instance_by_position(self, x);
-
-    _error_print(instance->error_messages);
-  }
-}
-
-static void _error_free(memcached_error_t *error)
-{
-  if (error)
-  {
-    _error_free(error->next);
-
-    libmemcached_free(error->root, error);
-  }
-}
-
-void memcached_error_free(Memcached& self)
-{
-  _error_free(self.error_messages);
-  self.error_messages= NULL;
-}
-
-void memcached_error_free(memcached_instance_st& self)
-{
-  _error_free(self.error_messages);
-  self.error_messages= NULL;
-}
-
-void memcached_error_free(memcached_server_st& self)
-{
-  _error_free(self.error_messages);
-  self.error_messages= NULL;
-}
-
-const char *memcached_error(const memcached_st *memc)
-{
-  return memcached_last_error_message(memc);
-}
-
-const char *memcached_last_error_message(const memcached_st *shell)
-{
-  const Memcached* memc= memcached2Memcached(shell);
-  if (memc)
-  {
-    if (memc->error_messages)
-    {
-      if (memc->error_messages->size and memc->error_messages->message[0])
-      {
-        return memc->error_messages->message;
-      }
-
-      return memcached_strerror(memc, memc->error_messages->rc);
-    }
-
-    return memcached_strerror(memc, MEMCACHED_SUCCESS);
-  }
-
-  return memcached_strerror(memc, MEMCACHED_INVALID_ARGUMENTS);
-}
-
-bool memcached_has_current_error(Memcached &memc)
-{
-  if (memc.error_messages 
-      and memc.error_messages->query_id == memc.query_id
-      and memcached_failed(memc.error_messages->rc))
-  {
-    return true;
-  }
-
-  return false;
-}
-
-bool memcached_has_current_error(memcached_instance_st& server)
-{
-  return memcached_has_current_error(*(server.root));
-}
-
-memcached_return_t memcached_last_error(const memcached_st *shell)
-{
-  const Memcached* memc= memcached2Memcached(shell);
-  if (memc)
-  {
-    if (memc->error_messages)
-    {
-      return memc->error_messages->rc;
-    }
-
-    return MEMCACHED_SUCCESS;
-  }
-
-  return MEMCACHED_INVALID_ARGUMENTS;
-}
-
-int memcached_last_error_errno(const memcached_st *shell)
-{
-  const Memcached* memc= memcached2Memcached(shell);
-  if (memc == NULL)
-  {
-    return 0;
-  }
-
-  if (memc->error_messages == NULL)
-  {
-    return 0;
-  }
-
-  return memc->error_messages->local_errno;
-}
-
-const char *memcached_server_error(const memcached_instance_st * server)
-{
-  if (server == NULL)
-  {
-    return NULL;
-  }
-
-  if (server->error_messages == NULL)
-  {
-    return memcached_strerror(server->root, MEMCACHED_SUCCESS);
-  }
-
-  if (server->error_messages->size == 0)
-  {
-    return memcached_strerror(server->root, server->error_messages->rc);
-  }
-
-  return server->error_messages->message;
-}
-
-
-memcached_error_t *memcached_error_copy(const memcached_instance_st& server)
-{
-  if (server.error_messages == NULL)
-  {
-    return NULL;
-  }
-
-  memcached_error_t *error= libmemcached_xmalloc(server.root, memcached_error_t);
-  memcpy(error, server.error_messages, sizeof(memcached_error_t));
-  error->next= NULL;
-
-  return error;
-}
-
-memcached_return_t memcached_server_error_return(const memcached_instance_st * ptr)
-{
-  if (ptr == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  if (ptr->error_messages)
-  {
-    return ptr->error_messages->rc;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_instance_error_return(memcached_instance_st* instance)
-{
-  if (instance == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  if (instance->error_messages)
-  {
-    return instance->error_messages->rc;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
diff --git a/libmemcached/error.hpp b/libmemcached/error.hpp
deleted file mode 100644 (file)
index 847dbc2..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libmemcached/common.h"
-
-#pragma once
-
-#ifdef __cplusplus
-
-#define STRINGIFY(x) #x
-#define TOSTRING(x) STRINGIFY(x)
-#define MEMCACHED_AT __FILE__ ":" TOSTRING(__LINE__)
-
-memcached_return_t memcached_set_parser_error(Memcached& memc,
-                                              const char *at,
-                                              const char *format, ...);
-
-memcached_return_t memcached_set_error(Memcached&, memcached_return_t rc, const char *at);
-
-memcached_return_t memcached_set_error(memcached_instance_st&, memcached_return_t rc, const char *at);
-
-memcached_return_t memcached_set_error(Memcached&, memcached_return_t rc, const char *at, const char *str, size_t length);
-
-memcached_return_t memcached_set_error(memcached_instance_st&, memcached_return_t rc, const char *at, const char *str, size_t length);
-
-memcached_return_t memcached_set_error(Memcached& memc, memcached_return_t rc, const char *at, memcached_string_t& str);
-
-memcached_return_t memcached_set_error(memcached_instance_st&, memcached_return_t rc, const char *at, memcached_string_t& str);
-
-memcached_return_t memcached_set_errno(Memcached& memc, int local_errno, const char *at, memcached_string_t& str);
-
-memcached_return_t memcached_set_errno(memcached_instance_st&, int local_errno, const char *at, memcached_string_t& str);
-
-memcached_return_t memcached_set_errno(Memcached& memc, int local_errno, const char *at, const char *str, size_t length);
-
-memcached_return_t memcached_set_errno(memcached_instance_st&, int local_errno, const char *at, const char *str, size_t length);
-
-memcached_return_t memcached_set_errno(Memcached& memc, int local_errno, const char *at);
-
-memcached_return_t memcached_set_errno(memcached_instance_st&, int local_errno, const char *at);
-
-bool memcached_has_current_error(Memcached&);
-
-bool memcached_has_current_error(memcached_instance_st&);
-
-void memcached_error_free(Memcached&);
-
-void memcached_error_free(memcached_server_st&);
-
-void memcached_error_free(memcached_instance_st& self);
-
-memcached_error_t *memcached_error_copy(const memcached_instance_st&);
-
-memcached_return_t memcached_instance_error_return(memcached_instance_st*);
-
-#endif
diff --git a/libmemcached/exist.cc b/libmemcached/exist.cc
deleted file mode 100644 (file)
index 5cb99e6..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-static memcached_return_t ascii_exist(Memcached *memc, memcached_instance_st* instance, const char *key, size_t key_length)
-{
-  libmemcached_io_vector_st vector[]=
-  {
-    { NULL, 0 },
-    { memcached_literal_param("add ") },
-    { memcached_array_string(memc->_namespace), memcached_array_size(memc->_namespace) },
-    { key, key_length },
-    { memcached_literal_param(" 0") },
-    { memcached_literal_param(" 2678400") },
-    { memcached_literal_param(" 0") },
-    { memcached_literal_param("\r\n") },
-    { memcached_literal_param("\r\n") }
-  };
-
-  /* Send command header */
-  memcached_return_t rc;
-  if (memcached_fatal(rc= memcached_vdo(instance, vector, 9, true)))
-  {
-    return rc;
-  }
-
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
-
-  if (rc == MEMCACHED_NOTSTORED)
-  {
-    rc= MEMCACHED_SUCCESS;
-  }
-
-  if (rc == MEMCACHED_STORED)
-  {
-    rc= MEMCACHED_NOTFOUND;
-  }
-
-  return rc;
-}
-
-static memcached_return_t binary_exist(Memcached *memc, memcached_instance_st* instance, const char *key, size_t key_length)
-{
-  protocol_binary_request_set request= {};
-  size_t send_length= sizeof(request.bytes);
-
-  initialize_binary_request(instance, request.message.header);
-
-  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_ADD;
-  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(memc->_namespace)));
-  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-  request.message.header.request.extlen= 8;
-  request.message.body.flags= 0;
-  request.message.body.expiration= htonl(2678400);
-
-  request.message.header.request.bodylen= htonl((uint32_t) (key_length 
-                                                            +memcached_array_size(memc->_namespace)
-                                                            +request.message.header.request.extlen));
-
-  libmemcached_io_vector_st vector[]=
-  {
-    { NULL, 0 },
-    { request.bytes, send_length },
-    { memcached_array_string(memc->_namespace), memcached_array_size(memc->_namespace) },
-    { key, key_length }
-  };
-
-  /* write the header */
-  memcached_return_t rc;
-  if (memcached_fatal(rc= memcached_vdo(instance, vector, 4, true)))
-  {
-    return rc;
-  }
-
-  rc= memcached_response(instance, NULL, 0, NULL);
-
-  if (rc == MEMCACHED_SUCCESS)
-  {
-    rc= MEMCACHED_NOTFOUND;
-  }
-
-  if (rc == MEMCACHED_DATA_EXISTS)
-  {
-    rc= MEMCACHED_SUCCESS;
-  }
-
-  return rc;
-}
-
-memcached_return_t memcached_exist(memcached_st *memc, const char *key, size_t key_length)
-{
-  return memcached_exist_by_key(memc, key, key_length, key, key_length);
-}
-
-memcached_return_t memcached_exist_by_key(memcached_st *shell,
-                                          const char *group_key, size_t group_key_length,
-                                          const char *key, size_t key_length)
-{
-  Memcached* memc= memcached2Memcached(shell);
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(memc, true)))
-  {
-    return rc;
-  }
-
-  if (memcached_is_udp(memc))
-  {
-    return memcached_set_error(*memc, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
-  }
-
-  uint32_t server_key= memcached_generate_hash_with_redistribution(memc, group_key, group_key_length);
-  memcached_instance_st* instance= memcached_instance_fetch(memc, server_key);
-
-  if (memcached_is_binary(memc))
-  {
-    rc= binary_exist(memc, instance, key, key_length);
-  }
-  else
-  {
-    rc= ascii_exist(memc, instance, key, key_length);
-  }
-
-  return rc;
-}
diff --git a/libmemcached/fetch.cc b/libmemcached/fetch.cc
deleted file mode 100644 (file)
index d795109..0000000
+++ /dev/null
@@ -1,320 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-char *memcached_fetch(memcached_st *shell, char *key, size_t *key_length, 
-                      size_t *value_length, 
-                      uint32_t *flags,
-                      memcached_return_t *error)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  memcached_return_t unused;
-  if (error == NULL)
-  {
-    error= &unused;
-  }
-
-  if (memcached_is_udp(ptr))
-  {
-    if (value_length)
-    {
-      *value_length= 0;
-    }
-
-    if (key_length)
-    {
-      *key_length= 0;
-    }
-
-    if (flags)
-    {
-      *flags= 0;
-    }
-
-    if (key)
-    {
-      *key= 0;
-    }
-
-    *error= MEMCACHED_NOT_SUPPORTED;
-    return NULL;
-  }
-
-  memcached_result_st *result_buffer= &ptr->result;
-  result_buffer= memcached_fetch_result(ptr, result_buffer, error);
-  if (result_buffer == NULL or memcached_failed(*error))
-  {
-    WATCHPOINT_ASSERT(result_buffer == NULL);
-    if (value_length)
-    {
-      *value_length= 0;
-    }
-
-    if (key_length)
-    {
-      *key_length= 0;
-    }
-
-    if (flags)
-    {
-      *flags= 0;
-    }
-
-    if (key)
-    {
-      *key= 0;
-    }
-
-    return NULL;
-  }
-
-  if (value_length)
-  {
-    *value_length= memcached_string_length(&result_buffer->value);
-  }
-
-  if (key)
-  {
-    if (result_buffer->key_length > MEMCACHED_MAX_KEY)
-    {
-      *error= MEMCACHED_KEY_TOO_BIG;
-      if (value_length)
-      {
-        *value_length= 0;
-      }
-
-      if (key_length)
-      {
-        *key_length= 0;
-      }
-
-      if (flags)
-      {
-        *flags= 0;
-      }
-
-      if (key)
-      {
-        *key= 0;
-      }
-
-      return NULL;
-    }
-
-    strncpy(key, result_buffer->item_key, result_buffer->key_length); // For the binary protocol we will cut off the key :(
-    if (key_length)
-    {
-      *key_length= result_buffer->key_length;
-    }
-  }
-
-  if (flags)
-  {
-    *flags= result_buffer->item_flags;
-  }
-
-  return memcached_string_take_value(&result_buffer->value);
-}
-
-memcached_result_st *memcached_fetch_result(memcached_st *ptr,
-                                            memcached_result_st *result,
-                                            memcached_return_t *error)
-{
-  memcached_return_t unused;
-  if (error == NULL)
-  {
-    error= &unused;
-  }
-
-  if (ptr == NULL)
-  {
-    *error= MEMCACHED_INVALID_ARGUMENTS;
-    return NULL;
-  }
-
-  if (memcached_is_udp(ptr))
-  {
-    *error= MEMCACHED_NOT_SUPPORTED;
-    return NULL;
-  }
-
-  if (result == NULL)
-  {
-    // If we have already initialized (ie it is in use) our internal, we
-    // create one.
-    if (memcached_is_initialized(&ptr->result))
-    {
-      if ((result= memcached_result_create(ptr, NULL)) == NULL)
-      {
-        *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-        return NULL;
-      }
-    }
-    else
-    {
-      result= memcached_result_create(ptr, &ptr->result);
-    }
-  }
-
-  *error= MEMCACHED_MAXIMUM_RETURN; // We use this to see if we ever go into the loop
-  memcached_instance_st *server;
-  memcached_return_t read_ret= MEMCACHED_SUCCESS;
-  bool connection_failures= false;
-  while ((server= memcached_io_get_readable_server(ptr, read_ret)))
-  {
-    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-    *error= memcached_response(server, buffer, sizeof(buffer), result);
-
-    if (*error == MEMCACHED_IN_PROGRESS)
-    {
-      continue;
-    }
-    else if (*error == MEMCACHED_CONNECTION_FAILURE)
-    {
-      connection_failures= true;
-      continue;
-    }
-    else if (*error == MEMCACHED_SUCCESS)
-    {
-      result->count++;
-      return result;
-    }
-    else if (*error == MEMCACHED_END)
-    {
-      memcached_server_response_reset(server);
-    }
-    else if (*error != MEMCACHED_NOTFOUND)
-    {
-      break;
-    }
-  }
-
-  if (*error == MEMCACHED_NOTFOUND and result->count)
-  {
-    *error= MEMCACHED_END;
-  }
-  else if (*error == MEMCACHED_MAXIMUM_RETURN and result->count)
-  {
-    *error= MEMCACHED_END;
-  }
-  else if (*error == MEMCACHED_MAXIMUM_RETURN) // while() loop was never entered
-  {
-    *error= MEMCACHED_NOTFOUND;
-  }
-  else if (connection_failures)
-  {
-    /*  
-        If we have a connection failure to some servers, the caller may
-        wish to treat that differently to getting a definitive NOT_FOUND
-        from all servers, so return MEMCACHED_CONNECTION_FAILURE to allow
-        that. 
-        */
-    *error= MEMCACHED_CONNECTION_FAILURE;
-  }
-  else if (*error == MEMCACHED_SUCCESS)
-  {
-    *error= MEMCACHED_END;
-  }
-  else if (result->count == 0)
-  {
-    *error= MEMCACHED_NOTFOUND;
-  }
-
-  /* We have completed reading data */
-  if (memcached_is_allocated(result))
-  {
-    memcached_result_free(result);
-  }
-  else
-  {
-    result->count= 0;
-    memcached_string_reset(&result->value);
-  }
-
-  return NULL;
-}
-
-memcached_return_t memcached_fetch_execute(memcached_st *shell, 
-                                           memcached_execute_fn *callback,
-                                           void *context,
-                                           uint32_t number_of_callbacks)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  memcached_result_st *result= &ptr->result;
-  memcached_return_t rc;
-  bool some_errors= false;
-
-  while ((result= memcached_fetch_result(ptr, result, &rc)))
-  {
-    if (memcached_failed(rc) and rc == MEMCACHED_NOTFOUND)
-    {
-      continue;
-    }
-    else if (memcached_failed(rc))
-    {
-      memcached_set_error(*ptr, rc, MEMCACHED_AT);
-      some_errors= true;
-      continue;
-    }
-
-    for (uint32_t x= 0; x < number_of_callbacks; x++)
-    {
-      memcached_return_t ret= (*callback[x])(ptr, result, context);
-      if (memcached_failed(ret))
-      {
-        some_errors= true;
-        memcached_set_error(*ptr, ret, MEMCACHED_AT);
-        break;
-      }
-    }
-  }
-
-  if (some_errors)
-  {
-    return MEMCACHED_SOME_ERRORS;
-  }
-
-  // If we were able to run all keys without issue we return
-  // MEMCACHED_SUCCESS
-  if (memcached_success(rc))
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  return rc;
-}
diff --git a/libmemcached/flag.cc b/libmemcached/flag.cc
deleted file mode 100644 (file)
index 09b401e..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-bool memcached_flag(const memcached_st& memc, const memcached_flag_t flag)
-{
-  switch (flag)
-  {
-  case MEMCACHED_FLAG_AUTO_EJECT_HOSTS:
-    return memcached_is_auto_eject_hosts(&memc);
-
-  case MEMCACHED_FLAG_BINARY_PROTOCOL:
-    return memcached_is_binary(&memc);
-
-  case MEMCACHED_FLAG_BUFFER_REQUESTS:
-    return memcached_is_buffering(&memc);
-
-  case MEMCACHED_FLAG_HASH_WITH_NAMESPACE:
-    return memcached_is_hash_with_namespace(&memc);
-
-  case MEMCACHED_FLAG_NO_BLOCK:
-    return memcached_is_no_block(&memc);
-
-  case MEMCACHED_FLAG_REPLY:
-    return memcached_is_replying(&memc);
-
-  case MEMCACHED_FLAG_RANDOMIZE_REPLICA_READ:
-    return memcached_is_randomize_replica_read(&memc);
-
-  case MEMCACHED_FLAG_SUPPORT_CAS:
-    return memcached_is_cas(&memc);
-
-  case MEMCACHED_FLAG_TCP_NODELAY:
-    return memcached_is_tcp_nodelay(&memc);
-
-  case MEMCACHED_FLAG_USE_SORT_HOSTS:
-    return memcached_is_use_sort_hosts(&memc);
-
-  case MEMCACHED_FLAG_USE_UDP:
-    return memcached_is_udp(&memc);
-
-  case MEMCACHED_FLAG_VERIFY_KEY:
-    return memcached_is_verify_key(&memc);
-
-  case MEMCACHED_FLAG_TCP_KEEPALIVE:
-    return memcached_is_use_sort_hosts(&memc);
-
-  case MEMCACHED_FLAG_IS_AES:
-    return memcached_is_aes(&memc);
-
-  case MEMCACHED_FLAG_IS_FETCHING_VERSION:
-    return memcached_is_fetching_version(&memc);
-  }
-
-  abort();
-}
-
-void memcached_flag(memcached_st& memc, const memcached_flag_t flag, const bool arg)
-{
-  switch (flag)
-  {
-  case MEMCACHED_FLAG_AUTO_EJECT_HOSTS:
-    memcached_set_auto_eject_hosts(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_BINARY_PROTOCOL:
-    memcached_set_binary(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_BUFFER_REQUESTS:
-    memcached_set_buffering(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_HASH_WITH_NAMESPACE:
-    memcached_set_hash_with_namespace(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_NO_BLOCK:
-    memcached_set_no_block(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_REPLY:
-    memcached_set_replying(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_RANDOMIZE_REPLICA_READ:
-    memcached_set_randomize_replica_read(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_SUPPORT_CAS:
-    memcached_set_cas(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_TCP_NODELAY:
-    memcached_set_tcp_nodelay(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_USE_SORT_HOSTS:
-    memcached_set_use_sort_hosts(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_USE_UDP:
-    memcached_set_udp(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_VERIFY_KEY:
-    memcached_set_verify_key(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_TCP_KEEPALIVE:
-    memcached_set_use_sort_hosts(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_IS_AES:
-    memcached_set_aes(memc, arg);
-    break;
-
-  case MEMCACHED_FLAG_IS_FETCHING_VERSION:
-    memcached_set_fetching_version(memc, arg);
-    break;
-  }
-}
diff --git a/libmemcached/flag.hpp b/libmemcached/flag.hpp
deleted file mode 100644 (file)
index 6efe2ef..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-enum memcached_flag_t
-{
-  MEMCACHED_FLAG_AUTO_EJECT_HOSTS,
-  MEMCACHED_FLAG_BINARY_PROTOCOL,
-  MEMCACHED_FLAG_BUFFER_REQUESTS,
-  MEMCACHED_FLAG_HASH_WITH_NAMESPACE,
-  MEMCACHED_FLAG_NO_BLOCK,
-  MEMCACHED_FLAG_REPLY,
-  MEMCACHED_FLAG_RANDOMIZE_REPLICA_READ,
-  MEMCACHED_FLAG_SUPPORT_CAS,
-  MEMCACHED_FLAG_TCP_NODELAY,
-  MEMCACHED_FLAG_USE_SORT_HOSTS,
-  MEMCACHED_FLAG_USE_UDP,
-  MEMCACHED_FLAG_VERIFY_KEY,
-  MEMCACHED_FLAG_TCP_KEEPALIVE,
-  MEMCACHED_FLAG_IS_AES,
-  MEMCACHED_FLAG_IS_FETCHING_VERSION
-};
-
-bool memcached_flag(const memcached_st&, const memcached_flag_t);
-void memcached_flag(memcached_st&, const memcached_flag_t, const bool);
diff --git a/libmemcached/flush.cc b/libmemcached/flush.cc
deleted file mode 100644 (file)
index 9702771..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-static memcached_return_t memcached_flush_binary(Memcached *ptr, 
-                                                 time_t expiration,
-                                                 const bool reply)
-{
-  protocol_binary_request_flush request= {};
-
-  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
-  request.message.header.request.extlen= 4;
-  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-  request.message.header.request.bodylen= htonl(request.message.header.request.extlen);
-  request.message.body.expiration= htonl((uint32_t) expiration);
-
-  memcached_return_t rc= MEMCACHED_SUCCESS;
-
-  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
-  {
-    memcached_instance_st* instance= memcached_instance_fetch(ptr, x);
-    initialize_binary_request(instance, request.message.header);
-
-    if (reply)
-    {
-      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
-    }
-    else
-    {
-      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSHQ;
-    }
-
-    libmemcached_io_vector_st vector[]=
-    {
-      { NULL, 0 },
-      { request.bytes, sizeof(request.bytes) }
-    };
-
-    memcached_return_t rrc;
-    if (memcached_failed(rrc= memcached_vdo(instance, vector, 2, true)))
-    {
-      if (instance->error_messages == NULL or instance->root->error_messages == NULL)
-      {
-        memcached_set_error(*instance, rrc, MEMCACHED_AT);
-      }
-      rc= MEMCACHED_SOME_ERRORS;
-    } 
-  }
-
-  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
-  {
-    memcached_instance_st* instance= memcached_instance_fetch(ptr, x);
-
-    if (instance->response_count() > 0)
-    {
-      (void)memcached_response(instance, NULL, 0, NULL);
-    }
-  }
-
-  return rc;
-}
-
-static memcached_return_t memcached_flush_textual(Memcached *ptr, 
-                                                  time_t expiration,
-                                                  const bool reply)
-{
-  char buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
-  int send_length= 0;
-  if (expiration)
-  {
-    send_length= snprintf(buffer, sizeof(buffer), "%llu", (unsigned long long)expiration);
-  }
-
-  if (size_t(send_length) >= sizeof(buffer) or send_length < 0)
-  {
-    return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                               memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
-  }
-
-  memcached_return_t rc= MEMCACHED_SUCCESS;
-  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
-  {
-    memcached_instance_st* instance= memcached_instance_fetch(ptr, x);
-
-    libmemcached_io_vector_st vector[]=
-    {
-      { NULL, 0 },
-      { memcached_literal_param("flush_all ") },
-      { buffer, size_t(send_length) },
-      { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
-      { memcached_literal_param("\r\n") }
-    };
-
-    memcached_return_t rrc= memcached_vdo(instance, vector, 5, true);
-    if (memcached_success(rrc) and reply == true)
-    {
-      char response_buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-      rrc= memcached_response(instance, response_buffer, sizeof(response_buffer), NULL);
-    }
-
-    if (memcached_failed(rrc))
-    {
-      // If an error has already been reported, then don't add to it
-      if (instance->error_messages == NULL or instance->root->error_messages == NULL)
-      {
-        memcached_set_error(*instance, rrc, MEMCACHED_AT);
-      }
-      rc= MEMCACHED_SOME_ERRORS;
-    }
-  }
-
-  return rc;
-}
-
-memcached_return_t memcached_flush(memcached_st *shell, time_t expiration)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr, true)))
-  {
-    return rc;
-  }
-
-  bool reply= memcached_is_replying(ptr);
-
-  LIBMEMCACHED_MEMCACHED_FLUSH_START();
-  if (memcached_is_binary(ptr))
-  {
-    rc= memcached_flush_binary(ptr, expiration, reply);
-  }
-  else
-  {
-    rc= memcached_flush_textual(ptr, expiration, reply);
-  }
-  LIBMEMCACHED_MEMCACHED_FLUSH_END();
-
-  return rc;
-}
diff --git a/libmemcached/flush_buffers.cc b/libmemcached/flush_buffers.cc
deleted file mode 100644 (file)
index 24f7c0d..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-memcached_return_t memcached_flush_buffers(memcached_st *shell)
-{
-  Memcached* memc= memcached2Memcached(shell);
-  if (memc)
-  {
-    memcached_return_t ret= MEMCACHED_SUCCESS;
-
-    for (uint32_t x= 0; x < memcached_server_count(memc); ++x)
-    {
-      memcached_instance_st* instance= memcached_instance_fetch(memc, x);
-
-      if (instance->write_buffer_offset != 0) 
-      {
-        if (instance->fd == INVALID_SOCKET and
-            (ret= memcached_connect(instance)) != MEMCACHED_SUCCESS)
-        {
-          WATCHPOINT_ERROR(ret);
-          return ret;
-        }
-
-        if (memcached_io_write(instance) == false)
-        {
-          ret= MEMCACHED_SOME_ERRORS;
-        }
-      }
-    }
-
-    return ret;
-  }
-
-  return MEMCACHED_INVALID_ARGUMENTS;
-}
diff --git a/libmemcached/get.cc b/libmemcached/get.cc
deleted file mode 100644 (file)
index 86d8cf2..0000000
+++ /dev/null
@@ -1,738 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-/*
-  What happens if no servers exist?
-*/
-char *memcached_get(memcached_st *ptr, const char *key,
-                    size_t key_length,
-                    size_t *value_length,
-                    uint32_t *flags,
-                    memcached_return_t *error)
-{
-  return memcached_get_by_key(ptr, NULL, 0, key, key_length, value_length,
-                              flags, error);
-}
-
-static memcached_return_t __mget_by_key_real(memcached_st *ptr,
-                                             const char *group_key,
-                                             size_t group_key_length,
-                                             const char * const *keys,
-                                             const size_t *key_length,
-                                             size_t number_of_keys,
-                                             const bool mget_mode);
-char *memcached_get_by_key(memcached_st *shell,
-                           const char *group_key,
-                           size_t group_key_length,
-                           const char *key, size_t key_length,
-                           size_t *value_length,
-                           uint32_t *flags,
-                           memcached_return_t *error)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  memcached_return_t unused;
-  if (error == NULL)
-  {
-    error= &unused;
-  }
-
-  uint64_t query_id= 0;
-  if (ptr)
-  {
-    query_id= ptr->query_id;
-  }
-
-  /* Request the key */
-  *error= __mget_by_key_real(ptr, group_key, group_key_length,
-                             (const char * const *)&key, &key_length, 
-                             1, false);
-  if (ptr)
-  {
-    assert_msg(ptr->query_id == query_id +1, "Programmer error, the query_id was not incremented.");
-  }
-
-  if (memcached_failed(*error))
-  {
-    if (ptr)
-    {
-      if (memcached_has_current_error(*ptr)) // Find the most accurate error
-      {
-        *error= memcached_last_error(ptr);
-      }
-    }
-
-    if (value_length) 
-    {
-      *value_length= 0;
-    }
-
-    return NULL;
-  }
-
-  char *value= memcached_fetch(ptr, NULL, NULL,
-                               value_length, flags, error);
-  assert_msg(ptr->query_id == query_id +1, "Programmer error, the query_id was not incremented.");
-
-  /* This is for historical reasons */
-  if (*error == MEMCACHED_END)
-  {
-    *error= MEMCACHED_NOTFOUND;
-  }
-  if (value == NULL)
-  {
-    if (ptr->get_key_failure and *error == MEMCACHED_NOTFOUND)
-    {
-      memcached_result_st key_failure_result;
-      memcached_result_st* result_ptr= memcached_result_create(ptr, &key_failure_result);
-      memcached_return_t rc= ptr->get_key_failure(ptr, key, key_length, result_ptr);
-
-      /* On all failure drop to returning NULL */
-      if (rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED)
-      {
-        if (rc == MEMCACHED_BUFFERED)
-        {
-          uint64_t latch; /* We use latch to track the state of the original socket */
-          latch= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS);
-          if (latch == 0)
-          {
-            memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1);
-          }
-
-          rc= memcached_set(ptr, key, key_length,
-                            (memcached_result_value(result_ptr)),
-                            (memcached_result_length(result_ptr)),
-                            0,
-                            (memcached_result_flags(result_ptr)));
-
-          if (rc == MEMCACHED_BUFFERED and latch == 0)
-          {
-            memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 0);
-          }
-        }
-        else
-        {
-          rc= memcached_set(ptr, key, key_length,
-                            (memcached_result_value(result_ptr)),
-                            (memcached_result_length(result_ptr)),
-                            0,
-                            (memcached_result_flags(result_ptr)));
-        }
-
-        if (rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED)
-        {
-          *error= rc;
-          *value_length= memcached_result_length(result_ptr);
-          *flags= memcached_result_flags(result_ptr);
-          char *result_value=  memcached_string_take_value(&result_ptr->value);
-          memcached_result_free(result_ptr);
-
-          return result_value;
-        }
-      }
-
-      memcached_result_free(result_ptr);
-    }
-    assert_msg(ptr->query_id == query_id +1, "Programmer error, the query_id was not incremented.");
-
-    return NULL;
-  }
-
-  return value;
-}
-
-memcached_return_t memcached_mget(memcached_st *ptr,
-                                  const char * const *keys,
-                                  const size_t *key_length,
-                                  size_t number_of_keys)
-{
-  return memcached_mget_by_key(ptr, NULL, 0, keys, key_length, number_of_keys);
-}
-
-static memcached_return_t binary_mget_by_key(memcached_st *ptr,
-                                             const uint32_t master_server_key,
-                                             const bool is_group_key_set,
-                                             const char * const *keys,
-                                             const size_t *key_length,
-                                             const size_t number_of_keys,
-                                             const bool mget_mode);
-
-static memcached_return_t __mget_by_key_real(memcached_st *ptr,
-                                             const char *group_key,
-                                             const size_t group_key_length,
-                                             const char * const *keys,
-                                             const size_t *key_length,
-                                             size_t number_of_keys,
-                                             const bool mget_mode)
-{
-  bool failures_occured_in_sending= false;
-  const char *get_command= "get";
-  uint8_t get_command_length= 3;
-  unsigned int master_server_key= (unsigned int)-1; /* 0 is a valid server id! */
-
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr, true)))
-  {
-    return rc;
-  }
-
-  if (memcached_is_udp(ptr))
-  {
-    return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
-  }
-
-  LIBMEMCACHED_MEMCACHED_MGET_START();
-
-  if (number_of_keys == 0)
-  {
-    return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Numbers of keys provided was zero"));
-  }
-
-  if (memcached_failed((rc= memcached_key_test(*ptr, keys, key_length, number_of_keys))))
-  {
-    assert(memcached_last_error(ptr) == rc);
-
-    return rc;
-  }
-
-  bool is_group_key_set= false;
-  if (group_key and group_key_length)
-  {
-    master_server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
-    is_group_key_set= true;
-  }
-
-  /*
-    Here is where we pay for the non-block API. We need to remove any data sitting
-    in the queue before we start our get.
-
-    It might be optimum to bounce the connection if count > some number.
-  */
-  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
-  {
-    memcached_instance_st* instance= memcached_instance_fetch(ptr, x);
-
-    if (instance->response_count())
-    {
-      char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-
-      if (ptr->flags.no_block)
-      {
-        memcached_io_write(instance);
-      }
-
-      while(instance->response_count())
-      {
-        (void)memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, &ptr->result);
-      }
-    }
-  }
-
-  if (memcached_is_binary(ptr))
-  {
-    return binary_mget_by_key(ptr, master_server_key, is_group_key_set, keys,
-                              key_length, number_of_keys, mget_mode);
-  }
-
-  if (ptr->flags.support_cas)
-  {
-    get_command= "gets";
-    get_command_length= 4;
-  }
-
-  /*
-    If a server fails we warn about errors and start all over with sending keys
-    to the server.
-  */
-  WATCHPOINT_ASSERT(rc == MEMCACHED_SUCCESS);
-  size_t hosts_connected= 0;
-  for (uint32_t x= 0; x < number_of_keys; x++)
-  {
-    uint32_t server_key;
-
-    if (is_group_key_set)
-    {
-      server_key= master_server_key;
-    }
-    else
-    {
-      server_key= memcached_generate_hash_with_redistribution(ptr, keys[x], key_length[x]);
-    }
-
-    memcached_instance_st* instance= memcached_instance_fetch(ptr, server_key);
-
-    libmemcached_io_vector_st vector[]=
-    {
-      { get_command, get_command_length },
-      { memcached_literal_param(" ") },
-      { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
-      { keys[x], key_length[x] }
-    };
-
-
-    if (instance->response_count() == 0)
-    {
-      rc= memcached_connect(instance);
-
-      if (memcached_failed(rc))
-      {
-        memcached_set_error(*instance, rc, MEMCACHED_AT);
-        continue;
-      }
-      hosts_connected++;
-
-      if ((memcached_io_writev(instance, vector, 1, false)) == false)
-      {
-        failures_occured_in_sending= true;
-        continue;
-      }
-      WATCHPOINT_ASSERT(instance->cursor_active_ == 0);
-      memcached_instance_response_increment(instance);
-      WATCHPOINT_ASSERT(instance->cursor_active_ == 1);
-    }
-
-    {
-      if ((memcached_io_writev(instance, (vector + 1), 3, false)) == false)
-      {
-        memcached_instance_response_reset(instance);
-        failures_occured_in_sending= true;
-        continue;
-      }
-    }
-  }
-
-  if (hosts_connected == 0)
-  {
-    LIBMEMCACHED_MEMCACHED_MGET_END();
-
-    if (memcached_failed(rc))
-    {
-      return rc;
-    }
-
-    return memcached_set_error(*ptr, MEMCACHED_NO_SERVERS, MEMCACHED_AT);
-  }
-
-
-  /*
-    Should we muddle on if some servers are dead?
-  */
-  bool success_happened= false;
-  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
-  {
-    memcached_instance_st* instance= memcached_instance_fetch(ptr, x);
-
-    if (instance->response_count())
-    {
-      /* We need to do something about non-connnected hosts in the future */
-      if ((memcached_io_write(instance, "\r\n", 2, true)) == -1)
-      {
-        failures_occured_in_sending= true;
-      }
-      else
-      {
-        success_happened= true;
-      }
-    }
-  }
-
-  LIBMEMCACHED_MEMCACHED_MGET_END();
-
-  if (failures_occured_in_sending and success_happened)
-  {
-    return MEMCACHED_SOME_ERRORS;
-  }
-
-  if (success_happened)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  return MEMCACHED_FAILURE; // Complete failure occurred
-}
-
-memcached_return_t memcached_mget_by_key(memcached_st *shell,
-                                         const char *group_key,
-                                         size_t group_key_length,
-                                         const char * const *keys,
-                                         const size_t *key_length,
-                                         size_t number_of_keys)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  return __mget_by_key_real(ptr, group_key, group_key_length, keys, key_length, number_of_keys, true);
-}
-
-memcached_return_t memcached_mget_execute(memcached_st *ptr,
-                                          const char * const *keys,
-                                          const size_t *key_length,
-                                          size_t number_of_keys,
-                                          memcached_execute_fn *callback,
-                                          void *context,
-                                          unsigned int number_of_callbacks)
-{
-  return memcached_mget_execute_by_key(ptr, NULL, 0, keys, key_length,
-                                       number_of_keys, callback,
-                                       context, number_of_callbacks);
-}
-
-memcached_return_t memcached_mget_execute_by_key(memcached_st *shell,
-                                                 const char *group_key,
-                                                 size_t group_key_length,
-                                                 const char * const *keys,
-                                                 const size_t *key_length,
-                                                 size_t number_of_keys,
-                                                 memcached_execute_fn *callback,
-                                                 void *context,
-                                                 unsigned int number_of_callbacks)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr, false)))
-  {
-    return rc;
-  }
-
-  if (memcached_is_udp(ptr))
-  {
-    return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
-  }
-
-  if (memcached_is_binary(ptr) == false)
-  {
-    return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT,
-                               memcached_literal_param("ASCII protocol is not supported for memcached_mget_execute_by_key()"));
-  }
-
-  memcached_callback_st *original_callbacks= ptr->callbacks;
-  memcached_callback_st cb= {
-    callback,
-    context,
-    number_of_callbacks
-  };
-
-  ptr->callbacks= &cb;
-  rc= memcached_mget_by_key(ptr, group_key, group_key_length, keys,
-                            key_length, number_of_keys);
-  ptr->callbacks= original_callbacks;
-
-  return rc;
-}
-
-static memcached_return_t simple_binary_mget(memcached_st *ptr,
-                                             const uint32_t master_server_key,
-                                             bool is_group_key_set,
-                                             const char * const *keys,
-                                             const size_t *key_length,
-                                             const size_t number_of_keys, const bool mget_mode)
-{
-  memcached_return_t rc= MEMCACHED_NOTFOUND;
-
-  bool flush= (number_of_keys == 1);
-
-  if (memcached_failed(rc= memcached_key_test(*ptr, keys, key_length, number_of_keys)))
-  {
-    return rc;
-  }
-
-  /*
-    If a server fails we warn about errors and start all over with sending keys
-    to the server.
-  */
-  for (uint32_t x= 0; x < number_of_keys; ++x)
-  {
-    uint32_t server_key;
-
-    if (is_group_key_set)
-    {
-      server_key= master_server_key;
-    }
-    else
-    {
-      server_key= memcached_generate_hash_with_redistribution(ptr, keys[x], key_length[x]);
-    }
-
-    memcached_instance_st* instance= memcached_instance_fetch(ptr, server_key);
-
-    if (instance->response_count() == 0)
-    {
-      rc= memcached_connect(instance);
-      if (memcached_failed(rc))
-      {
-        continue;
-      }
-    }
-
-    protocol_binary_request_getk request= { }; //= {.bytes= {0}};
-    initialize_binary_request(instance, request.message.header);
-    if (mget_mode)
-    {
-      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETKQ;
-    }
-    else
-    {
-      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
-    }
-
-#if 0
-    {
-      memcached_return_t vk= memcached_validate_key_length(key_length[x], ptr->flags.binary_protocol);
-      if (memcached_failed(rc= memcached_key_test(*memc, (const char **)&key, &key_length, 1)))
-      {
-        memcached_set_error(ptr, vk, MEMCACHED_AT, memcached_literal_param("Key was too long."));
-
-        if (x > 0)
-        {
-          memcached_io_reset(instance);
-        }
-
-        return vk;
-      }
-    }
-#endif
-
-    request.message.header.request.keylen= htons((uint16_t)(key_length[x] + memcached_array_size(ptr->_namespace)));
-    request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-    request.message.header.request.bodylen= htonl((uint32_t)( key_length[x] + memcached_array_size(ptr->_namespace)));
-
-    libmemcached_io_vector_st vector[]=
-    {
-      { request.bytes, sizeof(request.bytes) },
-      { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
-      { keys[x], key_length[x] }
-    };
-
-    if (memcached_io_writev(instance, vector, 3, flush) == false)
-    {
-      memcached_server_response_reset(instance);
-      rc= MEMCACHED_SOME_ERRORS;
-      continue;
-    }
-
-    /* We just want one pending response per server */
-    memcached_server_response_reset(instance);
-    memcached_server_response_increment(instance);
-    if ((x > 0 and x == ptr->io_key_prefetch) and memcached_flush_buffers(ptr) != MEMCACHED_SUCCESS)
-    {
-      rc= MEMCACHED_SOME_ERRORS;
-    }
-  }
-
-  if (mget_mode)
-  {
-    /*
-      Send a noop command to flush the buffers
-    */
-    protocol_binary_request_noop request= {}; //= {.bytes= {0}};
-    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_NOOP;
-    request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-
-    for (uint32_t x= 0; x < memcached_server_count(ptr); ++x)
-    {
-      memcached_instance_st* instance= memcached_instance_fetch(ptr, x);
-
-      if (instance->response_count())
-      {
-        initialize_binary_request(instance, request.message.header);
-        if ((memcached_io_write(instance) == false) or
-            (memcached_io_write(instance, request.bytes, sizeof(request.bytes), true) == -1))
-        {
-          memcached_instance_response_reset(instance);
-          memcached_io_reset(instance);
-          rc= MEMCACHED_SOME_ERRORS;
-        }
-      }
-    }
-  }
-
-  return rc;
-}
-
-static memcached_return_t replication_binary_mget(memcached_st *ptr,
-                                                  uint32_t* hash,
-                                                  bool* dead_servers,
-                                                  const char *const *keys,
-                                                  const size_t *key_length,
-                                                  const size_t number_of_keys)
-{
-  memcached_return_t rc= MEMCACHED_NOTFOUND;
-  uint32_t start= 0;
-  uint64_t randomize_read= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ);
-
-  if (randomize_read)
-  {
-    start= (uint32_t)random() % (uint32_t)(ptr->number_of_replicas + 1);
-  }
-
-  /* Loop for each replica */
-  for (uint32_t replica= 0; replica <= ptr->number_of_replicas; ++replica)
-  {
-    bool success= true;
-
-    for (uint32_t x= 0; x < number_of_keys; ++x)
-    {
-      if (hash[x] == memcached_server_count(ptr))
-      {
-        continue; /* Already successfully sent */
-      }
-
-      uint32_t server= hash[x] +replica;
-
-      /* In case of randomized reads */
-      if (randomize_read and ((server + start) <= (hash[x] + ptr->number_of_replicas)))
-      {
-        server+= start;
-      }
-
-      while (server >= memcached_server_count(ptr))
-      {
-        server -= memcached_server_count(ptr);
-      }
-
-      if (dead_servers[server])
-      {
-        continue;
-      }
-
-      memcached_instance_st* instance= memcached_instance_fetch(ptr, server);
-
-      if (instance->response_count() == 0)
-      {
-        rc= memcached_connect(instance);
-
-        if (memcached_failed(rc))
-        {
-          memcached_io_reset(instance);
-          dead_servers[server]= true;
-          success= false;
-          continue;
-        }
-      }
-
-      protocol_binary_request_getk request= {};
-      initialize_binary_request(instance, request.message.header);
-      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
-      request.message.header.request.keylen= htons((uint16_t)(key_length[x] + memcached_array_size(ptr->_namespace)));
-      request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-      request.message.header.request.bodylen= htonl((uint32_t)(key_length[x] + memcached_array_size(ptr->_namespace)));
-
-      /*
-       * We need to disable buffering to actually know that the request was
-       * successfully sent to the server (so that we should expect a result
-       * back). It would be nice to do this in buffered mode, but then it
-       * would be complex to handle all error situations if we got to send
-       * some of the messages, and then we failed on writing out some others
-       * and we used the callback interface from memcached_mget_execute so
-       * that we might have processed some of the responses etc. For now,
-       * just make sure we work _correctly_
-     */
-      libmemcached_io_vector_st vector[]=
-      {
-        { request.bytes, sizeof(request.bytes) },
-        { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
-        { keys[x], key_length[x] }
-      };
-
-      if (memcached_io_writev(instance, vector, 3, true) == false)
-      {
-        memcached_io_reset(instance);
-        dead_servers[server]= true;
-        success= false;
-        continue;
-      }
-
-      memcached_server_response_increment(instance);
-      hash[x]= memcached_server_count(ptr);
-    }
-
-    if (success)
-    {
-      break;
-    }
-  }
-
-  return rc;
-}
-
-static memcached_return_t binary_mget_by_key(memcached_st *ptr,
-                                             const uint32_t master_server_key,
-                                             bool is_group_key_set,
-                                             const char * const *keys,
-                                             const size_t *key_length,
-                                             const size_t number_of_keys,
-                                             const bool mget_mode)
-{
-  if (ptr->number_of_replicas == 0)
-  {
-    return simple_binary_mget(ptr, master_server_key, is_group_key_set,
-                              keys, key_length, number_of_keys, mget_mode);
-  }
-
-  uint32_t* hash= libmemcached_xvalloc(ptr, number_of_keys, uint32_t);
-  bool* dead_servers= libmemcached_xcalloc(ptr, memcached_server_count(ptr), bool);
-
-  if (hash == NULL or dead_servers == NULL)
-  {
-    libmemcached_free(ptr, hash);
-    libmemcached_free(ptr, dead_servers);
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-  }
-
-  if (is_group_key_set)
-  {
-    for (size_t x= 0; x < number_of_keys; x++)
-    {
-      hash[x]= master_server_key;
-    }
-  }
-  else
-  {
-    for (size_t x= 0; x < number_of_keys; x++)
-    {
-      hash[x]= memcached_generate_hash_with_redistribution(ptr, keys[x], key_length[x]);
-    }
-  }
-
-  memcached_return_t rc= replication_binary_mget(ptr, hash, dead_servers, keys,
-                                                 key_length, number_of_keys);
-
-  WATCHPOINT_IFERROR(rc);
-  libmemcached_free(ptr, hash);
-  libmemcached_free(ptr, dead_servers);
-
-  return MEMCACHED_SUCCESS;
-}
diff --git a/libmemcached/hash.cc b/libmemcached/hash.cc
deleted file mode 100644 (file)
index 4e02312..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libmemcached/common.h>
-
-#include <sys/time.h>
-
-#include <libmemcached/virtual_bucket.h>
-
-uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash_t hash_algorithm)
-{
-  return libhashkit_digest(key, key_length, (hashkit_hash_algorithm_t)hash_algorithm);
-}
-
-static inline uint32_t generate_hash(const Memcached *ptr, const char *key, size_t key_length)
-{
-  return hashkit_digest(&ptr->hashkit, key, key_length);
-}
-
-static uint32_t dispatch_host(const Memcached *ptr, uint32_t hash)
-{
-  switch (ptr->distribution)
-  {
-  case MEMCACHED_DISTRIBUTION_CONSISTENT:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
-    {
-      uint32_t num= ptr->ketama.continuum_points_counter;
-      WATCHPOINT_ASSERT(ptr->ketama.continuum);
-
-      memcached_continuum_item_st *begin, *end, *left, *right, *middle;
-      begin= left= ptr->ketama.continuum;
-      end= right= ptr->ketama.continuum + num;
-
-      while (left < right)
-      {
-        middle= left + (right - left) / 2;
-        if (middle->value < hash)
-          left= middle + 1;
-        else
-          right= middle;
-      }
-      if (right == end)
-        right= begin;
-      return right->index;
-    }
-  case MEMCACHED_DISTRIBUTION_MODULA:
-    return hash % memcached_server_count(ptr);
-  case MEMCACHED_DISTRIBUTION_RANDOM:
-    return (uint32_t) random() % memcached_server_count(ptr);
-  case MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET:
-    {
-      return memcached_virtual_bucket_get(ptr, hash);
-    }
-  default:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX:
-    WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
-    return hash % memcached_server_count(ptr);
-  }
-  /* NOTREACHED */
-}
-
-/*
-  One version is public and will not modify the distribution hash, the other will.
-*/
-static inline uint32_t _generate_hash_wrapper(const Memcached *ptr, const char *key, size_t key_length)
-{
-  WATCHPOINT_ASSERT(memcached_server_count(ptr));
-
-  if (memcached_server_count(ptr) == 1)
-    return 0;
-
-  if (ptr->flags.hash_with_namespace)
-  {
-    size_t temp_length= memcached_array_size(ptr->_namespace) + key_length;
-    char temp[MEMCACHED_MAX_KEY];
-
-    if (temp_length > MEMCACHED_MAX_KEY -1)
-      return 0;
-
-    strncpy(temp, memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace));
-    strncpy(temp + memcached_array_size(ptr->_namespace), key, key_length);
-
-    return generate_hash(ptr, temp, temp_length);
-  }
-  else
-  {
-    return generate_hash(ptr, key, key_length);
-  }
-}
-
-static inline void _regen_for_auto_eject(Memcached *ptr)
-{
-  if (_is_auto_eject_host(ptr) && ptr->ketama.next_distribution_rebuild)
-  {
-    struct timeval now;
-
-    if (gettimeofday(&now, NULL) == 0 and
-        now.tv_sec > ptr->ketama.next_distribution_rebuild)
-    {
-      run_distribution(ptr);
-    }
-  }
-}
-
-void memcached_autoeject(memcached_st *ptr)
-{
-  _regen_for_auto_eject(ptr);
-}
-
-uint32_t memcached_generate_hash_with_redistribution(memcached_st *ptr, const char *key, size_t key_length)
-{
-  uint32_t hash= _generate_hash_wrapper(ptr, key, key_length);
-
-  _regen_for_auto_eject(ptr);
-
-  return dispatch_host(ptr, hash);
-}
-
-uint32_t memcached_generate_hash(const memcached_st *shell, const char *key, size_t key_length)
-{
-  const Memcached* ptr= memcached2Memcached(shell);
-  if (ptr)
-  {
-    return dispatch_host(ptr, _generate_hash_wrapper(ptr, key, key_length));
-  }
-
-  return UINT32_MAX;
-}
-
-const hashkit_st *memcached_get_hashkit(const memcached_st *shell)
-{
-  const Memcached* ptr= memcached2Memcached(shell);
-  if (ptr)
-  {
-    return &ptr->hashkit;
-  }
-
-  return NULL;
-}
-
-memcached_return_t memcached_set_hashkit(memcached_st *shell, hashkit_st *hashk)
-{
-  Memcached* self= memcached2Memcached(shell);
-  if (self)
-  {
-    hashkit_free(&self->hashkit);
-    hashkit_clone(&self->hashkit, hashk);
-
-    return MEMCACHED_SUCCESS;
-  }
-
-  return MEMCACHED_INVALID_ARGUMENTS;
-}
-
-const char * libmemcached_string_hash(memcached_hash_t type)
-{
-  return libhashkit_string_hash((hashkit_hash_algorithm_t)type);
-}
diff --git a/libmemcached/hash.hpp b/libmemcached/hash.hpp
deleted file mode 100644 (file)
index bf450ee..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-uint32_t memcached_generate_hash_with_redistribution(memcached_st *ptr, const char *key, size_t key_length);
diff --git a/libmemcached/hosts.cc b/libmemcached/hosts.cc
deleted file mode 100644 (file)
index 98cb3f7..0000000
+++ /dev/null
@@ -1,618 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-#include "libmemcached/assert.hpp"
-
-#include <cmath>
-#include <sys/time.h>
-
-/* Protoypes (static) */
-static memcached_return_t update_continuum(Memcached *ptr);
-
-static int compare_servers(const void *p1, const void *p2)
-{
-  const memcached_instance_st * a= (const memcached_instance_st *)p1;
-  const memcached_instance_st * b= (const memcached_instance_st *)p2;
-
-  int return_value= strcmp(a->_hostname, b->_hostname);
-
-  if (return_value == 0)
-  {
-    return_value= int(a->port() - b->port());
-  }
-
-  return return_value;
-}
-
-static void sort_hosts(Memcached *ptr)
-{
-  if (memcached_server_count(ptr))
-  {
-    qsort(memcached_instance_list(ptr), memcached_server_count(ptr), sizeof(memcached_instance_st), compare_servers);
-  }
-}
-
-
-memcached_return_t run_distribution(Memcached *ptr)
-{
-  if (ptr->flags.use_sort_hosts)
-  {
-    sort_hosts(ptr);
-  }
-
-  switch (ptr->distribution)
-  {
-  case MEMCACHED_DISTRIBUTION_CONSISTENT:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED:
-    return update_continuum(ptr);
-
-  case MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET:
-  case MEMCACHED_DISTRIBUTION_MODULA:
-    break;
-
-  case MEMCACHED_DISTRIBUTION_RANDOM:
-    srandom((uint32_t) time(NULL));
-    break;
-
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX:
-  default:
-    assert_msg(0, "Invalid distribution type passed to run_distribution()");
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-static uint32_t ketama_server_hash(const char *key, size_t key_length, uint32_t alignment)
-{
-  unsigned char results[16];
-
-  libhashkit_md5_signature((unsigned char*)key, key_length, results);
-
-  return ((uint32_t) (results[3 + alignment * 4] & 0xFF) << 24)
-    | ((uint32_t) (results[2 + alignment * 4] & 0xFF) << 16)
-    | ((uint32_t) (results[1 + alignment * 4] & 0xFF) << 8)
-    | (results[0 + alignment * 4] & 0xFF);
-}
-
-static int continuum_item_cmp(const void *t1, const void *t2)
-{
-  memcached_continuum_item_st *ct1= (memcached_continuum_item_st *)t1;
-  memcached_continuum_item_st *ct2= (memcached_continuum_item_st *)t2;
-
-  /* Why 153? Hmmm... */
-  WATCHPOINT_ASSERT(ct1->value != 153);
-  if (ct1->value == ct2->value)
-  {
-    if (ct1->index == ct2->index)
-    {
-      return 0;
-    }
-    else if (ct1->index > ct2->index)
-    {
-      return 1;
-    }
-    else
-    {
-      return -1;
-    }
-  }
-  else if (ct1->value > ct2->value)
-  {
-    return 1;
-  }
-  else
-  {
-    return -1;
-  }
-}
-
-static memcached_return_t update_continuum(Memcached *ptr)
-{
-  uint32_t continuum_index= 0;
-  uint32_t pointer_counter= 0;
-  uint32_t pointer_per_server= MEMCACHED_POINTS_PER_SERVER;
-  uint32_t pointer_per_hash= 1;
-  uint32_t live_servers= 0;
-  struct timeval now;
-
-  if (gettimeofday(&now, NULL))
-  {
-    return memcached_set_errno(*ptr, errno, MEMCACHED_AT);
-  }
-
-  memcached_instance_st* list= memcached_instance_list(ptr);
-
-  /* count live servers (those without a retry delay set) */
-  bool is_auto_ejecting= _is_auto_eject_host(ptr);
-  if (is_auto_ejecting)
-  {
-    live_servers= 0;
-    ptr->ketama.next_distribution_rebuild= 0;
-    for (uint32_t host_index= 0; host_index < memcached_server_count(ptr); ++host_index)
-    {
-      if (list[host_index].next_retry <= now.tv_sec)
-      {
-        live_servers++;
-      }
-      else
-      {
-        if (ptr->ketama.next_distribution_rebuild == 0 or list[host_index].next_retry < ptr->ketama.next_distribution_rebuild)
-        {
-          ptr->ketama.next_distribution_rebuild= list[host_index].next_retry;
-        }
-      }
-    }
-  }
-  else
-  {
-    live_servers= memcached_server_count(ptr);
-  }
-
-  if (live_servers == 0)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  uint32_t points_per_server = (uint32_t) (memcached_is_weighted_ketama(ptr) ? MEMCACHED_POINTS_PER_SERVER_KETAMA : MEMCACHED_POINTS_PER_SERVER);
-  uint32_t continuum_limit = live_servers * points_per_server;
-  uint32_t continuum_extra = MEMCACHED_CONTINUUM_ADDITION * points_per_server;
-
-  if (continuum_limit > ptr->ketama.continuum_count)
-  {
-    memcached_continuum_item_st *new_ptr;
-
-    new_ptr= libmemcached_xrealloc(ptr, ptr->ketama.continuum, continuum_limit + continuum_extra, memcached_continuum_item_st);
-
-    if (new_ptr == 0)
-    {
-      return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-    }
-
-    ptr->ketama.continuum= new_ptr;
-    ptr->ketama.continuum_count= continuum_limit + continuum_extra;
-  }
-  assert_msg(ptr->ketama.continuum, "Programmer Error, empty ketama continuum");
-
-  uint64_t total_weight= 0;
-  if (memcached_is_weighted_ketama(ptr))
-  {
-    for (uint32_t host_index = 0; host_index < memcached_server_count(ptr); ++host_index)
-    {
-      if (is_auto_ejecting == false or list[host_index].next_retry <= now.tv_sec)
-      {
-        total_weight += list[host_index].weight;
-      }
-    }
-  }
-
-  for (uint32_t host_index= 0; host_index < memcached_server_count(ptr); ++host_index)
-  {
-    if (is_auto_ejecting and list[host_index].next_retry > now.tv_sec)
-    {
-      continue;
-    }
-
-    if (memcached_is_weighted_ketama(ptr))
-    {
-        float pct= (float)list[host_index].weight / (float)total_weight;
-        pointer_per_server= (uint32_t) ((::floor((float) (pct * MEMCACHED_POINTS_PER_SERVER_KETAMA / 4 * (float)live_servers + 0.0000000001))) * 4);
-        pointer_per_hash= 4;
-        if (0 && DEBUG)
-        {
-          printf("ketama_weighted:%s|%d|%llu|%u\n",
-                 list[host_index]._hostname,
-                 list[host_index].port(),
-                 (unsigned long long)list[host_index].weight,
-                 pointer_per_server);
-        }
-    }
-
-
-    if (ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY)
-    {
-      for (uint32_t pointer_index= 0;
-           pointer_index < pointer_per_server / pointer_per_hash;
-           pointer_index++)
-      {
-        char sort_host[1 +MEMCACHED_NI_MAXHOST +1 +MEMCACHED_NI_MAXSERV +1 + MEMCACHED_NI_MAXSERV ]= "";
-        int sort_host_length;
-
-        // Spymemcached ketema key format is: hostname/ip:port-index
-        // If hostname is not available then: /ip:port-index
-        sort_host_length= snprintf(sort_host, sizeof(sort_host),
-                                   "/%s:%u-%u",
-                                   list[host_index]._hostname,
-                                   (uint32_t)list[host_index].port(),
-                                   pointer_index);
-
-        if (size_t(sort_host_length) >= sizeof(sort_host) or sort_host_length < 0)
-        {
-          return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                                     memcached_literal_param("snprintf(sizeof(sort_host))"));
-        }
-
-        if (0 && DEBUG)
-        {
-          fprintf(stdout, "update_continuum: key is %s\n", sort_host);
-        }
-
-        if (memcached_is_weighted_ketama(ptr))
-        {
-          for (uint32_t x= 0; x < pointer_per_hash; x++)
-          {
-            uint32_t value= ketama_server_hash(sort_host, (size_t)sort_host_length, x);
-            ptr->ketama.continuum[continuum_index].index= host_index;
-            ptr->ketama.continuum[continuum_index++].value= value;
-          }
-        }
-        else
-        {
-          uint32_t value= hashkit_digest(&ptr->hashkit, sort_host, (size_t)sort_host_length);
-          ptr->ketama.continuum[continuum_index].index= host_index;
-          ptr->ketama.continuum[continuum_index++].value= value;
-        }
-      }
-    }
-    else
-    {
-      for (uint32_t pointer_index= 1;
-           pointer_index <= pointer_per_server / pointer_per_hash;
-           pointer_index++)
-      {
-        char sort_host[MEMCACHED_NI_MAXHOST +1 +MEMCACHED_NI_MAXSERV +1 +MEMCACHED_NI_MAXSERV]= "";
-        int sort_host_length;
-
-        if (list[host_index].port() == MEMCACHED_DEFAULT_PORT)
-        {
-          sort_host_length= snprintf(sort_host, sizeof(sort_host),
-                                     "%s-%u",
-                                     list[host_index]._hostname,
-                                     pointer_index - 1);
-        }
-        else
-        {
-          sort_host_length= snprintf(sort_host, sizeof(sort_host),
-                                     "%s:%u-%u",
-                                     list[host_index]._hostname,
-                                     (uint32_t)list[host_index].port(),
-                                     pointer_index - 1);
-        }
-
-        if (size_t(sort_host_length) >= sizeof(sort_host) or sort_host_length < 0)
-        {
-          return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                                     memcached_literal_param("snprintf(sizeof(sort_host)))"));
-        }
-
-        if (memcached_is_weighted_ketama(ptr))
-        {
-          for (uint32_t x = 0; x < pointer_per_hash; x++)
-          {
-            uint32_t value= ketama_server_hash(sort_host, (size_t)sort_host_length, x);
-            ptr->ketama.continuum[continuum_index].index= host_index;
-            ptr->ketama.continuum[continuum_index++].value= value;
-          }
-        }
-        else
-        {
-          uint32_t value= hashkit_digest(&ptr->hashkit, sort_host, (size_t)sort_host_length);
-          ptr->ketama.continuum[continuum_index].index= host_index;
-          ptr->ketama.continuum[continuum_index++].value= value;
-        }
-      }
-    }
-
-    pointer_counter+= pointer_per_server;
-  }
-
-  assert_msg(ptr, "Programmer Error, no valid ptr");
-  assert_msg(ptr->ketama.continuum, "Programmer Error, empty ketama continuum");
-  assert_msg(memcached_server_count(ptr) * MEMCACHED_POINTS_PER_SERVER <= MEMCACHED_CONTINUUM_SIZE, "invalid size information being given to qsort()");
-  ptr->ketama.continuum_points_counter= pointer_counter;
-  qsort(ptr->ketama.continuum, ptr->ketama.continuum_points_counter, sizeof(memcached_continuum_item_st), continuum_item_cmp);
-
-  if (DEBUG)
-  {
-    for (uint32_t pointer_index= 0; memcached_server_count(ptr) && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++)
-    {
-      WATCHPOINT_ASSERT(ptr->ketama.continuum[pointer_index].value <= ptr->ketama.continuum[pointer_index + 1].value);
-    }
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-static memcached_return_t server_add(Memcached *memc, 
-                                     const memcached_string_t& hostname,
-                                     in_port_t port,
-                                     uint32_t weight,
-                                     memcached_connection_t type)
-{
-  assert_msg(memc, "Programmer mistake, somehow server_add() was passed a NULL memcached_st");
-
-  if (memc->number_of_hosts)
-  {
-    assert(memcached_instance_list(memc));
-  }
-
-  if (memcached_instance_list(memc))
-  {
-    assert(memc->number_of_hosts);
-  }
-
-  uint32_t host_list_size= memc->number_of_hosts +1;
-  memcached_instance_st* new_host_list= libmemcached_xrealloc(memc, memcached_instance_list(memc), host_list_size, memcached_instance_st);
-
-  if (new_host_list == NULL)
-  {
-    return memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-  }
-
-  memcached_instance_set(memc, new_host_list, host_list_size);
-  assert(memc->number_of_hosts == host_list_size);
-
-  /* TODO: Check return type */
-  memcached_instance_st* instance= memcached_instance_fetch(memc, memcached_server_count(memc) -1);
-
-  if (__instance_create_with(memc, instance, hostname, port, weight, type) == NULL)
-  {
-    return memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-  }
-
-  if (weight > 1)
-  {
-    if (memcached_is_consistent_distribution(memc))
-    {
-      memcached_set_weighted_ketama(memc, true);
-    }
-  }
-
-  return run_distribution(memc);
-}
-
-
-memcached_return_t memcached_server_push(memcached_st *shell, const memcached_server_list_st list)
-{
-  if (list == NULL)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  Memcached* ptr= memcached2Memcached(shell);
-  if (ptr)
-  {
-    uint32_t original_host_size= memcached_server_count(ptr);
-    uint32_t count= memcached_server_list_count(list);
-    uint32_t host_list_size= count +original_host_size;
-
-    memcached_instance_st* new_host_list= libmemcached_xrealloc(ptr, memcached_instance_list(ptr), host_list_size, memcached_instance_st);
-
-    if (new_host_list == NULL)
-    {
-      return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-    }
-
-    memcached_instance_set(ptr, new_host_list, host_list_size);
-
-    ptr->state.is_parsing= true;
-    for (uint32_t x= 0; x < count; ++x, ++original_host_size)
-    {
-      WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
-
-      // We have extended the array, and now we will find it, and use it.
-      memcached_instance_st* instance= memcached_instance_fetch(ptr, original_host_size);
-      WATCHPOINT_ASSERT(instance);
-
-      memcached_string_t hostname= { memcached_string_make_from_cstr(list[x].hostname) };
-      if (__instance_create_with(ptr, instance, 
-                                 hostname,
-                                 list[x].port, list[x].weight, list[x].type) == NULL)
-      {
-        ptr->state.is_parsing= false;
-        return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-      }
-
-      if (list[x].weight > 1)
-      {
-        memcached_set_weighted_ketama(ptr, true);
-      }
-    }
-    ptr->state.is_parsing= false;
-
-    return run_distribution(ptr);
-  }
-
-  return MEMCACHED_INVALID_ARGUMENTS;
-}
-
-memcached_return_t memcached_instance_push(memcached_st *ptr, const struct memcached_instance_st* list, uint32_t number_of_hosts)
-{
-  if (list == NULL)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  uint32_t original_host_size= memcached_server_count(ptr);
-  uint32_t host_list_size= number_of_hosts +original_host_size;
-  memcached_instance_st* new_host_list= libmemcached_xrealloc(ptr, memcached_instance_list(ptr), host_list_size, memcached_instance_st);
-
-  if (new_host_list == NULL)
-  {
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-  }
-
-  memcached_instance_set(ptr, new_host_list, host_list_size);
-
-  // We don't bother with lookups for this operation
-  ptr->state.is_parsing= true;
-
-  // We use original_host_size since size will now point to the first new
-  // instance allocated.
-  for (uint32_t x= 0; x < number_of_hosts; ++x, ++original_host_size)
-  {
-    WATCHPOINT_ASSERT(list[x]._hostname[0] != 0);
-
-    // We have extended the array, and now we will find it, and use it.
-    memcached_instance_st* instance= memcached_instance_fetch(ptr, original_host_size);
-    WATCHPOINT_ASSERT(instance);
-
-    memcached_string_t hostname= { memcached_string_make_from_cstr(list[x]._hostname) };
-    if (__instance_create_with(ptr, instance, 
-                               hostname,
-                               list[x].port(), list[x].weight, list[x].type) == NULL)
-    {
-      ptr->state.is_parsing= false;
-      return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-    }
-
-    if (list[x].weight > 1)
-    {
-      memcached_set_weighted_ketama(ptr, true);
-    }
-  }
-  ptr->state.is_parsing= false;
-
-  return run_distribution(ptr);
-}
-
-memcached_return_t memcached_server_add_unix_socket(memcached_st *ptr,
-                                                    const char *filename)
-{
-  return memcached_server_add_unix_socket_with_weight(ptr, filename, 0);
-}
-
-memcached_return_t memcached_server_add_unix_socket_with_weight(memcached_st *shell,
-                                                                const char *filename,
-                                                                uint32_t weight)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  if (ptr)
-  {
-    memcached_string_t _filename= { memcached_string_make_from_cstr(filename) };
-    if (memcached_is_valid_filename(_filename) == false)
-    {
-      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid filename for socket provided"));
-    }
-
-    return server_add(ptr, _filename, 0, weight, MEMCACHED_CONNECTION_UNIX_SOCKET);
-  }
-
-  return MEMCACHED_FAILURE;
-}
-
-memcached_return_t memcached_server_add_udp(memcached_st *ptr,
-                                            const char *hostname,
-                                            in_port_t port)
-{
-  return memcached_server_add_udp_with_weight(ptr, hostname, port, 0);
-}
-
-memcached_return_t memcached_server_add_udp_with_weight(memcached_st *shell,
-                                                        const char *,
-                                                        in_port_t,
-                                                        uint32_t)
-{
-  Memcached* self= memcached2Memcached(shell);
-  if (self)
-  {
-    return memcached_set_error(*self, MEMCACHED_DEPRECATED, MEMCACHED_AT);
-  }
-
-  return MEMCACHED_INVALID_ARGUMENTS;
-}
-
-memcached_return_t memcached_server_add(memcached_st *shell,
-                                        const char *hostname,
-                                        in_port_t port)
-{
-  return memcached_server_add_with_weight(shell, hostname, port, 0);
-}
-
-memcached_return_t memcached_server_add_with_weight(memcached_st *shell,
-                                                    const char *hostname,
-                                                    in_port_t port,
-                                                    uint32_t weight)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  if (ptr == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  if (port == 0)
-  {
-    port= MEMCACHED_DEFAULT_PORT;
-  }
-
-  size_t hostname_length= hostname ? strlen(hostname) : 0;
-  if (hostname_length == 0)
-  {
-    hostname= "localhost";
-    hostname_length= memcached_literal_param_size("localhost");
-  }
-
-  memcached_string_t _hostname= { hostname, hostname_length };
-
-  if (memcached_is_valid_servername(_hostname) == false)
-  {
-    return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid hostname provided"));
-  }
-
-  return server_add(ptr, _hostname, port, weight, _hostname.c_str[0] == '/' ? MEMCACHED_CONNECTION_UNIX_SOCKET  : MEMCACHED_CONNECTION_TCP);
-}
-
-memcached_return_t memcached_server_add_parsed(memcached_st *ptr,
-                                               const char *hostname,
-                                               size_t hostname_length,
-                                               in_port_t port,
-                                               uint32_t weight)
-{
-  char buffer[MEMCACHED_NI_MAXHOST]= { 0 };
-
-  memcpy(buffer, hostname, hostname_length);
-  buffer[hostname_length]= 0;
-
-  memcached_string_t _hostname= { buffer, hostname_length };
-
-  return server_add(ptr, _hostname,
-                    port,
-                    weight,
-                    MEMCACHED_CONNECTION_TCP);
-}
diff --git a/libmemcached/initialize_query.cc b/libmemcached/initialize_query.cc
deleted file mode 100644 (file)
index cef8e57..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-memcached_return_t initialize_query(Memcached *self, bool increment_query_id)
-{
-  if (self == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  if (increment_query_id)
-  {
-    self->query_id++;
-  }
-
-  if (self->state.is_time_for_rebuild)
-  {
-    memcached_reset(self);
-  }
-
-  if (memcached_server_count(self) == 0)
-  {
-    return memcached_set_error(*self, MEMCACHED_NO_SERVERS, MEMCACHED_AT);
-  }
-
-  memcached_error_free(*self);
-  memcached_result_reset(&self->result);
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t initialize_const_query(const Memcached *self)
-{
-  if (self == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  if (memcached_server_count(self) == 0)
-  {
-    return MEMCACHED_NO_SERVERS;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
diff --git a/libmemcached/initialize_query.h b/libmemcached/initialize_query.h
deleted file mode 100644 (file)
index 105283c..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-memcached_return_t initialize_query(Memcached *self, bool increment_query_id);
-
-memcached_return_t initialize_const_query(const Memcached *self);
diff --git a/libmemcached/instance.cc b/libmemcached/instance.cc
deleted file mode 100644 (file)
index df08c60..0000000
+++ /dev/null
@@ -1,361 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-static inline void _server_init(memcached_instance_st* self, Memcached *root,
-                                const memcached_string_t& hostname,
-                                in_port_t port,
-                                uint32_t weight, memcached_connection_t type)
-{
-  self->options.is_shutting_down= false;
-  self->options.is_dead= false;
-  self->options.ready= false;
-  self->_events= 0;
-  self->_revents= 0;
-  self->cursor_active_= 0;
-  self->port_= port;
-  self->fd= INVALID_SOCKET;
-  self->io_bytes_sent= 0;
-  self->request_id= 0;
-  self->server_failure_counter= 0;
-  self->server_failure_counter_query_id= 0;
-  self->server_timeout_counter= 0;
-  self->server_timeout_counter_query_id= 0;
-  self->weight= weight ? weight : 1; // 1 is the default weight value
-  self->io_wait_count.read= 0;
-  self->io_wait_count.write= 0;
-  self->io_wait_count.timeouts= 0;
-  self->io_wait_count._bytes_read= 0;
-  self->major_version= UINT8_MAX;
-  self->micro_version= UINT8_MAX;
-  self->minor_version= UINT8_MAX;
-  self->type= type;
-  self->error_messages= NULL;
-  self->read_ptr= self->read_buffer;
-  self->read_buffer_length= 0;
-  self->write_buffer_offset= 0;
-  self->address_info= NULL;
-  self->address_info_next= NULL;
-
-  self->state= MEMCACHED_SERVER_STATE_NEW;
-  self->next_retry= 0;
-
-  self->root= root;
-  if (root)
-  {
-    self->version= ++root->server_info.version;
-  }
-  else
-  {
-    self->version= UINT_MAX;
-  }
-  self->limit_maxbytes= 0;
-  self->hostname(hostname);
-}
-
-static memcached_instance_st* _server_create(memcached_instance_st* self, const memcached_st *memc)
-{
-  if (self == NULL)
-  {
-   self= libmemcached_xmalloc(memc, memcached_instance_st);
-
-    if (self == NULL)
-    {
-      return NULL; /*  MEMCACHED_MEMORY_ALLOCATION_FAILURE */
-    }
-
-    self->options.is_allocated= true;
-  }
-  else
-  {
-    self->options.is_allocated= false;
-  }
-
-  self->options.is_initialized= true;
-
-  return self;
-}
-
-void memcached_instance_st::events(short arg)
-{
-  if ((_events | arg) == _events)
-  {
-    return;
-  }
-
-  _events|= arg;
-}
-
-void memcached_instance_st::revents(short arg)
-{
-  if (arg)
-  {
-    options.ready= true;
-  }
-
-  _revents= arg;
-  _events&= short(~arg);
-}
-
-memcached_instance_st* __instance_create_with(memcached_st *memc,
-                                                    memcached_instance_st* self,
-                                                    const memcached_string_t& hostname,
-                                                    const in_port_t port,
-                                                    uint32_t weight, 
-                                                    const memcached_connection_t type)
-{
-  if (memcached_is_valid_servername(hostname) == false)
-  {
-    memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid hostname provided"));
-    return NULL;
-  }
-
-  self= _server_create(self, memc);
-
-  if (self == NULL)
-  {
-    return NULL;
-  }
-
-  _server_init(self, const_cast<memcached_st *>(memc), hostname, port, weight, type);
-
-  if (memc and memcached_is_udp(memc))
-  { 
-    self->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
-    memcached_io_init_udp_header(self, 0);
-  }
-
-  return self;
-}
-
-void __instance_free(memcached_instance_st* self)
-{
-  memcached_quit_server(self, false);
-
-  self->clear_addrinfo();
-  assert(self->address_info_next == NULL);
-
-  memcached_error_free(*self);
-
-  if (memcached_is_allocated(self))
-  {
-    libmemcached_free(self->root, self);
-  }
-  else
-  {
-    self->options.is_initialized= false;
-  }
-}
-
-void memcached_instance_free(memcached_instance_st* self)
-{
-  if (self)
-  {
-    __instance_free(self);
-  }
-}
-
-memcached_return_t memcached_server_cursor(const memcached_st* shell,
-                                           const memcached_server_fn *callback,
-                                           void *context,
-                                           uint32_t number_of_callbacks)
-{
-  const Memcached* memc= memcached2Memcached(shell);
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_const_query(memc)))
-  {
-    return rc;
-  }
-
-  size_t errors= 0;
-  for (uint32_t x= 0; x < memcached_instance_list_count(memc); x++)
-  {
-    memcached_instance_st* instance= memcached_instance_by_position(memc, x);
-
-    for (uint32_t y= 0; y < number_of_callbacks; y++)
-    {
-      memcached_return_t ret= (*callback[y])(memc, instance, context);
-
-      if (memcached_failed(ret))
-      {
-        errors++;
-        continue;
-      }
-    }
-  }
-
-  return errors ? MEMCACHED_SOME_ERRORS : MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_server_execute(memcached_st *memc,
-                                            memcached_server_execute_fn callback,
-                                            void *context)
-{
-  if (callback == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  bool some_errors= false;;
-  for (uint32_t x= 0; x < memcached_instance_list_count(memc); x++)
-  {
-    memcached_instance_st* instance= memcached_instance_fetch(memc, x);
-
-    memcached_return_t rc= (*callback)(memc, instance, context);
-    if (rc == MEMCACHED_INVALID_ARGUMENTS)
-    {
-      return rc;
-    }
-    else if (memcached_fatal(rc))
-    {
-      some_errors= true;
-    }
-  }
-
-  (void)some_errors;
-  return MEMCACHED_SUCCESS;
-}
-
-const memcached_instance_st * memcached_server_by_key(memcached_st *shell,
-                                                     const char *key,
-                                                     size_t key_length,
-                                                     memcached_return_t *error)
-{
-  Memcached* memc= memcached2Memcached(shell);
-  memcached_return_t unused;
-  if (error == NULL)
-  {
-    error= &unused;
-  }
-
-
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_const_query(memc)))
-  {
-    *error= rc;
-    return NULL;
-  }
-
-  if (memcached_failed((memcached_key_test(*memc, (const char **)&key, &key_length, 1))))
-  {
-    *error= memcached_last_error(memc);
-    return NULL;
-  }
-
-  uint32_t server_key= memcached_generate_hash(memc, key, key_length);
-  return memcached_instance_by_position(memc, server_key);
-}
-
-/*
-  If we do not have a valid object to clone from, we toss an error.
-*/
-static memcached_instance_st* memcached_instance_clone(memcached_instance_st* source)
-{
-  /* We just do a normal create if source is missing */
-  if (source == NULL)
-  {
-    return NULL;
-  }
-
-  memcached_string_t hostname_= { memcached_string_make_from_cstr(source->hostname()) };
-  return __instance_create_with(source->root,
-                                NULL,
-                                hostname_,
-                                source->port(), source->weight,
-                                source->type);
-}
-
-void set_last_disconnected_host(memcached_instance_st* self)
-{
-  assert(self->root);
-  if (self->root)
-  {
-    if (memcached_server_get_last_disconnect(self->root) and
-        memcached_server_get_last_disconnect(self->root)->version == self->version)
-    {
-      return;
-    }
-
-    // const_cast
-    memcached_st *root= (memcached_st *)self->root;
-
-    memcached_instance_free((memcached_instance_st*)(root->last_disconnected_server));
-
-    // We set is_parsing so that no lookup happens
-    root->state.is_parsing= true;
-    root->last_disconnected_server= memcached_instance_clone(self);
-    root->state.is_parsing= false;
-
-    ((memcached_instance_st*)memcached_server_get_last_disconnect(root))->version= self->version;
-  }
-}
-
-const memcached_instance_st * memcached_server_get_last_disconnect(const memcached_st *shell)
-{
-  const Memcached* self= memcached2Memcached(shell);
-  if (self)
-  {
-    return (const memcached_instance_st *)self->last_disconnected_server;
-  }
-
-  return 0;
-}
-
-void memcached_instance_next_retry(const memcached_instance_st * self, const time_t absolute_time)
-{
-  WATCHPOINT_ASSERT(self);
-  if (self)
-  {
-    ((memcached_instance_st*)self)->next_retry= absolute_time;
-  }
-}
-
-bool memcached_instance_st::valid() const
-{
-  if (fd == INVALID_SOCKET)
-  {
-    return false;
-  }
-
-  return true;
-}
-
-bool memcached_instance_st::is_shutting_down() const
-{
-  return options.is_shutting_down;
-}
diff --git a/libmemcached/instance.hpp b/libmemcached/instance.hpp
deleted file mode 100644 (file)
index 63bf083..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/ 
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#ifndef WIN32
-# ifdef HAVE_NETDB_H
-#  include <netdb.h>
-# endif
-#endif
-
-#ifdef NI_MAXHOST
-# define MEMCACHED_NI_MAXHOST NI_MAXHOST
-#else
-# define MEMCACHED_NI_MAXHOST 1025
-#endif
-
-#ifdef NI_MAXSERV
-# define MEMCACHED_NI_MAXSERV NI_MAXSERV
-#else
-# define MEMCACHED_NI_MAXSERV 32
-#endif
-
-#include "libmemcached/string.hpp"
-
-// @todo Complete class transformation
-struct memcached_instance_st {
-  in_port_t port() const
-  {
-    return port_;
-  }
-
-  void port(in_port_t arg)
-  {
-    port_= arg;
-  }
-
-  void mark_server_as_clean()
-  {
-    server_failure_counter= 0;
-    server_timeout_counter= 0;
-    next_retry= 0;
-  }
-
-  void disable()
-  {
-  }
-
-  void enable()
-  {
-  }
-
-  bool valid() const;
-
-  bool is_shutting_down() const;
-
-  void start_close_socket();
-  void close_socket();
-  void reset_socket();
-
-  uint32_t response_count() const
-  {
-    return cursor_active_;
-  }
-
-  struct {
-    bool is_allocated;
-    bool is_initialized;
-    bool is_shutting_down;
-    bool is_dead;
-    bool ready;
-  } options;
-
-  short _events;
-  short _revents;
-
-  short events(void)
-  {
-    return _events;
-  }
-
-  short revents(void)
-  {
-    return _revents;
-  }
-
-  const char* hostname()
-  {
-    return _hostname;
-  }
-
-  void hostname(const memcached_string_t& hostname_)
-  {
-    if (hostname_.size)
-    {
-      memcpy(_hostname, hostname_.c_str, hostname_.size);
-      _hostname[hostname_.size]= 0;
-    }
-    else
-    {
-      memcpy(_hostname, memcached_literal_param("localhost"));
-      _hostname[memcached_literal_param_size("localhost")]= 0;
-    }
-  }
-
-  void events(short);
-  void revents(short);
-
-  uint32_t cursor_active_;
-  in_port_t port_;
-  memcached_socket_t fd;
-  uint32_t io_bytes_sent; /* # bytes sent since last read */
-  uint32_t request_id;
-  uint32_t server_failure_counter;
-  uint64_t server_failure_counter_query_id;
-  uint32_t server_timeout_counter;
-  uint64_t server_timeout_counter_query_id;
-  uint32_t weight;
-  uint32_t version;
-  enum memcached_server_state_t state;
-  struct {
-    uint32_t read;
-    uint32_t write;
-    uint32_t timeouts;
-    size_t _bytes_read;
-  } io_wait_count;
-  uint8_t major_version; // Default definition of UINT8_MAX means that it has not been set.
-  uint8_t micro_version; // ditto, and note that this is the third, not second version bit
-  uint8_t minor_version; // ditto
-  memcached_connection_t type;
-  char *read_ptr;
-  size_t read_buffer_length;
-  size_t write_buffer_offset;
-  struct addrinfo *address_info;
-  struct addrinfo *address_info_next;
-  time_t next_retry;
-  struct memcached_st *root;
-  uint64_t limit_maxbytes;
-  struct memcached_error_t *error_messages;
-  char read_buffer[MEMCACHED_MAX_BUFFER];
-  char write_buffer[MEMCACHED_MAX_BUFFER];
-  char _hostname[MEMCACHED_NI_MAXHOST];
-
-  void clear_addrinfo()
-  {
-    if (address_info)
-    {
-      freeaddrinfo(address_info);
-      address_info= NULL;
-      address_info_next= NULL;
-    }
-  }
-};
-
-memcached_instance_st* __instance_create_with(memcached_st *memc,
-                                              memcached_instance_st* self,
-                                              const memcached_string_t& _hostname,
-                                              const in_port_t port,
-                                              uint32_t weight, 
-                                              const memcached_connection_t type);
-
-memcached_return_t memcached_instance_push(memcached_st *ptr, const memcached_instance_st*, uint32_t);
-
-void __instance_free(memcached_instance_st *);
diff --git a/libmemcached/internal.h b/libmemcached/internal.h
deleted file mode 100644 (file)
index 67ae67d..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached/io.cc b/libmemcached/io.cc
deleted file mode 100644 (file)
index 13c8cf3..0000000
+++ /dev/null
@@ -1,934 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libmemcached/common.h>
-
-#ifdef HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-
-void initialize_binary_request(memcached_instance_st* server, protocol_binary_request_header& header)
-{
-  server->request_id++;
-  header.request.magic= PROTOCOL_BINARY_REQ;
-  header.request.opaque= htons(server->request_id);
-}
-
-enum memc_read_or_write {
-  MEM_READ,
-  MEM_WRITE
-};
-
-/**
- * Try to fill the input buffer for a server with as much
- * data as possible.
- *
- * @param instance the server to pack
- */
-static bool repack_input_buffer(memcached_instance_st* instance)
-{
-  if (instance->read_ptr != instance->read_buffer)
-  {
-    /* Move all of the data to the beginning of the buffer so
-     ** that we can fit more data into the buffer...
-   */
-    memmove(instance->read_buffer, instance->read_ptr, instance->read_buffer_length);
-    instance->read_ptr= instance->read_buffer;
-  }
-
-  /* There is room in the buffer, try to fill it! */
-  if (instance->read_buffer_length != MEMCACHED_MAX_BUFFER)
-  {
-    do {
-      /* Just try a single read to grab what's available */
-      ssize_t nr;
-      if ((nr= ::recv(instance->fd,
-                      instance->read_ptr + instance->read_buffer_length,
-                      MEMCACHED_MAX_BUFFER - instance->read_buffer_length,
-                      MSG_NOSIGNAL)) <= 0)
-      {
-        if (nr == 0)
-        {
-          memcached_set_error(*instance, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT);
-        }
-        else
-        {
-          switch (get_socket_errno())
-          {
-          case EINTR:
-            continue;
-
-#if EWOULDBLOCK != EAGAIN
-          case EWOULDBLOCK:
-#endif
-          case EAGAIN:
-#ifdef __linux
-          case ERESTART:
-#endif
-            break; // No IO is fine, we can just move on
-
-          default:
-            memcached_set_errno(*instance, get_socket_errno(), MEMCACHED_AT);
-          }
-        }
-
-        break;
-      }
-      else // We read data, append to our read buffer
-      {
-        instance->read_buffer_length+= size_t(nr);
-
-        return true;
-      }
-    } while (false);
-  }
-
-  return false;
-}
-
-/**
- * If the we have callbacks connected to this server structure
- * we may start process the input queue and fire the callbacks
- * for the incomming messages. This function is _only_ called
- * when the input buffer is full, so that we _know_ that we have
- * at least _one_ message to process.
- *
- * @param instance the server to star processing iput messages for
- * @return true if we processed anything, false otherwise
- */
-static bool process_input_buffer(memcached_instance_st* instance)
-{
-  /*
-   ** We might be able to process some of the response messages if we
-   ** have a callback set up
- */
-  if (instance->root->callbacks != NULL)
-  {
-    /*
-     * We might have responses... try to read them out and fire
-     * callbacks
-   */
-    memcached_callback_st cb= *instance->root->callbacks;
-
-    memcached_set_processing_input((Memcached *)instance->root, true);
-
-    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-    Memcached *root= (Memcached *)instance->root;
-    memcached_return_t error= memcached_response(instance, buffer, sizeof(buffer), &root->result);
-
-    memcached_set_processing_input(root, false);
-
-    if (error == MEMCACHED_SUCCESS)
-    {
-      for (unsigned int x= 0; x < cb.number_of_callback; x++)
-      {
-        error= (*cb.callback[x])(instance->root, &root->result, cb.context);
-        if (error != MEMCACHED_SUCCESS)
-        {
-          break;
-        }
-      }
-
-      /* @todo what should I do with the error message??? */
-    }
-    /* @todo what should I do with other error messages?? */
-    return true;
-  }
-
-  return false;
-}
-
-static memcached_return_t io_wait(memcached_instance_st* instance,
-                                  const short events)
-{
-  /*
-   ** We are going to block on write, but at least on Solaris we might block
-   ** on write if we haven't read anything from our input buffer..
-   ** Try to purge the input buffer if we don't do any flow control in the
-   ** application layer (just sending a lot of data etc)
-   ** The test is moved down in the purge function to avoid duplication of
-   ** the test.
- */
-  if (events & POLLOUT)
-  {
-    if (memcached_purge(instance) == false)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-
-  struct pollfd fds;
-  fds.fd= instance->fd;
-  fds.events= events;
-  fds.revents= 0;
-
-  if (fds.events & POLLOUT) /* write */
-  {
-    instance->io_wait_count.write++;
-  }
-  else
-  {
-    instance->io_wait_count.read++;
-  }
-
-  if (instance->root->poll_timeout == 0) // Mimic 0 causes timeout behavior (not all platforms do this)
-  {
-    return memcached_set_error(*instance, MEMCACHED_TIMEOUT, MEMCACHED_AT, memcached_literal_param("poll_timeout() was set to zero"));
-  }
-
-  size_t loop_max= 5;
-  while (--loop_max) // While loop is for ERESTART or EINTR
-  {
-    int active_fd= poll(&fds, 1, instance->root->poll_timeout);
-
-    if (active_fd >= 1)
-    {
-      assert_msg(active_fd == 1 , "poll() returned an unexpected number of active file descriptors");
-      if (fds.revents & POLLIN or fds.revents & POLLOUT)
-      {
-        return MEMCACHED_SUCCESS;
-      }
-
-      if (fds.revents & POLLHUP)
-      {
-        return memcached_set_error(*instance, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT, 
-                                   memcached_literal_param("poll() detected hang up"));
-      }
-
-      if (fds.revents & POLLERR)
-      {
-        int local_errno= EINVAL;
-        int err;
-        socklen_t len= sizeof (err);
-        if (getsockopt(instance->fd, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == 0)
-        {
-          if (err == 0) // treat this as EINTR
-          {
-            continue;
-          }
-          local_errno= err;
-        }
-        memcached_quit_server(instance, true);
-        return memcached_set_errno(*instance, local_errno, MEMCACHED_AT,
-                                   memcached_literal_param("poll() returned POLLHUP"));
-      }
-      
-      return memcached_set_error(*instance, MEMCACHED_FAILURE, MEMCACHED_AT, memcached_literal_param("poll() returned a value that was not dealt with"));
-    }
-
-    if (active_fd == 0)
-    {
-      return memcached_set_error(*instance, MEMCACHED_TIMEOUT, MEMCACHED_AT, memcached_literal_param("No active_fd were found"));
-    }
-
-    // Only an error should result in this code being called.
-    int local_errno= get_socket_errno(); // We cache in case memcached_quit_server() modifies errno
-    assert_msg(active_fd == -1 , "poll() returned an unexpected value");
-    switch (local_errno)
-    {
-#ifdef __linux
-    case ERESTART:
-#endif
-    case EINTR:
-      continue;
-
-    case EFAULT:
-    case ENOMEM:
-      memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-      break;
-
-    case EINVAL:
-      memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, memcached_literal_param("RLIMIT_NOFILE exceeded, or if OSX the timeout value was invalid"));
-      break;
-
-    default:
-      memcached_set_errno(*instance, local_errno, MEMCACHED_AT, memcached_literal_param("poll"));
-    }
-
-    break;
-  }
-
-  memcached_quit_server(instance, true);
-
-  if (memcached_has_error(instance))
-  {
-    return memcached_instance_error_return(instance);
-  }
-
-  return memcached_set_error(*instance, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT, 
-                             memcached_literal_param("number of attempts to call io_wait() failed"));
-}
-
-static bool io_flush(memcached_instance_st* instance,
-                     const bool with_flush,
-                     memcached_return_t& error)
-{
-  /*
-   ** We might want to purge the input buffer if we haven't consumed
-   ** any output yet... The test for the limits is the purge is inline
-   ** in the purge function to avoid duplicating the logic..
- */
-  {
-    WATCHPOINT_ASSERT(instance->fd != INVALID_SOCKET);
-
-    if (memcached_purge(instance) == false)
-    {
-      return false;
-    }
-  }
-  char *local_write_ptr= instance->write_buffer;
-  size_t write_length= instance->write_buffer_offset;
-
-  error= MEMCACHED_SUCCESS;
-
-  WATCHPOINT_ASSERT(instance->fd != INVALID_SOCKET);
-
-  /* Looking for memory overflows */
-#if defined(DEBUG)
-  if (write_length == MEMCACHED_MAX_BUFFER)
-    WATCHPOINT_ASSERT(instance->write_buffer == local_write_ptr);
-  WATCHPOINT_ASSERT((instance->write_buffer + MEMCACHED_MAX_BUFFER) >= (local_write_ptr + write_length));
-#endif
-
-  while (write_length)
-  {
-    WATCHPOINT_ASSERT(instance->fd != INVALID_SOCKET);
-    WATCHPOINT_ASSERT(write_length > 0);
-
-    int flags;
-    if (with_flush)
-    {
-      flags= MSG_NOSIGNAL;
-    }
-    else
-    {
-      flags= MSG_NOSIGNAL|MSG_MORE;
-    }
-
-    ssize_t sent_length= ::send(instance->fd, local_write_ptr, write_length, flags);
-    int local_errno= get_socket_errno(); // We cache in case memcached_quit_server() modifies errno
-
-    if (sent_length == SOCKET_ERROR)
-    {
-#if 0 // @todo I should look at why we hit this bit of code hard frequently
-      WATCHPOINT_ERRNO(get_socket_errno());
-      WATCHPOINT_NUMBER(get_socket_errno());
-#endif
-      switch (get_socket_errno())
-      {
-      case ENOBUFS:
-        continue;
-
-#if EWOULDBLOCK != EAGAIN
-      case EWOULDBLOCK:
-#endif
-      case EAGAIN:
-        {
-          /*
-           * We may be blocked on write because the input buffer
-           * is full. Let's check if we have room in our input
-           * buffer for more data and retry the write before
-           * waiting..
-         */
-          if (repack_input_buffer(instance) or process_input_buffer(instance))
-          {
-            continue;
-          }
-
-          memcached_return_t rc= io_wait(instance, POLLOUT);
-          if (memcached_success(rc))
-          {
-            continue;
-          }
-          else if (rc == MEMCACHED_TIMEOUT)
-          {
-            return false;
-          }
-
-          memcached_quit_server(instance, true);
-          error= memcached_set_errno(*instance, local_errno, MEMCACHED_AT);
-          return false;
-        }
-      case ENOTCONN:
-      case EPIPE:
-      default:
-        memcached_quit_server(instance, true);
-        error= memcached_set_errno(*instance, local_errno, MEMCACHED_AT);
-        WATCHPOINT_ASSERT(instance->fd == INVALID_SOCKET);
-        return false;
-      }
-    }
-
-    instance->io_bytes_sent+= uint32_t(sent_length);
-
-    local_write_ptr+= sent_length;
-    write_length-= uint32_t(sent_length);
-  }
-
-  WATCHPOINT_ASSERT(write_length == 0);
-  instance->write_buffer_offset= 0;
-
-  return true;
-}
-
-memcached_return_t memcached_io_wait_for_write(memcached_instance_st* instance)
-{
-  return io_wait(instance, POLLOUT);
-}
-
-memcached_return_t memcached_io_wait_for_read(memcached_instance_st* instance)
-{
-  return io_wait(instance, POLLIN);
-}
-
-static memcached_return_t _io_fill(memcached_instance_st* instance)
-{
-  ssize_t data_read;
-  do
-  {
-    data_read= ::recv(instance->fd, instance->read_buffer, MEMCACHED_MAX_BUFFER, MSG_NOSIGNAL);
-    int local_errno= get_socket_errno(); // We cache in case memcached_quit_server() modifies errno
-
-    if (data_read == SOCKET_ERROR)
-    {
-      switch (get_socket_errno())
-      {
-      case EINTR: // We just retry
-        continue;
-
-      case ETIMEDOUT: // OSX
-#if EWOULDBLOCK != EAGAIN
-      case EWOULDBLOCK:
-#endif
-      case EAGAIN:
-#ifdef __linux
-      case ERESTART:
-#endif
-        {
-          memcached_return_t io_wait_ret;
-          if (memcached_success(io_wait_ret= io_wait(instance, POLLIN)))
-          {
-            continue;
-          }
-
-          return io_wait_ret;
-        }
-
-        /* fall through */
-
-      case ENOTCONN: // Programmer Error
-        WATCHPOINT_ASSERT(0);
-        // fall through
-      case ENOTSOCK:
-        WATCHPOINT_ASSERT(0);
-        // fall through
-      case EBADF:
-        assert_msg(instance->fd != INVALID_SOCKET, "Programmer error, invalid socket");
-        /* fall through */
-      case EINVAL:
-      case EFAULT:
-      case ECONNREFUSED:
-      default:
-        memcached_quit_server(instance, true);
-        memcached_set_errno(*instance, local_errno, MEMCACHED_AT);
-        break;
-      }
-
-      return memcached_instance_error_return(instance);
-    }
-    else if (data_read == 0)
-    {
-      /*
-        EOF. Any data received so far is incomplete
-        so discard it. This always reads by byte in case of TCP
-        and protocol enforcement happens at memcached_response()
-        looking for '\n'. We do not care for UDB which requests 8 bytes
-        at once. Generally, this means that connection went away. Since
-        for blocking I/O we do not return 0 and for non-blocking case
-        it will return EGAIN if data is not immediatly available.
-      */
-      memcached_quit_server(instance, true);
-      return memcached_set_error(*instance, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT, 
-                                 memcached_literal_param("::rec() returned zero, server has disconnected"));
-    }
-    instance->io_wait_count._bytes_read+= data_read;
-  } while (data_read <= 0);
-
-  instance->io_bytes_sent= 0;
-  instance->read_buffer_length= (size_t) data_read;
-  instance->read_ptr= instance->read_buffer;
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_io_read(memcached_instance_st* instance,
-                                     void *buffer, size_t length, ssize_t& nread)
-{
-  assert(memcached_is_udp(instance->root) == false);
-  assert_msg(instance, "Programmer error, memcached_io_read() recieved an invalid Instance"); // Programmer error
-  char *buffer_ptr= static_cast<char *>(buffer);
-
-  if (instance->fd == INVALID_SOCKET)
-  {
-#if 0
-    assert_msg(int(instance->state) <= int(MEMCACHED_SERVER_STATE_ADDRINFO), "Programmer error, invalid socket state");
-#endif
-    return MEMCACHED_CONNECTION_FAILURE;
-  }
-
-  while (length)
-  {
-    if (instance->read_buffer_length == 0)
-    {
-      memcached_return_t io_fill_ret;
-      if (memcached_fatal(io_fill_ret= _io_fill(instance)))
-      {
-        nread= -1;
-        return io_fill_ret;
-      }
-    }
-
-    if (length > 1)
-    {
-      size_t difference= (length > instance->read_buffer_length) ? instance->read_buffer_length : length;
-
-      memcpy(buffer_ptr, instance->read_ptr, difference);
-      length -= difference;
-      instance->read_ptr+= difference;
-      instance->read_buffer_length-= difference;
-      buffer_ptr+= difference;
-    }
-    else
-    {
-      *buffer_ptr= *instance->read_ptr;
-      instance->read_ptr++;
-      instance->read_buffer_length--;
-      buffer_ptr++;
-      break;
-    }
-  }
-
-  nread= ssize_t(buffer_ptr - (char*)buffer);
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_io_slurp(memcached_instance_st* instance)
-{
-  assert_msg(instance, "Programmer error, invalid Instance");
-  assert(memcached_is_udp(instance->root) == false);
-
-  if (instance->fd == INVALID_SOCKET)
-  {
-    assert_msg(int(instance->state) <= int(MEMCACHED_SERVER_STATE_ADDRINFO), "Invalid socket state");
-    return MEMCACHED_CONNECTION_FAILURE;
-  }
-
-  ssize_t data_read;
-  char buffer[MEMCACHED_MAX_BUFFER];
-  do
-  {
-    data_read= ::recv(instance->fd, instance->read_buffer, sizeof(buffer), MSG_NOSIGNAL);
-    if (data_read == SOCKET_ERROR)
-    {
-      switch (get_socket_errno())
-      {
-      case EINTR: // We just retry
-        continue;
-
-      case ETIMEDOUT: // OSX
-#if EWOULDBLOCK != EAGAIN
-      case EWOULDBLOCK:
-#endif
-      case EAGAIN:
-#ifdef __linux
-      case ERESTART:
-#endif
-        if (memcached_success(io_wait(instance, POLLIN)))
-        {
-          continue;
-        }
-        return MEMCACHED_IN_PROGRESS;
-
-        /* fall through */
-
-      case ENOTCONN: // Programmer Error
-      case ENOTSOCK:
-        assert(0);
-        /* fall through */
-      case EBADF:
-        assert_msg(instance->fd != INVALID_SOCKET, "Invalid socket state");
-        /* fall through */
-      case EINVAL:
-      case EFAULT:
-      case ECONNREFUSED:
-      default:
-        return MEMCACHED_CONNECTION_FAILURE; // We want this!
-      }
-    }
-  } while (data_read > 0);
-
-  return MEMCACHED_CONNECTION_FAILURE;
-}
-
-static bool _io_write(memcached_instance_st* instance,
-                      const void *buffer, size_t length, bool with_flush,
-                      size_t& written)
-{
-  assert(instance->fd != INVALID_SOCKET);
-  assert(memcached_is_udp(instance->root) == false);
-
-  const char *buffer_ptr= static_cast<const char *>(buffer);
-
-  const size_t original_length= length;
-
-  while (length)
-  {
-    char *write_ptr;
-    size_t buffer_end= MEMCACHED_MAX_BUFFER;
-    size_t should_write= buffer_end -instance->write_buffer_offset;
-    should_write= (should_write < length) ? should_write : length;
-
-    write_ptr= instance->write_buffer + instance->write_buffer_offset;
-    memcpy(write_ptr, buffer_ptr, should_write);
-    instance->write_buffer_offset+= should_write;
-    buffer_ptr+= should_write;
-    length-= should_write;
-
-    if (instance->write_buffer_offset == buffer_end)
-    {
-      WATCHPOINT_ASSERT(instance->fd != INVALID_SOCKET);
-
-      memcached_return_t rc;
-      if (io_flush(instance, with_flush, rc) == false)
-      {
-        written= original_length -length;
-        return false;
-      }
-    }
-  }
-
-  if (with_flush)
-  {
-    memcached_return_t rc;
-    WATCHPOINT_ASSERT(instance->fd != INVALID_SOCKET);
-    if (io_flush(instance, with_flush, rc) == false)
-    {
-      written= original_length -length;
-      return false;
-    }
-  }
-
-  written= original_length -length;
-
-  return true;
-}
-
-bool memcached_io_write(memcached_instance_st* instance)
-{
-  size_t written;
-  return _io_write(instance, NULL, 0, true, written);
-}
-
-ssize_t memcached_io_write(memcached_instance_st* instance,
-                           const void *buffer, const size_t length, const bool with_flush)
-{
-  size_t written;
-
-  if (_io_write(instance, buffer, length, with_flush, written) == false)
-  {
-    return -1;
-  }
-
-  return ssize_t(written);
-}
-
-bool memcached_io_writev(memcached_instance_st* instance,
-                         libmemcached_io_vector_st vector[],
-                         const size_t number_of, const bool with_flush)
-{
-  ssize_t complete_total= 0;
-  ssize_t total= 0;
-
-  for (size_t x= 0; x < number_of; x++, vector++)
-  {
-    complete_total+= vector->length;
-    if (vector->length)
-    {
-      size_t written;
-      if ((_io_write(instance, vector->buffer, vector->length, false, written)) == false)
-      {
-        return false;
-      }
-      total+= written;
-    }
-  }
-
-  if (with_flush)
-  {
-    if (memcached_io_write(instance) == false)
-    {
-      return false;
-    }
-  }
-
-  return (complete_total == total);
-}
-
-void memcached_instance_st::start_close_socket()
-{
-  if (fd != INVALID_SOCKET)
-  {
-    shutdown(fd, SHUT_WR);
-    options.is_shutting_down= true;
-  }
-}
-
-void memcached_instance_st::reset_socket()
-{
-  if (fd != INVALID_SOCKET)
-  {
-    (void)closesocket(fd);
-    fd= INVALID_SOCKET;
-  }
-}
-
-void memcached_instance_st::close_socket()
-{
-  if (fd != INVALID_SOCKET)
-  {
-    int shutdown_options= SHUT_RD;
-    if (options.is_shutting_down == false)
-    {
-      shutdown_options= SHUT_RDWR;
-    }
-
-    /* in case of death shutdown to avoid blocking at close() */
-    if (shutdown(fd, shutdown_options) == SOCKET_ERROR and get_socket_errno() != ENOTCONN)
-    {
-      WATCHPOINT_NUMBER(fd);
-      WATCHPOINT_ERRNO(get_socket_errno());
-      WATCHPOINT_ASSERT(get_socket_errno());
-    }
-
-    reset_socket();
-    state= MEMCACHED_SERVER_STATE_NEW;
-  }
-
-  state= MEMCACHED_SERVER_STATE_NEW;
-  cursor_active_= 0;
-  io_bytes_sent= 0;
-  write_buffer_offset= size_t(root and memcached_is_udp(root) ? UDP_DATAGRAM_HEADER_LENGTH : 0);
-  read_buffer_length= 0;
-  read_ptr= read_buffer;
-  options.is_shutting_down= false;
-  memcached_server_response_reset(this);
-
-  // We reset the version so that if we end up talking to a different server
-  // we don't have stale server version information.
-  major_version= minor_version= micro_version= UINT8_MAX;
-}
-
-memcached_instance_st* memcached_io_get_readable_server(Memcached *memc, memcached_return_t&)
-{
-#define MAX_SERVERS_TO_POLL 100
-  struct pollfd fds[MAX_SERVERS_TO_POLL];
-  nfds_t host_index= 0;
-
-  for (uint32_t x= 0; x < memcached_server_count(memc) and host_index < MAX_SERVERS_TO_POLL; ++x)
-  {
-    memcached_instance_st* instance= memcached_instance_fetch(memc, x);
-
-    if (instance->read_buffer_length > 0) /* I have data in the buffer */
-    {
-      return instance;
-    }
-
-    if (instance->response_count() > 0)
-    {
-      fds[host_index].events= POLLIN;
-      fds[host_index].revents= 0;
-      fds[host_index].fd= instance->fd;
-      ++host_index;
-    }
-  }
-
-  if (host_index < 2)
-  {
-    /* We have 0 or 1 server with pending events.. */
-    for (uint32_t x= 0; x< memcached_server_count(memc); ++x)
-    {
-      memcached_instance_st* instance= memcached_instance_fetch(memc, x);
-
-      if (instance->response_count() > 0)
-      {
-        return instance;
-      }
-    }
-
-    return NULL;
-  }
-
-  int error= poll(fds, host_index, memc->poll_timeout);
-  switch (error)
-  {
-  case -1:
-    memcached_set_errno(*memc, get_socket_errno(), MEMCACHED_AT);
-    /* FALLTHROUGH */
-  case 0:
-    break;
-
-  default:
-    for (nfds_t x= 0; x < host_index; ++x)
-    {
-      if (fds[x].revents & POLLIN)
-      {
-        for (uint32_t y= 0; y < memcached_server_count(memc); ++y)
-        {
-          memcached_instance_st* instance= memcached_instance_fetch(memc, y);
-
-          if (instance->fd == fds[x].fd)
-          {
-            return instance;
-          }
-        }
-      }
-    }
-  }
-
-  return NULL;
-}
-
-/*
-  Eventually we will just kill off the server with the problem.
-*/
-void memcached_io_reset(memcached_instance_st* instance)
-{
-  memcached_quit_server(instance, true);
-}
-
-/**
- * Read a given number of bytes from the server and place it into a specific
- * buffer. Reset the IO channel on this server if an error occurs.
- */
-memcached_return_t memcached_safe_read(memcached_instance_st* instance,
-                                       void *dta,
-                                       const size_t size)
-{
-  size_t offset= 0;
-  char *data= static_cast<char *>(dta);
-
-  while (offset < size)
-  {
-    ssize_t nread;
-    memcached_return_t rc;
-
-    while (memcached_continue(rc= memcached_io_read(instance, data + offset, size - offset, nread))) { };
-
-    if (memcached_failed(rc))
-    {
-      return rc;
-    }
-
-    offset+= size_t(nread);
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_io_readline(memcached_instance_st* instance,
-                                         char *buffer_ptr,
-                                         size_t size,
-                                         size_t& total_nr)
-{
-  total_nr= 0;
-  bool line_complete= false;
-
-  while (line_complete == false)
-  {
-    if (instance->read_buffer_length == 0)
-    {
-      /*
-       * We don't have any data in the buffer, so let's fill the read
-       * buffer. Call the standard read function to avoid duplicating
-       * the logic.
-     */
-      ssize_t nread;
-      memcached_return_t rc= memcached_io_read(instance, buffer_ptr, 1, nread);
-      if (memcached_failed(rc) and rc == MEMCACHED_IN_PROGRESS)
-      {
-        memcached_quit_server(instance, true);
-        return memcached_set_error(*instance, rc, MEMCACHED_AT);
-      }
-      else if (memcached_failed(rc))
-      {
-        return rc;
-      }
-
-      if (*buffer_ptr == '\n')
-      {
-        line_complete= true;
-      }
-
-      ++buffer_ptr;
-      ++total_nr;
-    }
-
-    /* Now let's look in the buffer and copy as we go! */
-    while (instance->read_buffer_length and total_nr < size and line_complete == false)
-    {
-      *buffer_ptr = *instance->read_ptr;
-      if (*buffer_ptr == '\n')
-      {
-        line_complete = true;
-      }
-      --instance->read_buffer_length;
-      ++instance->read_ptr;
-      ++total_nr;
-      ++buffer_ptr;
-    }
-
-    if (total_nr == size)
-    {
-      return MEMCACHED_PROTOCOL_ERROR;
-    }
-  }
-
-  return MEMCACHED_SUCCESS;
-}
diff --git a/libmemcached/io.h b/libmemcached/io.h
deleted file mode 100644 (file)
index c2711e2..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-struct libmemcached_io_vector_st
-{
-  const void *buffer;
-  size_t length;
-};
diff --git a/libmemcached/io.hpp b/libmemcached/io.hpp
deleted file mode 100644 (file)
index 5480239..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-void initialize_binary_request(memcached_instance_st* server, protocol_binary_request_header&);
-
-bool memcached_io_write(memcached_instance_st* ptr);
-
-ssize_t memcached_io_write(memcached_instance_st* ptr,
-                           const void *buffer, size_t length, bool with_flush);
-
-bool memcached_io_writev(memcached_instance_st* ptr,
-                         libmemcached_io_vector_st vector[],
-                         const size_t number_of, const bool with_flush);
-
-memcached_return_t memcached_io_wait_for_write(memcached_instance_st*);
-memcached_return_t memcached_io_wait_for_read(memcached_instance_st*);
-
-void memcached_io_reset(memcached_instance_st* ptr);
-
-memcached_return_t memcached_io_read(memcached_instance_st* ptr,
-                                     void *buffer, size_t length, ssize_t& nread);
-
-/* Read a line (terminated by '\n') into the buffer */
-memcached_return_t memcached_io_readline(memcached_instance_st* ptr,
-                                         char *buffer_ptr,
-                                         size_t size,
-                                         size_t& total);
-
-/* Read n bytes of data from the server and store them in dta */
-memcached_return_t memcached_safe_read(memcached_instance_st* ptr,
-                                       void *dta,
-                                       const size_t size);
-
-memcached_instance_st* memcached_io_get_readable_server(memcached_st *memc, memcached_return_t&);
-
-memcached_return_t memcached_io_slurp(memcached_instance_st* ptr);
diff --git a/libmemcached/is.h b/libmemcached/is.h
deleted file mode 100644 (file)
index 54f2c2b..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-/* These are private */ 
-#define memcached_is_allocated(__object) ((__object)->options.is_allocated)
-#define memcached_is_encrypted(__object) ((__object)->hashkit._key)
-#define memcached_is_initialized(__object) ((__object)->options.is_initialized)
-#define memcached_is_purging(__object) ((__object)->state.is_purging)
-#define memcached_is_processing_input(__object) ((__object)->state.is_processing_input)
-
-#define memcached_is_aes(__object) ((__object)->flags.is_aes)
-#define memcached_is_udp(__object) ((__object)->flags.use_udp)
-#define memcached_is_verify_key(__object) ((__object)->flags.verify_key)
-#define memcached_is_binary(__object) ((__object)->flags.binary_protocol)
-#define memcached_is_fetching_version(__object) ((__object)->flags.is_fetching_version)
-#define memcached_is_buffering(__object) ((__object)->flags.buffer_requests)
-#define memcached_is_replying(__object) ((__object)->flags.reply)
-#define memcached_is_cas(__object) ((__object)->flags.reply)
-#define memcached_is_randomize_replica_read(__object) ((__object)->flags.randomize_replica_read)
-#define memcached_is_no_block(__object) ((__object)->flags.no_block)
-#define memcached_is_hash_with_namespace(__object) ((__object)->flags.hash_with_namespace)
-#define memcached_is_tcp_nodelay(__object) ((__object)->flags.tcp_nodelay)
-#define memcached_is_auto_eject_hosts(__object) ((__object)->flags.auto_eject_hosts)
-#define memcached_is_use_sort_hosts(__object) ((__object)->flags.use_sort_hosts)
-
-#define memcached_is_ready(__object) ((__object)->options.ready)
-
-#define memcached_is_weighted_ketama(__object) ((__object)->ketama.weighted_)
-
-#define memcached_set_ready(__object, __flag) ((__object)->options.ready= (__flag))
-
-#define memcached_set_aes(__object, __flag) ((__object).flags.is_aes= __flag)
-#define memcached_set_udp(__object, __flag) ((__object).flags.use_udp= __flag)
-#define memcached_set_verify_key(__object, __flag) ((__object).flags.verify_key= __flag)
-#define memcached_set_binary(__object, __flag) ((__object).flags.binary_protocol= __flag)
-#define memcached_set_fetching_version(__object, __flag) ((__object).flags.is_fetching_version= __flag)
-#define memcached_set_buffering(__object, __flag) ((__object).flags.buffer_requests= __flag)
-#define memcached_set_replying(__object, __flag) ((__object).flags.reply= __flag)
-#define memcached_set_cas(__object, __flag) ((__object).flags.reply= __flag)
-#define memcached_set_randomize_replica_read(__object, __flag) ((__object).flags.randomize_replica_read= __flag)
-#define memcached_set_no_block(__object, __flag) ((__object).flags.no_block= __flag)
-#define memcached_set_hash_with_namespace(__object, __flag) ((__object).flags.hash_with_namespace= __flag)
-#define memcached_set_tcp_nodelay(__object, __flag) ((__object).flags.tcp_nodelay= __flag)
-#define memcached_set_auto_eject_hosts(__object, __flag) ((__object).flags.auto_eject_hosts= __flag)
-#define memcached_set_use_sort_hosts(__object, __flag) ((__object).flags.use_sort_hosts= __flag)
-
-#define memcached_has_root(__object) ((__object)->root)
-
-#define memcached_has_error(__object) ((__object)->error_messages)
-
-#define memcached_has_replicas(__object) ((__object)->root->number_of_replicas)
-
-#define memcached_set_processing_input(__object, __value) ((__object)->state.is_processing_input= (__value))
-#define memcached_set_initialized(__object, __value) ((__object)->options.is_initialized= (__value))
-#define memcached_set_allocated(__object, __value) ((__object)->options.is_allocated= (__value))
-
-#define memcached_set_weighted_ketama(__object, __value) ((__object)->ketama.weighted_= (__value))
-
-#define memcached2Memcached(__obj) (__obj)
diff --git a/libmemcached/key.cc b/libmemcached/key.cc
deleted file mode 100644 (file)
index cec0eec..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-static inline memcached_return_t memcached_validate_key_length(size_t key_length, bool)
-{
-  if (key_length == 0)
-  {
-    return MEMCACHED_BAD_KEY_PROVIDED;
-  }
-
-  // No one ever reimplemented MEMCACHED to use keys longer then the original ascii length
-#if 0
-  if (binary)
-  {
-    if (key_length > 0xffff)
-    {
-      return MEMCACHED_BAD_KEY_PROVIDED;
-    }
-  }
-  else
-#endif
-  {
-    if (key_length >= MEMCACHED_MAX_KEY)
-    {
-      return MEMCACHED_BAD_KEY_PROVIDED;
-    }
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_key_test(memcached_st &memc,
-                                      const char * const *keys,
-                                      const size_t *key_length,
-                                      size_t number_of_keys)
-{
-  if (number_of_keys == 0)
-  {
-    return memcached_set_error(memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Numbers of keys provided was zero"));
-  }
-
-  if (keys == NULL or key_length == NULL)
-  {
-    return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT, memcached_literal_param("Key was NULL or length of key was zero."));
-  }
-
-  const bool is_binary= memcached_flag(memc, MEMCACHED_FLAG_BINARY_PROTOCOL);
-
-  // If we don't need to verify the key, or we are using the binary protoocol,
-  // we just check the size of the key
-  for (size_t x= 0; x < number_of_keys; ++x)
-  {
-    // We should set binary key, but the memcached server is broken for
-    // longer keys at the moment.
-    memcached_return_t rc= memcached_validate_key_length(*(key_length +x), false /* memc.flags.binary_protocol */);
-    if (memcached_failed(rc))
-    {
-      return memcached_set_error(memc, rc, MEMCACHED_AT, memcached_literal_param("Key provided was too long."));
-    }
-
-    if (memc.flags.verify_key and is_binary == false)
-    {
-      for (size_t y= 0; y < *(key_length +x); ++y)
-      {
-        if ((isgraph(keys[x][y])) == 0)
-        {
-          return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT, memcached_literal_param("Key provided had invalid character."));
-        }
-      }
-    }
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
diff --git a/libmemcached/key.hpp b/libmemcached/key.hpp
deleted file mode 100644 (file)
index 811a4b7..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-memcached_return_t memcached_key_test(memcached_st& memc,
-                                      const char * const *keys,
-                                      const size_t *key_length,
-                                      size_t number_of_keys);
-
diff --git a/libmemcached/libmemcached_probes.d b/libmemcached/libmemcached_probes.d
deleted file mode 100644 (file)
index 28d8402..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-provider libmemcached {
-       probe memcached_delete_start();
-       probe memcached_delete_end();
-       probe memcached_increment_with_initial_start();
-       probe memcached_increment_with_initial_end();
-       probe memcached_decrement_with_initial_start();
-       probe memcached_decrement_with_initial_end();
-       probe memcached_increment_start();
-       probe memcached_increment_end();
-       probe memcached_decrement_start();
-       probe memcached_decrement_end();
-       probe memcached_flush_start();
-       probe memcached_flush_end();
-       probe memcached_set_start();
-       probe memcached_set_end();
-       probe memcached_add_start();
-       probe memcached_add_end();
-       probe memcached_replace_start();
-       probe memcached_replace_end();
-       probe memcached_get_start();
-       probe memcached_get_end();
-       probe memcached_touch_start();
-       probe memcached_touch_end();
-       probe memcached_mget_start();
-       probe memcached_mget_end();
-       probe memcached_connect_start();
-       probe memcached_connect_end();
-       probe memcached_server_add_start();
-       probe memcached_server_add_end();
-};
diff --git a/libmemcached/libmemcached_probes.h b/libmemcached/libmemcached_probes.h
deleted file mode 100644 (file)
index 9dba8aa..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-/*
- * This file contains the definition of the various probes supported by
- * libmemcached. Currently it only support DTRACE, but just create an
- * implementation of the following macros to create your own sort of
- * probing :)
- */
-
-#ifdef HAVE_DTRACE
-/*
- * Create the DTrace probes on the system using it (to support both Solaris
- * and MacOS X
- */
-#include "libmemcached/dtrace_probes.h"
-
-#else
-/*
- * Provide dummy macros so that we don't need to clutter the code with
- * ifdefs when we want to use the probes.
- */
-
-#define        LIBMEMCACHED_MEMCACHED_ADD_END()
-#define        LIBMEMCACHED_MEMCACHED_ADD_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_ADD_START()
-#define        LIBMEMCACHED_MEMCACHED_ADD_START_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_CONNECT_END()
-#define        LIBMEMCACHED_MEMCACHED_CONNECT_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_CONNECT_START()
-#define        LIBMEMCACHED_MEMCACHED_CONNECT_START_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_DECREMENT_END()
-#define        LIBMEMCACHED_MEMCACHED_DECREMENT_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_DECREMENT_START()
-#define        LIBMEMCACHED_MEMCACHED_DECREMENT_START_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_END()
-#define        LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_START()
-#define        LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_START_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_DELETE_END()
-#define        LIBMEMCACHED_MEMCACHED_DELETE_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_DELETE_START()
-#define        LIBMEMCACHED_MEMCACHED_DELETE_START_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_FLUSH_END()
-#define        LIBMEMCACHED_MEMCACHED_FLUSH_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_FLUSH_START()
-#define        LIBMEMCACHED_MEMCACHED_FLUSH_START_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_GET_END()
-#define        LIBMEMCACHED_MEMCACHED_GET_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_GET_START()
-#define        LIBMEMCACHED_MEMCACHED_GET_START_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_TOUCH_END()
-#define        LIBMEMCACHED_MEMCACHED_TOUCH_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_TOUCH_START()
-#define        LIBMEMCACHED_MEMCACHED_TOUCH_START_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_INCREMENT_END()
-#define        LIBMEMCACHED_MEMCACHED_INCREMENT_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_INCREMENT_START()
-#define        LIBMEMCACHED_MEMCACHED_INCREMENT_START_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END()
-#define        LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START()
-#define        LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_MGET_END()
-#define        LIBMEMCACHED_MEMCACHED_MGET_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_MGET_START()
-#define        LIBMEMCACHED_MEMCACHED_MGET_START_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_REPLACE_END()
-#define        LIBMEMCACHED_MEMCACHED_REPLACE_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_REPLACE_START()
-#define        LIBMEMCACHED_MEMCACHED_REPLACE_START_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_SERVER_ADD_END()
-#define        LIBMEMCACHED_MEMCACHED_SERVER_ADD_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_SERVER_ADD_START()
-#define        LIBMEMCACHED_MEMCACHED_SERVER_ADD_START_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_SET_END()
-#define        LIBMEMCACHED_MEMCACHED_SET_END_ENABLED() (0)
-#define        LIBMEMCACHED_MEMCACHED_SET_START()
-#define        LIBMEMCACHED_MEMCACHED_SET_START_ENABLED() (0)
-
-#endif
diff --git a/libmemcached/memcached.cc b/libmemcached/memcached.cc
deleted file mode 100644 (file)
index 6e88c25..0000000
+++ /dev/null
@@ -1,495 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-#include <libmemcached/options.hpp>
-#include <libmemcached/virtual_bucket.h>
-
-static inline bool _memcached_init(Memcached *self)
-{
-  self->state.is_purging= false;
-  self->state.is_processing_input= false;
-  self->state.is_time_for_rebuild= false;
-  self->state.is_parsing= false;
-
-  self->flags.auto_eject_hosts= false;
-  self->flags.binary_protocol= false;
-  self->flags.buffer_requests= false;
-  self->flags.hash_with_namespace= false;
-  self->flags.no_block= false;
-  self->flags.reply= true;
-  self->flags.randomize_replica_read= false;
-  self->flags.support_cas= false;
-  self->flags.tcp_nodelay= false;
-  self->flags.use_sort_hosts= false;
-  self->flags.use_udp= false;
-  self->flags.verify_key= false;
-  self->flags.tcp_keepalive= false;
-  self->flags.is_aes= false;
-  self->flags.is_fetching_version= false;
-
-  self->virtual_bucket= NULL;
-
-  self->distribution= MEMCACHED_DISTRIBUTION_MODULA;
-
-  if (hashkit_create(&self->hashkit) == NULL)
-  {
-    return false;
-  }
-
-  self->server_info.version= 0;
-
-  self->ketama.continuum= NULL;
-  self->ketama.continuum_count= 0;
-  self->ketama.continuum_points_counter= 0;
-  self->ketama.next_distribution_rebuild= 0;
-  self->ketama.weighted_= false;
-
-  self->number_of_hosts= 0;
-  self->servers= NULL;
-  self->last_disconnected_server= NULL;
-
-  self->snd_timeout= 0;
-  self->rcv_timeout= 0;
-  self->server_failure_limit= MEMCACHED_SERVER_FAILURE_LIMIT;
-  self->server_timeout_limit= MEMCACHED_SERVER_TIMEOUT_LIMIT;
-  self->query_id= 1; // 0 is considered invalid
-
-  /* TODO, Document why we picked these defaults */
-  self->io_msg_watermark= 500;
-  self->io_bytes_watermark= 65 * 1024;
-
-  self->tcp_keepidle= 0;
-
-  self->io_key_prefetch= 0;
-  self->poll_timeout= MEMCACHED_DEFAULT_TIMEOUT;
-  self->connect_timeout= MEMCACHED_DEFAULT_CONNECT_TIMEOUT;
-  self->retry_timeout= MEMCACHED_SERVER_FAILURE_RETRY_TIMEOUT;
-  self->dead_timeout= MEMCACHED_SERVER_FAILURE_DEAD_TIMEOUT;
-
-  self->send_size= -1;
-  self->recv_size= -1;
-
-  self->user_data= NULL;
-  self->number_of_replicas= 0;
-
-  self->allocators= memcached_allocators_return_default();
-
-  self->on_clone= NULL;
-  self->on_cleanup= NULL;
-  self->get_key_failure= NULL;
-  self->delete_trigger= NULL;
-  self->callbacks= NULL;
-  self->sasl.callbacks= NULL;
-  self->sasl.is_allocated= false;
-
-  self->error_messages= NULL;
-  self->_namespace= NULL;
-  self->configure.initial_pool_size= 1;
-  self->configure.max_pool_size= 1;
-  self->configure.version= -1;
-  self->configure.filename= NULL;
-
-  return true;
-}
-
-static void __memcached_free(Memcached *ptr, bool release_st)
-{
-  /* If we have anything open, lets close it now */
-  send_quit(ptr);
-  memcached_instance_list_free(memcached_instance_list(ptr), memcached_instance_list_count(ptr));
-  memcached_result_free(&ptr->result);
-
-  memcached_virtual_bucket_free(ptr);
-
-  memcached_instance_free((memcached_instance_st*)ptr->last_disconnected_server);
-
-  if (ptr->on_cleanup)
-  {
-    ptr->on_cleanup(ptr);
-  }
-
-  libmemcached_free(ptr, ptr->ketama.continuum);
-  ptr->ketama.continuum= NULL;
-
-  memcached_array_free(ptr->_namespace);
-  ptr->_namespace= NULL;
-
-  memcached_error_free(*ptr);
-
-  if (LIBMEMCACHED_WITH_SASL_SUPPORT and ptr->sasl.callbacks)
-  {
-    memcached_destroy_sasl_auth_data(ptr);
-  }
-
-  if (release_st)
-  {
-    memcached_array_free(ptr->configure.filename);
-    ptr->configure.filename= NULL;
-  }
-
-  hashkit_free(&ptr->hashkit);
-
-  if (memcached_is_allocated(ptr) and release_st)
-  {
-    libmemcached_free(ptr, ptr);
-  }
-}
-
-memcached_st *memcached_create(memcached_st *shell)
-{
-  if (shell)
-  {
-    shell->options.is_allocated= false;
-  }
-  else
-  {
-    shell= (memcached_st *)libmemcached_xmalloc(NULL, memcached_st);
-
-    if (shell == NULL)
-    {
-      return NULL; /*  MEMCACHED_MEMORY_ALLOCATION_FAILURE */
-    }
-
-    shell->options.is_allocated= true;
-  }
-
-  if (_memcached_init(shell) == false)
-  {
-    memcached_free(shell);
-    return NULL;
-  }
-
-  Memcached* memc= memcached2Memcached(shell);
-  if (memcached_result_create(shell, &memc->result) == NULL)
-  {
-    memcached_free(shell);
-    return NULL;
-  }
-
-  WATCHPOINT_ASSERT_INITIALIZED(&memc->result);
-
-  return shell;
-}
-
-memcached_st *memcached(const char *string, size_t length)
-{
-  if (length == 0 and string)
-  {
-    return NULL;
-  }
-
-  if (length and string == NULL)
-  {
-    return NULL;
-  }
-
-  if (length == 0)
-  {
-    if (bool(getenv("LIBMEMCACHED")))
-    {
-      string= getenv("LIBMEMCACHED");
-      length= string ? strlen(string) : 0;
-    }
-  }
-
-  memcached_st *memc= memcached_create(NULL);
-  if (memc == NULL)
-  {
-    return NULL;
-  }
-
-  if (length == 0 or string == NULL)
-  {
-    return memc;
-  }
-
-  memcached_return_t rc= memcached_parse_configuration(memc, string, length);
-  if (memcached_success(rc) and memcached_parse_filename(memc))
-  {
-    rc= memcached_parse_configure_file(*memc, memcached_parse_filename(memc), memcached_parse_filename_length(memc));
-  }
-    
-  if (memcached_failed(rc))
-  {
-    memcached_free(memc);
-    return NULL;
-  }
-
-  return memc;
-}
-
-memcached_return_t memcached_reset(memcached_st *shell)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  WATCHPOINT_ASSERT(ptr);
-  if (ptr == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  bool stored_is_allocated= memcached_is_allocated(ptr);
-  uint64_t query_id= ptr->query_id;
-  __memcached_free(ptr, false);
-  memcached_create(ptr);
-  memcached_set_allocated(ptr, stored_is_allocated);
-  ptr->query_id= query_id;
-
-  if (ptr->configure.filename)
-  {
-    return memcached_parse_configure_file(*ptr, memcached_param_array(ptr->configure.filename));
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-void memcached_servers_reset(memcached_st *shell)
-{
-  Memcached* self= memcached2Memcached(shell);
-  if (self)
-  {
-    libmemcached_free(self, self->ketama.continuum);
-    self->ketama.continuum= NULL;
-    self->ketama.continuum_count= 0;
-    self->ketama.continuum_points_counter= 0;
-
-    memcached_instance_list_free(memcached_instance_list(self), self->number_of_hosts);
-    memcached_instance_set(self, NULL, 0);
-
-    memcached_reset_last_disconnected_server(self);
-  }
-}
-
-void memcached_reset_last_disconnected_server(memcached_st *shell)
-{
-  Memcached* self= memcached2Memcached(shell);
-  if (self)
-  {
-    memcached_instance_free((memcached_instance_st*)self->last_disconnected_server);
-    self->last_disconnected_server= NULL;
-  }
-}
-
-void memcached_free(memcached_st *ptr)
-{
-  if (ptr)
-  {
-    __memcached_free(ptr, true);
-  }
-}
-
-/*
-  clone is the destination, while source is the structure to clone.
-  If source is NULL the call is the same as if a memcached_create() was
-  called.
-*/
-memcached_st *memcached_clone(memcached_st *clone, const memcached_st *source)
-{
-  if (source == NULL)
-  {
-    return memcached_create(clone);
-  }
-
-  if (clone and memcached_is_allocated(clone))
-  {
-    return NULL;
-  }
-
-  memcached_st *new_clone= memcached_create(clone);
-
-  if (new_clone == NULL)
-  {
-    return NULL;
-  }
-
-  new_clone->flags= source->flags;
-  new_clone->send_size= source->send_size;
-  new_clone->recv_size= source->recv_size;
-  new_clone->poll_timeout= source->poll_timeout;
-  new_clone->connect_timeout= source->connect_timeout;
-  new_clone->retry_timeout= source->retry_timeout;
-  new_clone->dead_timeout= source->dead_timeout;
-  new_clone->distribution= source->distribution;
-
-  if (hashkit_clone(&new_clone->hashkit, &source->hashkit) == NULL)
-  {
-    memcached_free(new_clone);
-    return NULL;
-  }
-
-  new_clone->user_data= source->user_data;
-
-  new_clone->snd_timeout= source->snd_timeout;
-  new_clone->rcv_timeout= source->rcv_timeout;
-
-  new_clone->on_clone= source->on_clone;
-  new_clone->on_cleanup= source->on_cleanup;
-
-  new_clone->allocators= source->allocators;
-
-  new_clone->get_key_failure= source->get_key_failure;
-  new_clone->delete_trigger= source->delete_trigger;
-  new_clone->server_failure_limit= source->server_failure_limit;
-  new_clone->server_timeout_limit= source->server_timeout_limit;
-  new_clone->io_msg_watermark= source->io_msg_watermark;
-  new_clone->io_bytes_watermark= source->io_bytes_watermark;
-  new_clone->io_key_prefetch= source->io_key_prefetch;
-  new_clone->number_of_replicas= source->number_of_replicas;
-  new_clone->tcp_keepidle= source->tcp_keepidle;
-
-  if (memcached_server_count(source))
-  {
-    if (memcached_failed(memcached_push(new_clone, source)))
-    {
-      return NULL;
-    }
-  }
-
-
-  new_clone->_namespace= memcached_array_clone(new_clone, source->_namespace);
-  new_clone->configure.filename= memcached_array_clone(new_clone, source->_namespace);
-  new_clone->configure.version= source->configure.version;
-
-  if (LIBMEMCACHED_WITH_SASL_SUPPORT and source->sasl.callbacks)
-  {
-    if (memcached_failed(memcached_clone_sasl(new_clone, source)))
-    {
-      memcached_free(new_clone);
-      return NULL;
-    }
-  }
-
-  if (memcached_failed(run_distribution(new_clone)))
-  {
-    memcached_free(new_clone);
-
-    return NULL;
-  }
-
-  if (source->on_clone)
-  {
-    source->on_clone(new_clone, source);
-  }
-
-  return new_clone;
-}
-
-void *memcached_get_user_data(const memcached_st *shell)
-{
-  const Memcached* memc= memcached2Memcached(shell);
-  if (memc)
-  {
-    return memc->user_data;
-  }
-
-  return NULL;
-}
-
-void *memcached_set_user_data(memcached_st *shell, void *data)
-{
-  Memcached* memc= memcached2Memcached(shell);
-  if (memc)
-  {
-    void *ret= memc->user_data;
-    memc->user_data= data;
-
-    return ret;
-  }
-
-  return NULL;
-}
-
-memcached_return_t memcached_push(memcached_st *destination, const memcached_st *source)
-{
-  return memcached_instance_push(destination, (memcached_instance_st*)source->servers, source->number_of_hosts);
-}
-
-memcached_instance_st* memcached_instance_fetch(Memcached *ptr, uint32_t server_key)
-{
-  if (ptr == NULL)
-  {
-    return NULL;
-  }
-
-  return &ptr->servers[server_key];
-}
-
-const memcached_instance_st * memcached_server_instance_by_position(const memcached_st *shell, uint32_t server_key)
-{
-  const Memcached* memc= memcached2Memcached(shell);
-  if (memc)
-  {
-    return &memc->servers[server_key];
-  }
-
-  return NULL;
-}
-
-memcached_instance_st* memcached_instance_by_position(const memcached_st *shell, uint32_t server_key)
-{
-  const Memcached* memc= memcached2Memcached(shell);
-  if (memc)
-  {
-    return &memc->servers[server_key];
-  }
-
-  return NULL;
-}
-
-uint64_t memcached_query_id(const memcached_st *shell)
-{
-  const Memcached* memc= memcached2Memcached(shell);
-  if (memc)
-  {
-    return memc->query_id;
-  }
-
-  return 0;
-}
-
-memcached_instance_st* memcached_instance_list(const memcached_st *shell)
-{
-  const Memcached* memc= memcached2Memcached(shell);
-  if (memc)
-  {
-    return (memcached_instance_st*)memc->servers;
-  }
-
-  return NULL;
-}
-
diff --git a/libmemcached/memcached.h b/libmemcached/memcached.h
deleted file mode 100644 (file)
index a45077e..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <libmemcached-1.0/memcached.h>
diff --git a/libmemcached/memcached.hpp b/libmemcached/memcached.hpp
deleted file mode 100644 (file)
index d38e6d2..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <libmemcached-1.0/memcached.hpp>
-
diff --git a/libmemcached/memcached/README.txt b/libmemcached/memcached/README.txt
deleted file mode 100644 (file)
index adcac80..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-For your convenience libmemcached contains a copy of protocol_binary.h so that
-you may compile libmemcached without having a memcached server with support
-for the binary protocol installed on your computer. Please do not modify this
-fine, but replace it with a fresh copy from a new distribution if they are 
-out of sync.
-
-Trond Norbye
diff --git a/libmemcached/memcached/protocol_binary.h b/libmemcached/memcached/protocol_binary.h
deleted file mode 100644 (file)
index 51e2c42..0000000
+++ /dev/null
@@ -1,728 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- * Copyright (c) <2008>, Sun Microsystems, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the  nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY SUN MICROSYSTEMS, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * Summary: Constants used by to implement the binary protocol.
- *
- * Copy: See Copyright for the status of this software.
- *
- * Author: Trond Norbye <trond.norbye@sun.com>
- */
-
-#ifndef PROTOCOL_BINARY_H
-#define PROTOCOL_BINARY_H
-
-#include <libmemcachedprotocol-0.0/vbucket.h>
-
-/**
- * \addtogroup Protocol
- * @{
- */
-
-/**
- * This file contains definitions of the constants and packet formats
- * defined in the binary specification. Please note that you _MUST_ remember
- * to convert each multibyte field to / from network byte order to / from
- * host order.
- */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /**
-     * Definition of the legal "magic" values used in a packet.
-     * See section 3.1 Magic byte
-     */
-    typedef enum {
-        PROTOCOL_BINARY_REQ = 0x80,
-        PROTOCOL_BINARY_RES = 0x81
-    } protocol_binary_magic;
-
-    /**
-     * Definition of the valid response status numbers.
-     * See section 3.2 Response Status
-     */
-    typedef enum {
-        PROTOCOL_BINARY_RESPONSE_SUCCESS = 0x00,
-        PROTOCOL_BINARY_RESPONSE_KEY_ENOENT = 0x01,
-        PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS = 0x02,
-        PROTOCOL_BINARY_RESPONSE_E2BIG = 0x03,
-        PROTOCOL_BINARY_RESPONSE_EINVAL = 0x04,
-        PROTOCOL_BINARY_RESPONSE_NOT_STORED = 0x05,
-        PROTOCOL_BINARY_RESPONSE_DELTA_BADVAL = 0x06,
-        PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET = 0x07,
-        PROTOCOL_BINARY_RESPONSE_AUTH_ERROR = 0x20,
-        PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE = 0x21,
-        PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND = 0x81,
-        PROTOCOL_BINARY_RESPONSE_ENOMEM = 0x82,
-        PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED = 0x83,
-        PROTOCOL_BINARY_RESPONSE_EINTERNAL = 0x84,
-        PROTOCOL_BINARY_RESPONSE_EBUSY = 0x85,
-        PROTOCOL_BINARY_RESPONSE_ETMPFAIL = 0x86
-    } protocol_binary_response_status;
-
-    /**
-     * Defintion of the different command opcodes.
-     * See section 3.3 Command Opcodes
-     */
-    typedef enum {
-        PROTOCOL_BINARY_CMD_GET = 0x00,
-        PROTOCOL_BINARY_CMD_SET = 0x01,
-        PROTOCOL_BINARY_CMD_ADD = 0x02,
-        PROTOCOL_BINARY_CMD_REPLACE = 0x03,
-        PROTOCOL_BINARY_CMD_DELETE = 0x04,
-        PROTOCOL_BINARY_CMD_INCREMENT = 0x05,
-        PROTOCOL_BINARY_CMD_DECREMENT = 0x06,
-        PROTOCOL_BINARY_CMD_QUIT = 0x07,
-        PROTOCOL_BINARY_CMD_FLUSH = 0x08,
-        PROTOCOL_BINARY_CMD_GETQ = 0x09,
-        PROTOCOL_BINARY_CMD_NOOP = 0x0a,
-        PROTOCOL_BINARY_CMD_VERSION = 0x0b,
-        PROTOCOL_BINARY_CMD_GETK = 0x0c,
-        PROTOCOL_BINARY_CMD_GETKQ = 0x0d,
-        PROTOCOL_BINARY_CMD_APPEND = 0x0e,
-        PROTOCOL_BINARY_CMD_PREPEND = 0x0f,
-        PROTOCOL_BINARY_CMD_STAT = 0x10,
-        PROTOCOL_BINARY_CMD_SETQ = 0x11,
-        PROTOCOL_BINARY_CMD_ADDQ = 0x12,
-        PROTOCOL_BINARY_CMD_REPLACEQ = 0x13,
-        PROTOCOL_BINARY_CMD_DELETEQ = 0x14,
-        PROTOCOL_BINARY_CMD_INCREMENTQ = 0x15,
-        PROTOCOL_BINARY_CMD_DECREMENTQ = 0x16,
-        PROTOCOL_BINARY_CMD_QUITQ = 0x17,
-        PROTOCOL_BINARY_CMD_FLUSHQ = 0x18,
-        PROTOCOL_BINARY_CMD_APPENDQ = 0x19,
-        PROTOCOL_BINARY_CMD_PREPENDQ = 0x1a,
-        PROTOCOL_BINARY_CMD_VERBOSITY = 0x1b,
-        PROTOCOL_BINARY_CMD_TOUCH = 0x1c,
-        PROTOCOL_BINARY_CMD_GAT = 0x1d,
-        PROTOCOL_BINARY_CMD_GATQ = 0x1e,
-        PROTOCOL_BINARY_CMD_GATK = 0x23,
-        PROTOCOL_BINARY_CMD_GATKQ = 0x24,
-
-        PROTOCOL_BINARY_CMD_SASL_LIST_MECHS = 0x20,
-        PROTOCOL_BINARY_CMD_SASL_AUTH = 0x21,
-        PROTOCOL_BINARY_CMD_SASL_STEP = 0x22,
-
-        /* These commands are used for range operations and exist within
-         * this header for use in other projects.  Range operations are
-         * not expected to be implemented in the memcached server itself.
-         */
-        PROTOCOL_BINARY_CMD_RGET      = 0x30,
-        PROTOCOL_BINARY_CMD_RSET      = 0x31,
-        PROTOCOL_BINARY_CMD_RSETQ     = 0x32,
-        PROTOCOL_BINARY_CMD_RAPPEND   = 0x33,
-        PROTOCOL_BINARY_CMD_RAPPENDQ  = 0x34,
-        PROTOCOL_BINARY_CMD_RPREPEND  = 0x35,
-        PROTOCOL_BINARY_CMD_RPREPENDQ = 0x36,
-        PROTOCOL_BINARY_CMD_RDELETE   = 0x37,
-        PROTOCOL_BINARY_CMD_RDELETEQ  = 0x38,
-        PROTOCOL_BINARY_CMD_RINCR     = 0x39,
-        PROTOCOL_BINARY_CMD_RINCRQ    = 0x3a,
-        PROTOCOL_BINARY_CMD_RDECR     = 0x3b,
-        PROTOCOL_BINARY_CMD_RDECRQ    = 0x3c,
-        /* End Range operations */
-
-        /* VBucket commands */
-        PROTOCOL_BINARY_CMD_SET_VBUCKET = 0x3d,
-        PROTOCOL_BINARY_CMD_GET_VBUCKET = 0x3e,
-        PROTOCOL_BINARY_CMD_DEL_VBUCKET = 0x3f,
-        /* End VBucket commands */
-
-        /* TAP commands */
-        PROTOCOL_BINARY_CMD_TAP_CONNECT = 0x40,
-        PROTOCOL_BINARY_CMD_TAP_MUTATION = 0x41,
-        PROTOCOL_BINARY_CMD_TAP_DELETE = 0x42,
-        PROTOCOL_BINARY_CMD_TAP_FLUSH = 0x43,
-        PROTOCOL_BINARY_CMD_TAP_OPAQUE = 0x44,
-        PROTOCOL_BINARY_CMD_TAP_VBUCKET_SET = 0x45,
-        PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_START = 0x46,
-        PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_END = 0x47,
-        /* End TAP */
-
-        PROTOCOL_BINARY_CMD_LAST_RESERVED = 0xef,
-
-        /* Scrub the data */
-        PROTOCOL_BINARY_CMD_SCRUB = 0xf0
-    } protocol_binary_command;
-
-    /**
-     * Definition of the data types in the packet
-     * See section 3.4 Data Types
-     */
-    typedef enum {
-        PROTOCOL_BINARY_RAW_BYTES = 0x00
-    } protocol_binary_datatypes;
-
-    /**
-     * Definition of the header structure for a request packet.
-     * See section 2
-     */
-    typedef union {
-        struct {
-            uint8_t magic;
-            uint8_t opcode;
-            uint16_t keylen;
-            uint8_t extlen;
-            uint8_t datatype;
-            uint16_t vbucket;
-            uint32_t bodylen;
-            uint32_t opaque;
-            uint64_t cas;
-        } request;
-        uint8_t bytes[24];
-    } protocol_binary_request_header;
-
-    /**
-     * Definition of the header structure for a response packet.
-     * See section 2
-     */
-    typedef union {
-        struct {
-            uint8_t magic;
-            uint8_t opcode;
-            uint16_t keylen;
-            uint8_t extlen;
-            uint8_t datatype;
-            uint16_t status;
-            uint32_t bodylen;
-            uint32_t opaque;
-            uint64_t cas;
-        } response;
-        uint8_t bytes[24];
-    } protocol_binary_response_header;
-
-    /**
-     * Definition of a request-packet containing no extras
-     */
-    union protocol_binary_request_no_extras {
-        struct {
-            protocol_binary_request_header header;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header)];
-    };
-    typedef union protocol_binary_request_no_extras protocol_binary_request_no_extras;
-
-    /**
-     * Definition of a response-packet containing no extras
-     */
-    typedef union {
-        struct {
-            protocol_binary_response_header header;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_response_header)];
-    } protocol_binary_response_no_extras;
-
-    /**
-     * Definition of the packet used by the get, getq, getk and getkq command.
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_get;
-    typedef protocol_binary_request_no_extras protocol_binary_request_getq;
-    typedef protocol_binary_request_no_extras protocol_binary_request_getk;
-    typedef protocol_binary_request_no_extras protocol_binary_request_getkq;
-
-    /**
-     * Definition of the packet returned from a successful get, getq, getk and
-     * getkq.
-     * See section 4
-     */
-    typedef union {
-        struct {
-            protocol_binary_response_header header;
-            struct {
-                uint32_t flags;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_response_header) + 4];
-    } protocol_binary_response_get;
-
-    typedef protocol_binary_response_get protocol_binary_response_getq;
-    typedef protocol_binary_response_get protocol_binary_response_getk;
-    typedef protocol_binary_response_get protocol_binary_response_getkq;
-
-    /**
-     * Definition of the packet used by the delete command
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_delete;
-
-    /**
-     * Definition of the packet returned by the delete command
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_delete;
-
-    /**
-     * Definition of the packet used by the flush command
-     * See section 4
-     * Please note that the expiration field is optional, so remember to see
-     * check the header.bodysize to see if it is present.
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                uint32_t expiration;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
-    } protocol_binary_request_flush;
-
-    /**
-     * Definition of the packet returned by the flush command
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_flush;
-
-    /**
-     * Definition of the packet used by set, add and replace
-     * See section 4
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                uint32_t flags;
-                uint32_t expiration;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
-    } protocol_binary_request_set;
-    typedef protocol_binary_request_set protocol_binary_request_add;
-    typedef protocol_binary_request_set protocol_binary_request_replace;
-
-    /**
-     * Definition of the packet returned by set, add and replace
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_set;
-    typedef protocol_binary_response_no_extras protocol_binary_response_add;
-    typedef protocol_binary_response_no_extras protocol_binary_response_replace;
-
-    /**
-     * Definition of the noop packet
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_noop;
-
-    /**
-     * Definition of the packet returned by the noop command
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_noop;
-
-    /**
-     * Definition of the structure used by the increment and decrement
-     * command.
-     * See section 4
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                uint64_t delta;
-                uint64_t initial;
-                uint32_t expiration;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 20];
-    } protocol_binary_request_incr;
-    typedef protocol_binary_request_incr protocol_binary_request_decr;
-
-    /**
-     * Definition of the response from an incr or decr command
-     * command.
-     * See section 4
-     */
-    typedef union {
-        struct {
-            protocol_binary_response_header header;
-            struct {
-                uint64_t value;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_response_header) + 8];
-    } protocol_binary_response_incr;
-    typedef protocol_binary_response_incr protocol_binary_response_decr;
-
-    /**
-     * Definition of the quit
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_quit;
-
-    /**
-     * Definition of the packet returned by the quit command
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_quit;
-
-    /**
-     * Definition of the packet used by append and prepend command
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_append;
-    typedef protocol_binary_request_no_extras protocol_binary_request_prepend;
-
-    /**
-     * Definition of the packet returned from a successful append or prepend
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_append;
-    typedef protocol_binary_response_no_extras protocol_binary_response_prepend;
-
-    /**
-     * Definition of the packet used by the version command
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_version;
-
-    /**
-     * Definition of the packet returned from a successful version command
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_version;
-
-
-    /**
-     * Definition of the packet used by the stats command.
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_stats;
-
-    /**
-     * Definition of the packet returned from a successful stats command
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_stats;
-
-    /**
-     * Definition of the packet used by the verbosity command
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                uint32_t level;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
-    } protocol_binary_request_verbosity;
-
-    /**
-     * Definition of the packet returned from the verbosity command
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_verbosity;
-
-    /**
-     * Definition of the packet used by the touch command.
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                uint32_t expiration;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
-    } protocol_binary_request_touch;
-
-    /**
-     * Definition of the packet returned from the touch command
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_touch;
-
-    /**
-     * Definition of the packet used by the GAT(Q) command.
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                uint32_t expiration;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
-    } protocol_binary_request_gat;
-
-    typedef protocol_binary_request_gat protocol_binary_request_gatq;
-
-    /**
-     * Definition of the packet returned from the GAT(Q)
-     */
-    typedef protocol_binary_response_get protocol_binary_response_gat;
-    typedef protocol_binary_response_get protocol_binary_response_gatq;
-
-
-    /**
-     * Definition of a request for a range operation.
-     * See http://code.google.com/p/memcached/wiki/RangeOps
-     *
-     * These types are used for range operations and exist within
-     * this header for use in other projects.  Range operations are
-     * not expected to be implemented in the memcached server itself.
-     */
-    typedef union {
-        struct {
-            protocol_binary_response_header header;
-            struct {
-                uint16_t size;
-                uint8_t  reserved;
-                uint8_t  flags;
-                uint32_t max_results;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
-    } protocol_binary_request_rangeop;
-
-    typedef protocol_binary_request_rangeop protocol_binary_request_rget;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rset;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rsetq;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rappend;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rappendq;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rprepend;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rprependq;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rdelete;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rdeleteq;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rincr;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rincrq;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rdecr;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rdecrq;
-
-
-    /**
-     * Definition of tap commands
-     * See To be written
-     *
-     */
-
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                /**
-                 * flags is a bitmask used to set properties for the
-                 * the connection. Please In order to be forward compatible
-                 * you should set all undefined bits to 0.
-                 *
-                 * If the bit require extra userdata, it will be stored
-                 * in the user-data field of the body (passed to the engine
-                 * as enginespeciffic). That means that when you parse the
-                 * flags and the engine-specific data, you have to work your
-                 * way from bit 0 and upwards to find the correct offset for
-                 * the data.
-                 *
-                 */
-                uint32_t flags;
-
-                /**
-                 * Backfill age
-                 *
-                 * By using this flag you can limit the amount of data being
-                 * transmitted. If you don't specify a backfill age, the
-                 * server will transmit everything it contains.
-                 *
-                 * The first 8 bytes in the engine specific data contains
-                 * the oldest entry (from epoc) you're interested in.
-                 * Specifying a time in the future (for the server you are
-                 * connecting to), will cause it to start streaming current
-                 * changes.
-                 */
-#define TAP_CONNECT_FLAG_BACKFILL 0x01
-                /**
-                 * Dump will cause the server to send the data stored on the
-                 * server, but disconnect when the keys stored in the server
-                 * are transmitted.
-                 */
-#define TAP_CONNECT_FLAG_DUMP 0x02
-                /**
-                 * The body contains a list of 16 bits words in network byte
-                 * order specifying the vbucket ids to monitor. The first 16
-                 * bit word contains the number of buckets. The number of 0
-                 * means "all buckets"
-                 */
-#define TAP_CONNECT_FLAG_LIST_VBUCKETS 0x04
-                /**
-                 * The responsibility of the vbuckets is to be transferred
-                 * over to the caller when all items are transferred.
-                 */
-#define TAP_CONNECT_FLAG_TAKEOVER_VBUCKETS 0x08
-                /**
-                 * The tap consumer supports ack'ing of tap messages
-                 */
-#define TAP_CONNECT_SUPPORT_ACK 0x10
-                /**
-                 * The tap consumer would prefer to just get the keys
-                 * back. If the engine supports this it will set
-                 * the TAP_FLAG_NO_VALUE flag in each of the
-                 * tap packets returned.
-                 */
-#define TAP_CONNECT_REQUEST_KEYS_ONLY 0x20
-                /**
-                 * The body contains a list of (vbucket_id, last_checkpoint_id)
-                 * pairs. This provides the checkpoint support in TAP streams.
-                 * The last checkpoint id represents the last checkpoint that
-                 * was successfully persisted.
-                 */
-#define TAP_CONNECT_CHECKPOINT 0x40
-                /**
-                 * The tap consumer is a registered tap client, which means that
-                 * the tap server will maintain its checkpoint cursor permanently.
-                 */
-#define TAP_CONNECT_REGISTERED_CLIENT 0x80
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
-    } protocol_binary_request_tap_connect;
-
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                struct {
-                    uint16_t enginespecific_length;
-                    /*
-                     * The flag section support the following flags
-                     */
-                    /**
-                     * Request that the consumer send a response packet
-                     * for this packet. The opaque field must be preserved
-                     * in the response.
-                     */
-#define TAP_FLAG_ACK 0x01
-                    /**
-                     * The value for the key is not included in the packet
-                     */
-#define TAP_FLAG_NO_VALUE 0x02
-                    uint16_t flags;
-                    uint8_t  ttl;
-                    uint8_t  res1;
-                    uint8_t  res2;
-                    uint8_t  res3;
-                } tap;
-                struct {
-                    uint32_t flags;
-                    uint32_t expiration;
-                } item;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 16];
-    } protocol_binary_request_tap_mutation;
-
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                struct {
-                    uint16_t enginespecific_length;
-                    /**
-                     * See the definition of the flags for
-                     * protocol_binary_request_tap_mutation for a description
-                     * of the available flags.
-                     */
-                    uint16_t flags;
-                    uint8_t  ttl;
-                    uint8_t  res1;
-                    uint8_t  res2;
-                    uint8_t  res3;
-                } tap;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
-    } protocol_binary_request_tap_no_extras;
-
-    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_delete;
-    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_flush;
-    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_opaque;
-    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_vbucket_set;
-
-
-    /**
-     * Definition of the packet used by the scrub.
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_scrub;
-
-    /**
-     * Definition of the packet returned from scrub.
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_scrub;
-
-
-    /**
-     * Definition of the packet used by set vbucket
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                vbucket_state_t state;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + sizeof(vbucket_state_t)];
-    } protocol_binary_request_set_vbucket;
-    /**
-     * Definition of the packet returned from set vbucket
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_set_vbucket;
-    /**
-     * Definition of the packet used by del vbucket
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_del_vbucket;
-    /**
-     * Definition of the packet returned from del vbucket
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_del_vbucket;
-
-    /**
-     * Definition of the packet used by get vbucket
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_get_vbucket;
-
-    /**
-     * Definition of the packet returned from get vbucket
-     */
-    typedef union {
-        struct {
-            protocol_binary_response_header header;
-            struct {
-                vbucket_state_t state;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_response_header) + sizeof(vbucket_state_t)];
-    } protocol_binary_response_get_vbucket;
-
-
-    /**
-     * @}
-     */
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* PROTOCOL_BINARY_H */
diff --git a/libmemcached/memcached/vbucket.h b/libmemcached/memcached/vbucket.h
deleted file mode 100644 (file)
index e2cc563..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-typedef enum {
-    vbucket_state_active = 1, /**< Actively servicing a vbucket. */
-    vbucket_state_replica, /**< Servicing a vbucket as a replica only. */
-    vbucket_state_pending, /**< Pending active. */
-    vbucket_state_dead /**< Not in use, pending deletion. */
-} vbucket_state_t;
-
-#define is_valid_vbucket_state_t(state) \
-    (state == vbucket_state_active || \
-     state == vbucket_state_replica || \
-     state == vbucket_state_pending || \
-     state == vbucket_state_dead)
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached/memory.h b/libmemcached/memory.h
deleted file mode 100644 (file)
index 12d0284..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <mem_config.h>
-
-#include <libmemcached/common.h>
-
-#ifdef __cplusplus
-#include <cstddef>
-#include <cstdlib>
-#else
-#include <stddef.h>
-#include <stdlib.h>
-#endif
-
-static inline void libmemcached_free(const memcached_st *self, void *mem)
-{
-  if (self)
-  {
-    self->allocators.free(self, mem, self->allocators.context);
-  }
-  else if (mem)
-  {
-#ifdef __cplusplus
-    std::free(mem);
-#else
-    free(mem);
-#endif
-  }
-}
-
-static inline void *libmemcached_malloc(const memcached_st *self, const size_t size)
-{
-  if (self)
-  {
-    return self->allocators.malloc(self, size, self->allocators.context);
-  }
-
-#ifdef __cplusplus
-  return std::malloc(size);
-#else
-  return malloc(size);
-#endif
-}
-#define libmemcached_xmalloc(__memcachd_st, __type) ((__type *)libmemcached_malloc((__memcachd_st), sizeof(__type)))
-
-static inline void *libmemcached_realloc(const memcached_st *self, void *mem, size_t nmemb,  const size_t size)
-{
-  if (self)
-  {
-    return self->allocators.realloc(self, mem, nmemb * size, self->allocators.context);
-  }
-
-#ifdef __cplusplus
-    return std::realloc(mem, size);
-#else
-    return realloc(mem, size);
-#endif
-}
-#define libmemcached_xrealloc(__memcachd_st, __mem, __nelem, __type) ((__type *)libmemcached_realloc((__memcachd_st), (__mem), (__nelem), sizeof(__type)))
-#define libmemcached_xvalloc(__memcachd_st, __nelem, __type) ((__type *)libmemcached_realloc((__memcachd_st), NULL, (__nelem), sizeof(__type)))
-
-static inline void *libmemcached_calloc(const memcached_st *self, size_t nelem, size_t size)
-{
-  if (self)
-  {
-    return self->allocators.calloc(self, nelem, size, self->allocators.context);
-  }
-
-#ifdef __cplusplus
-    return std::calloc(nelem, size);
-#else
-    return calloc(nelem, size);
-#endif
-}
-#define libmemcached_xcalloc(__memcachd_st, __nelem, __type) ((__type *)libmemcached_calloc((__memcachd_st), (__nelem), sizeof(__type)))
diff --git a/libmemcached/namespace.cc b/libmemcached/namespace.cc
deleted file mode 100644 (file)
index 664ebc4..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libmemcached/common.h"
-#include "libmemcached/assert.hpp"
-
-memcached_return_t memcached_set_namespace(Memcached& memc, const char *key, size_t key_length)
-{
-  if (key and key_length == 0)
-  { 
-    WATCHPOINT_ASSERT(key_length);
-    return memcached_set_error(memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid namespace, namespace string had value but length was 0"));
-  }
-  else if (key_length and key == NULL)
-  {
-    WATCHPOINT_ASSERT(key);
-    return memcached_set_error(memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid namespace, namespace string length was > 1 but namespace string was null "));
-  }
-  else if (key and key_length)
-  {
-    bool orig= memc.flags.verify_key;
-    memc.flags.verify_key= true;
-    if (memcached_failed(memcached_key_test(memc, (const char **)&key, &key_length, 1)))
-    {
-      memc.flags.verify_key= orig;
-      return memcached_last_error(&memc);
-    }
-    memc.flags.verify_key= orig;
-
-    if ((key_length > MEMCACHED_PREFIX_KEY_MAX_SIZE -1))
-    {
-      return memcached_set_error(memc, MEMCACHED_KEY_TOO_BIG, MEMCACHED_AT);
-    }
-
-    memcached_array_free(memc._namespace);
-    memc._namespace= memcached_strcpy(&memc, key, key_length);
-
-    if (memc._namespace == NULL)
-    {
-      return memcached_set_error(memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-    }
-  }
-  else
-  {
-    memcached_array_free(memc._namespace);
-    memc._namespace= NULL;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-const char * memcached_get_namespace(Memcached& memc)
-{
-  if (memc._namespace == NULL)
-  {
-    return NULL;
-  }
-
-  return memcached_array_string(memc._namespace);
-}
diff --git a/libmemcached/namespace.h b/libmemcached/namespace.h
deleted file mode 100644 (file)
index 0c98ce4..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-
-memcached_return_t memcached_set_namespace(Memcached&, const char *str, size_t length);
-
-const char * memcached_get_namespace(Memcached&);
-
-#endif // __cplusplus
diff --git a/libmemcached/options.cc b/libmemcached/options.cc
deleted file mode 100644 (file)
index 290cfc8..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-#include <libmemcached/options.hpp>
-
-#include <libmemcached/csl/context.h>
-
-const char *memcached_parse_filename(memcached_st *memc)
-{
-  assert_msg(memc, "Invalid memcached_st");
-  return memcached_array_string(memc->configure.filename);
-}
-
-size_t memcached_parse_filename_length(memcached_st *memc)
-{
-  return memcached_array_size(memc->configure.filename);
-}
-
-static memcached_return_t _parse_file_options(memcached_st& self, memcached_array_st *real_name)
-{
-  FILE *fp= fopen(memcached_array_string(real_name), "r");
-  if (not fp)
-  {
-    memcached_string_t error_message= memcached_array_to_string(real_name);
-    memcached_return_t rc=  memcached_set_errno(self, errno, MEMCACHED_AT, error_message);
-    return rc;
-  }
-
-  char buffer[BUFSIZ];
-  memcached_return_t rc= MEMCACHED_INVALID_ARGUMENTS;
-  while (fgets(buffer, sizeof(buffer), fp))
-  {
-    size_t length= strlen(buffer);
-    
-    if (length == 1 and buffer[0] == '\n')
-      continue;
-
-    if (memcached_failed(rc= memcached_parse_configuration(&self, buffer, length)))
-      break;
-  }
-  fclose(fp);
-
-  return rc;
-}
-
-memcached_return_t libmemcached_check_configuration(const char *option_string, size_t length, char *error_buffer, size_t error_buffer_size)
-{
-  memcached_st memc, *memc_ptr;
-
-  if (option_string == NULL or length == 0)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  if (error_buffer and error_buffer_size)
-  {
-    error_buffer[0]= 0;
-  }
-
-  if (not (memc_ptr= memcached_create(&memc)))
-  {
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-  }
-
-  memcached_return_t rc= memcached_parse_configuration(memc_ptr, option_string, length);
-  if (memcached_failed(rc) and error_buffer and error_buffer_size)
-  {
-    strncpy(error_buffer, memcached_last_error_message(memc_ptr), error_buffer_size);
-    error_buffer[error_buffer_size -1]= 0;
-  }
-
-  bool has_filename= memcached_behavior_get(memc_ptr, MEMCACHED_BEHAVIOR_LOAD_FROM_FILE);
-  if (memcached_success(rc) and has_filename)
-  {
-    assert_msg(memcached_parse_filename(memc_ptr), "Invalid configuration file");
-    assert_msg(memcached_parse_filename_length(memc_ptr), "Invalid configuration file");
-    rc= _parse_file_options(*memc_ptr, memc_ptr->configure.filename);
-
-    if (memcached_failed(rc) and error_buffer and error_buffer_size)
-    {
-      strncpy(error_buffer, memcached_last_error_message(memc_ptr), error_buffer_size);
-      error_buffer[error_buffer_size -1]= 0;
-    }
-  }
-
-  memcached_free(memc_ptr);
-
-  return rc;
-}
-
-memcached_return_t memcached_parse_configuration(memcached_st *self, char const *option_string, size_t length)
-{
-  WATCHPOINT_ASSERT(self);
-  if (not self)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  memcached_return_t rc;
-  Context context(option_string, length, self, rc);
-
-  context.start();
-
-  return rc;
-}
-
-void memcached_set_configuration_file(memcached_st *self, const char *filename, size_t filename_length)
-{
-  assert_msg(filename, "Invalid filename");
-  assert_msg(filename_length, "Invalid filename_length");
-  memcached_array_free(self->configure.filename);
-  self->configure.filename= memcached_strcpy(self, filename, filename_length);
-}
-
-memcached_return_t memcached_parse_configure_file(memcached_st& self, const char *filename, size_t length)
-{
-  if (not filename)
-  {
-    return memcached_set_error(self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT);
-  }
-
-  WATCHPOINT_ASSERT(self);
-  if (not length)
-  {
-    return memcached_set_error(self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT);
-  }
-
-  memcached_array_st *tmp_array= memcached_strcpy(&self, filename, length);
-
-  if (not tmp_array)
-  {
-    return memcached_set_error(self, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-  }
-
-  memcached_return_t rc= memcached_parse_configure_file(self, *tmp_array);
-  memcached_array_free(tmp_array);
-
-  return rc;
-}
-
-memcached_return_t memcached_parse_configure_file(memcached_st& self, memcached_array_st& filename)
-{
-  WATCHPOINT_ASSERT(memcached_array_size(&filename));
-  if (not memcached_array_size(&filename))
-  {
-    return memcached_set_error(self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT);
-  }
-
-  return _parse_file_options(self, &filename);
-}
diff --git a/libmemcached/options.hpp b/libmemcached/options.hpp
deleted file mode 100644 (file)
index bc71732..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-LIBMEMCACHED_LOCAL
-  void memcached_set_configuration_file(memcached_st *self, const char *filename, size_t filename_length);
-
-LIBMEMCACHED_LOCAL
-  const char *memcached_parse_filename(memcached_st *memc);
-
-LIBMEMCACHED_LOCAL
-  memcached_return_t memcached_parse_configuration(memcached_st *ptr, const char *option_string, size_t length);
-
-LIBMEMCACHED_LOCAL
-  size_t memcached_parse_filename_length(memcached_st *memc);
-
-LIBMEMCACHED_LOCAL
-  memcached_return_t memcached_parse_configure_file(memcached_st&, const char *filename, size_t length);
-
-LIBMEMCACHED_LOCAL
-  memcached_return_t memcached_parse_configure_file(memcached_st&, memcached_array_st& filename);
diff --git a/libmemcached/parse.cc b/libmemcached/parse.cc
deleted file mode 100644 (file)
index 7665b73..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* 
-  I debated about putting this in the client library since it does an 
-  action I don't really believe belongs in the library.
-
-  Frankly its too damn useful not to be here though.
-*/
-
-#include <libmemcached/common.h>
-
-memcached_server_list_st memcached_servers_parse(const char *server_strings)
-{
-  char *string;
-  const char *begin_ptr;
-  const char *end_ptr;
-  memcached_server_st *servers= NULL;
-  memcached_return_t rc;
-
-  WATCHPOINT_ASSERT(server_strings);
-
-  end_ptr= server_strings + strlen(server_strings);
-
-  for (begin_ptr= server_strings, string= (char *)index(server_strings, ','); 
-       begin_ptr != end_ptr; 
-       string= (char *)index(begin_ptr, ','))
-  {
-    char buffer[HUGE_STRING_LEN];
-    char *ptr, *ptr2;
-    uint32_t weight= 0;
-
-    if (string)
-    {
-      memcpy(buffer, begin_ptr, (size_t) (string - begin_ptr));
-      buffer[(unsigned int)(string - begin_ptr)]= 0;
-      begin_ptr= string+1;
-    }
-    else
-    {
-      size_t length= strlen(begin_ptr);
-      memcpy(buffer, begin_ptr, length);
-      buffer[length]= 0;
-      begin_ptr= end_ptr;
-    }
-
-    ptr= index(buffer, ':');
-
-    in_port_t port= 0;
-    if (ptr)
-    {
-      ptr[0]= 0;
-
-      ptr++;
-
-      errno= 0;
-      port= (in_port_t) strtoul(ptr, (char **)NULL, 10);
-      if (errno != 0)
-      {
-        memcached_server_free(servers);
-        return NULL;
-      }
-
-      ptr2= index(ptr, ' ');
-      if (! ptr2)
-        ptr2= index(ptr, ':');
-
-      if (ptr2)
-      {
-        ptr2++;
-        errno= 0;
-        weight= uint32_t(strtoul(ptr2, (char **)NULL, 10));
-        if (errno != 0)
-        {
-          memcached_server_free(servers);
-          return NULL;
-        }
-      }
-    }
-
-    servers= memcached_server_list_append_with_weight(servers, buffer, port, weight, &rc);
-
-    if (isspace(*begin_ptr))
-    {
-      begin_ptr++;
-    }
-  }
-
-  return servers;
-}
diff --git a/libmemcached/poll.cc b/libmemcached/poll.cc
deleted file mode 100644 (file)
index 6fdf242..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2013 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker, Trond Norbye
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Implementation of poll by using select
- *
- */
-
-#include "libmemcached/common.h"
-
-#if defined(_WIN32)
-#include "libmemcached/poll.h"
-
-#include <sys/time.h>
-#include <strings.h>
-
-int poll(struct pollfd fds[], nfds_t nfds, int tmo)
-{
-  fd_set readfds, writefds, errorfds;
-  FD_ZERO(&readfds);
-  FD_ZERO(&writefds);
-  FD_ZERO(&errorfds);
-
-  int maxfd= 0;
-
-  for (nfds_t x= 0; x < nfds; ++x)
-  {
-    if (fds[x].events & (POLLIN | POLLOUT))
-    {
-#ifndef _WIN32
-      if (fds[x].fd > maxfd)
-      {
-        maxfd= fds[x].fd;
-      }
-#endif
-      if (fds[x].events & POLLIN)
-      {
-        FD_SET(fds[x].fd, &readfds);
-      }
-      if (fds[x].events & POLLOUT)
-      {
-        FD_SET(fds[x].fd, &writefds);
-      }
-    }
-  }
-
-  struct timeval timeout= { .tv_sec = tmo / 1000,
-                            .tv_usec= (tmo % 1000) * 1000 };
-  struct timeval *tp= &timeout;
-  if (tmo == -1)
-  {
-    tp= NULL;
-  }
-  int ret= select(maxfd + 1, &readfds, &writefds, &errorfds, tp);
-  if (ret <= 0)
-  {
-    return ret;
-  }
-
-  /* Iterate through all of them because I need to clear the revent map */
-  for (nfds_t x= 0; x < nfds; ++x)
-  {
-    fds[x].revents= 0;
-    if (FD_ISSET(fds[x].fd, &readfds))
-    {
-      fds[x].revents |= POLLIN;
-    }
-    if (FD_ISSET(fds[x].fd, &writefds))
-    {
-      fds[x].revents |= POLLOUT;
-    }
-    if (FD_ISSET(fds[x].fd, &errorfds))
-    {
-      fds[x].revents |= POLLERR;
-    }
-  }
-
-   return ret;
-}
-
-#endif // defined(_WIN32)
diff --git a/libmemcached/poll.h b/libmemcached/poll.h
deleted file mode 100644 (file)
index 46636c4..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2013 Data Differential, http://datadifferential.com/
- * Copyright (C) 2010 Brian Aker, Trond Norbye
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Implementation of poll by using select
- *
- */
-
-#pragma once
-
-#if defined(_WIN32)
-
-#include <winsock2.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct pollfd
-{
-#if defined(_WIN32)
-  SOCKET fd;
-#else
-  int fd;
-#endif
-  short events;
-  short revents;
-} pollfd_t;
-
-typedef int nfds_t;
-
-#define POLLIN 0x0001
-#define POLLOUT 0x0004
-#define POLLERR 0x0008
-#define POLLHUP                0x010           /* Hung up.  */
-#define POLLNVAL       0x020           /* Invalid polling request.  */
-
-int poll(struct pollfd fds[], nfds_t nfds, int tmo);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // defined(_WIN32)
diff --git a/libmemcached/purge.cc b/libmemcached/purge.cc
deleted file mode 100644 (file)
index 4dbe24d..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libmemcached/common.h>
-
-#define memcached_set_purging(__object, __value) ((__object)->state.is_purging= (__value))
-
-class Purge
-{
-public:
-  Purge(Memcached* arg) :
-    _memc(arg)
-  {
-    memcached_set_purging(_memc, true);
-  }
-
-  ~Purge()
-  {
-    memcached_set_purging(_memc, false);
-  }
-
-private:
-  Memcached* _memc;
-};
-
-class PollTimeout
-{
-public:
-  PollTimeout(Memcached* arg) :
-    _timeout(arg->poll_timeout),
-    _origin(arg->poll_timeout)
-  {
-    _origin = 2000;
-  }
-
-  ~PollTimeout()
-  {
-    _origin= _timeout;
-  }
-
-private:
-  int32_t _timeout;
-  int32_t& _origin;
-};
-
-bool memcached_purge(memcached_instance_st* ptr)
-{
-  Memcached *root= (Memcached *)ptr->root;
-
-  if (memcached_is_purging(ptr->root) || /* already purging */
-      (memcached_server_response_count(ptr) < ptr->root->io_msg_watermark &&
-       ptr->io_bytes_sent < ptr->root->io_bytes_watermark) ||
-      (ptr->io_bytes_sent >= ptr->root->io_bytes_watermark &&
-       memcached_server_response_count(ptr) < 2))
-  {
-    return true;
-  }
-
-  /*
-    memcached_io_write and memcached_response may call memcached_purge
-    so we need to be able stop any recursion.. 
-  */
-  Purge set_purge(root);
-
-  WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
-  /* 
-    Force a flush of the buffer to ensure that we don't have the n-1 pending
-    requests buffered up.. 
-  */
-  if (memcached_io_write(ptr) == false)
-  {
-    memcached_io_reset(ptr);
-    memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
-    return false;
-  }
-  WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
-
-  bool is_successful= true;
-  uint32_t no_msg= memcached_server_response_count(ptr);
-  if (no_msg > 1)
-  {
-    memcached_result_st result;
-
-    /*
-     * We need to increase the timeout, because we might be waiting for
-     * data to be sent from the server (the commands was in the output buffer
-     * and just flushed
-   */
-    PollTimeout poll_timeout(ptr->root);
-
-    memcached_result_st* result_ptr= memcached_result_create(root, &result);
-    assert(result_ptr);
-
-    for (uint32_t x= 0; x < no_msg - 1; x++)
-    {
-      memcached_result_reset(result_ptr);
-      memcached_return_t rc= memcached_read_one_response(ptr, result_ptr);
-      /*
-       * Purge doesn't care for what kind of command results that is received.
-       * The only kind of errors I care about if is I'm out of sync with the
-       * protocol or have problems reading data from the network..
-     */
-      if (rc== MEMCACHED_PROTOCOL_ERROR or rc == MEMCACHED_UNKNOWN_READ_FAILURE or rc == MEMCACHED_READ_FAILURE)
-      {
-        WATCHPOINT_ERROR(rc);
-        is_successful= false;
-      }
-
-      if (ptr->root->callbacks != NULL)
-      {
-        memcached_callback_st cb = *ptr->root->callbacks;
-        if (memcached_success(rc))
-        {
-          for (uint32_t y= 0; y < cb.number_of_callback; y++)
-          {
-            if (memcached_fatal((*cb.callback[y])(ptr->root, result_ptr, cb.context)))
-            {
-              break;
-            }
-          }
-        }
-      }
-    }
-
-    memcached_result_free(result_ptr);
-  }
-
-  return is_successful;
-}
diff --git a/libmemcached/quit.cc b/libmemcached/quit.cc
deleted file mode 100644 (file)
index 5d17b31..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-namespace {
-  memcached_return_t send_quit_message(memcached_instance_st* instance)
-  {
-    memcached_return_t rc;
-    if (instance->root->flags.binary_protocol)
-    {
-      protocol_binary_request_quit request= {}; // = {.bytes= {0}};
-
-      initialize_binary_request(instance, request.message.header);
-
-      request.message.header.request.opcode = PROTOCOL_BINARY_CMD_QUIT;
-      request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
-
-      libmemcached_io_vector_st vector[]=
-      {
-        { request.bytes, sizeof(request.bytes) }
-      };
-
-      rc= memcached_vdo(instance, vector, 1, true);
-    }
-    else
-    {
-      libmemcached_io_vector_st vector[]=
-      {
-        { memcached_literal_param("quit\r\n") }
-      };
-
-      rc= memcached_vdo(instance, vector, 1, true);
-    }
-
-    return rc;
-  }
-
-  void drain_instance(memcached_instance_st* instance)
-  {
-    /* read until socket is closed, or there is an error
-     * closing the socket before all data is read
-     * results in server throwing away all data which is
-     * not read
-     *
-     * In .40 we began to only do this if we had been doing buffered
-     * requests of had replication enabled.
-     */
-    if (instance->root->flags.buffer_requests or instance->root->number_of_replicas)
-    {
-      memcached_io_slurp(instance);
-    }
-
-    /*
-     * memcached_io_read may call memcached_quit_server with io_death if
-     * it encounters problems, but we don't care about those occurences.
-     * The intention of that loop is to drain the data sent from the
-     * server to ensure that the server processed all of the data we
-     * sent to the server.
-     */
-    instance->server_failure_counter= 0;
-    instance->server_timeout_counter= 0;
-  }
-}
-
-/*
-  This closes all connections (forces flush of input as well).
-
-  Maybe add a host specific, or key specific version?
-
-  The reason we send "quit" is that in case we have buffered IO, this
-  will force data to be completed.
-*/
-
-void memcached_quit_server(memcached_instance_st* instance, bool io_death)
-{
-  if (instance->valid())
-  {
-    if (io_death == false and memcached_is_udp(instance->root) == false and instance->is_shutting_down() == false)
-    {
-      send_quit_message(instance);
-
-      instance->start_close_socket();
-      drain_instance(instance);
-    }
-  }
-
-  instance->close_socket();
-
-  if (io_death and memcached_is_udp(instance->root))
-  {
-    /*
-       If using UDP, we should stop using the server briefly on every IO
-       failure. If using TCP, it may be that the connection went down a
-       short while ago (e.g. the server failed) and we've only just
-       noticed, so we should only set the retry timeout on a connect
-       failure (which doesn't call this method).
-       */
-    memcached_mark_server_for_timeout(instance);
-  }
-}
-
-void send_quit(Memcached *memc)
-{
-  for (uint32_t x= 0; x < memcached_server_count(memc); x++)
-  {
-    memcached_instance_st* instance= memcached_instance_fetch(memc, x);
-
-    memcached_quit_server(instance, false);
-  }
-}
-
-void memcached_quit(memcached_st *shell)
-{
-  Memcached* memc= memcached2Memcached(shell);
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(memc, true)))
-  {
-    return;
-  }
-
-  send_quit(memc);
-}
diff --git a/libmemcached/quit.hpp b/libmemcached/quit.hpp
deleted file mode 100644 (file)
index a48a8a7..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-void memcached_quit_server(memcached_instance_st* ptr, bool io_death);
-
-void send_quit(memcached_st *ptr);
diff --git a/libmemcached/response.cc b/libmemcached/response.cc
deleted file mode 100644 (file)
index 3d1e764..0000000
+++ /dev/null
@@ -1,940 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-#include <libmemcached/string.hpp>
-
-static memcached_return_t textual_value_fetch(memcached_instance_st* instance,
-                                              char *buffer,
-                                              memcached_result_st *result)
-{
-  char *next_ptr;
-  ssize_t read_length= 0;
-  size_t value_length;
-
-  WATCHPOINT_ASSERT(instance->root);
-  char *end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
-
-  memcached_result_reset(result);
-
-  char *string_ptr= buffer;
-  string_ptr+= 6; /* "VALUE " */
-
-
-  // Just used for cases of AES decrypt currently
-  memcached_return_t rc= MEMCACHED_SUCCESS;
-
-  /* We load the key */
-  {
-    char *key= result->item_key;
-    result->key_length= 0;
-
-    for (ptrdiff_t prefix_length= memcached_array_size(instance->root->_namespace); !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
-    {
-      if (prefix_length == 0)
-      {
-        *key= *string_ptr;
-        key++;
-        result->key_length++;
-      }
-      else
-        prefix_length--;
-    }
-    result->item_key[result->key_length]= 0;
-  }
-
-  if (end_ptr == string_ptr)
-  {
-    goto read_error;
-  }
-
-  /* Flags fetch move past space */
-  string_ptr++;
-  if (end_ptr == string_ptr)
-  {
-    goto read_error;
-  }
-
-  for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
-  errno= 0;
-  result->item_flags= (uint32_t) strtoul(next_ptr, &string_ptr, 10);
-
-  if (errno != 0 or end_ptr == string_ptr)
-  {
-    goto read_error;
-  }
-
-  /* Length fetch move past space*/
-  string_ptr++;
-  if (end_ptr == string_ptr)
-  {
-    goto read_error;
-  }
-
-  for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
-  errno= 0;
-  value_length= (size_t)strtoull(next_ptr, &string_ptr, 10);
-
-  if (errno != 0 or end_ptr == string_ptr)
-  {
-    goto read_error;
-  }
-
-  /* Skip spaces */
-  if (*string_ptr == '\r')
-  {
-    /* Skip past the \r\n */
-    string_ptr+= 2;
-  }
-  else
-  {
-    string_ptr++;
-    for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
-    errno= 0;
-    result->item_cas= strtoull(next_ptr, &string_ptr, 10);
-  }
-
-  if (errno != 0 or end_ptr < string_ptr)
-  {
-    goto read_error;
-  }
-
-  /* We add two bytes so that we can walk the \r\n */
-  if (memcached_failed(memcached_string_check(&result->value, value_length +2)))
-  {
-    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-  }
-
-  {
-    char *value_ptr= memcached_string_value_mutable(&result->value);
-    /*
-      We read the \r\n into the string since not doing so is more
-      cycles then the waster of memory to do so.
-
-      We are null terminating through, which will most likely make
-      some people lazy about using the return length.
-    */
-    size_t to_read= (value_length) + 2;
-    memcached_return_t rrc= memcached_io_read(instance, value_ptr, to_read, read_length);
-    if (memcached_failed(rrc) and rrc == MEMCACHED_IN_PROGRESS)
-    {
-      memcached_quit_server(instance, true);
-      return memcached_set_error(*instance, MEMCACHED_IN_PROGRESS, MEMCACHED_AT);
-    }
-    else if (memcached_failed(rrc))
-    {
-      return rrc;
-    }
-  }
-
-  if (read_length != (ssize_t)(value_length + 2))
-  {
-    goto read_error;
-  }
-
-  /* This next bit blows the API, but this is internal....*/
-  {
-    char *char_ptr;
-    char_ptr= memcached_string_value_mutable(&result->value);;
-    char_ptr[value_length]= 0;
-    char_ptr[value_length +1]= 0;
-    memcached_string_set_length(&result->value, value_length);
-  }
-
-  if (memcached_is_encrypted(instance->root) and memcached_result_length(result))
-  {
-    hashkit_string_st *destination;
-
-    if ((destination= hashkit_decrypt(&instance->root->hashkit,
-                                      memcached_result_value(result), memcached_result_length(result))) == NULL)
-    {
-      rc= memcached_set_error(*instance->root, MEMCACHED_FAILURE, 
-                              MEMCACHED_AT, memcached_literal_param("hashkit_decrypt() failed"));
-    }
-    else
-    {
-      memcached_result_reset_value(result);
-      if (memcached_failed(memcached_result_set_value(result, hashkit_string_c_str(destination), hashkit_string_length(destination))))
-      {
-        rc= memcached_set_error(*instance->root, MEMCACHED_FAILURE, 
-                                MEMCACHED_AT, memcached_literal_param("hashkit_decrypt() failed"));
-      }
-    }
-
-    if (memcached_failed(rc))
-    {
-      memcached_result_reset(result);
-    }
-    hashkit_string_free(destination);
-  }
-
-  return rc;
-
-read_error:
-  memcached_io_reset(instance);
-
-  return MEMCACHED_PARTIAL_READ;
-}
-
-static memcached_return_t textual_read_one_response(memcached_instance_st* instance,
-                                                    char *buffer, const size_t buffer_length,
-                                                    memcached_result_st *result)
-{
-  size_t total_read;
-  memcached_return_t rc= memcached_io_readline(instance, buffer, buffer_length, total_read);
-
-  if (memcached_failed(rc))
-  {
-    return rc;
-  }
-  assert(total_read);
-
-  switch(buffer[0])
-  {
-  case 'V':
-    {
-      // VALUE
-      if (buffer[1] == 'A' and buffer[2] == 'L' and buffer[3] == 'U' and buffer[4] == 'E') /* VALUE */
-      {
-        /* We add back in one because we will need to search for END */
-        memcached_server_response_increment(instance);
-        return textual_value_fetch(instance, buffer, result);
-      }
-      // VERSION
-      else if (buffer[1] == 'E' and buffer[2] == 'R' and buffer[3] == 'S' and buffer[4] == 'I' and buffer[5] == 'O' and buffer[6] == 'N') /* VERSION */
-      {
-        /* Find the space, and then move one past it to copy version */
-        char *response_ptr= index(buffer, ' ');
-
-        char *endptr;
-        errno= 0;
-        long int version= strtol(response_ptr, &endptr, 10);
-        if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX or version == 0)
-        {
-          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
-          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version"));
-        }
-        instance->major_version= uint8_t(version);
-
-        endptr++;
-        errno= 0;
-        version= strtol(endptr, &endptr, 10);
-        if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX)
-        {
-          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
-          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse minor version"));
-        }
-        instance->minor_version= uint8_t(version);
-
-        endptr++;
-        errno= 0;
-        version= strtol(endptr, &endptr, 10);
-        if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX)
-        {
-          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
-          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
-        }
-        instance->micro_version= uint8_t(version);
-
-        return MEMCACHED_SUCCESS;
-      }
-    }
-    break;
-
-  case 'O':
-    {
-      // OK
-      if (buffer[1] == 'K')
-      {
-        return MEMCACHED_SUCCESS;
-      }
-    }
-    break;
-
-  case 'S':
-    {
-      // STAT
-      if (buffer[1] == 'T' and buffer[2] == 'A' and buffer[3] == 'T') /* STORED STATS */
-      {
-        memcached_server_response_increment(instance);
-        return MEMCACHED_STAT;
-      }
-      // SERVER_ERROR
-      else if (buffer[1] == 'E' and buffer[2] == 'R' and buffer[3] == 'V' and buffer[4] == 'E' and buffer[5] == 'R'
-               and buffer[6] == '_' 
-               and buffer[7] == 'E' and buffer[8] == 'R' and buffer[9] == 'R' and buffer[10] == 'O' and buffer[11] == 'R' )
-      {
-        if (total_read == memcached_literal_param_size("SERVER_ERROR"))
-        {
-          return MEMCACHED_SERVER_ERROR;
-        }
-
-        if (total_read >= memcached_literal_param_size("SERVER_ERROR object too large for cache") and
-            (memcmp(buffer, memcached_literal_param("SERVER_ERROR object too large for cache")) == 0))
-        {
-          return MEMCACHED_E2BIG;
-        }
-
-        if (total_read >= memcached_literal_param_size("SERVER_ERROR out of memory") and
-            ((memcmp(buffer, memcached_literal_param("SERVER_ERROR out of memory")) == 0) or
-                (memcmp(buffer, memcached_literal_param("SERVER_ERROR Out of memory")) == 0)))
-        {
-          return MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE;
-        }
-
-        // Move past the basic error message and whitespace
-        char *startptr= buffer + memcached_literal_param_size("SERVER_ERROR");
-        if (startptr[0] == ' ')
-        {
-          startptr++;
-        }
-
-        char *endptr= startptr;
-        while (*endptr != '\r' && *endptr != '\n') endptr++;
-
-        return memcached_set_error(*instance, MEMCACHED_SERVER_ERROR, MEMCACHED_AT, startptr, size_t(endptr - startptr));
-      }
-      // STORED
-      else if (buffer[1] == 'T' and buffer[2] == 'O' and buffer[3] == 'R') //  and buffer[4] == 'E' and buffer[5] == 'D')
-      {
-        return MEMCACHED_STORED;
-      }
-    }
-    break;
-
-  case 'D':
-    {
-      // DELETED
-      if (buffer[1] == 'E' and buffer[2] == 'L' and buffer[3] == 'E' and buffer[4] == 'T' and buffer[5] == 'E' and buffer[6] == 'D')
-      {
-        return MEMCACHED_DELETED;
-      }
-    }
-    break;
-
-  case 'N':
-    {
-      // NOT_FOUND
-      if (buffer[1] == 'O' and buffer[2] == 'T' 
-          and buffer[3] == '_'
-          and buffer[4] == 'F' and buffer[5] == 'O' and buffer[6] == 'U' and buffer[7] == 'N' and buffer[8] == 'D')
-      {
-        return MEMCACHED_NOTFOUND;
-      }
-      // NOT_STORED
-      else if (buffer[1] == 'O' and buffer[2] == 'T' 
-               and buffer[3] == '_'
-               and buffer[4] == 'S' and buffer[5] == 'T' and buffer[6] == 'O' and buffer[7] == 'R' and buffer[8] == 'E' and buffer[9] == 'D')
-      {
-        return MEMCACHED_NOTSTORED;
-      }
-    }
-    break;
-
-  case 'E': /* PROTOCOL ERROR or END */
-    {
-      // END
-      if (buffer[1] == 'N' and buffer[2] == 'D')
-      {
-        return MEMCACHED_END;
-      }
-#if 0
-      // PROTOCOL_ERROR
-      else if (buffer[1] == 'R' and buffer[2] == 'O' and buffer[3] == 'T' and buffer[4] == 'O' and buffer[5] == 'C' and buffer[6] == 'O' and buffer[7] == 'L'
-               and buffer[8] == '_'
-               and buffer[9] == 'E' and buffer[10] == 'R' and buffer[11] == 'R' and buffer[12] == 'O' and buffer[13] == 'R')
-      {
-        return MEMCACHED_PROTOCOL_ERROR;
-      }
-#endif
-      // ERROR
-      else if (buffer[1] == 'R' and buffer[2] == 'R' and buffer[3] == 'O' and buffer[4] == 'R')
-      {
-        return MEMCACHED_ERROR;
-      }
-      // EXISTS
-      else if (buffer[1] == 'X' and buffer[2] == 'I' and buffer[3] == 'S' and buffer[4] == 'T' and buffer[5] == 'S')
-      {
-        return MEMCACHED_DATA_EXISTS;
-      }
-    }
-    break;
-
-  case 'T': /* TOUCHED */
-    {
-      // TOUCHED
-      if (buffer[1] == 'O' and buffer[2] == 'U' and buffer[3] == 'C' and buffer[4] == 'H' and buffer[5] == 'E' and buffer[6] == 'D')
-      {
-        return MEMCACHED_SUCCESS;
-      }
-    }
-    break;
-
-  case 'I': /* ITEM */
-    {
-      // ITEM
-      if (buffer[1] == 'T' and buffer[2] == 'E' and buffer[3] == 'M')
-      {
-        /* We add back in one because we will need to search for END */
-        memcached_server_response_increment(instance);
-        return MEMCACHED_ITEM;
-      }
-    }
-    break;
-
-  case 'C': /* CLIENT ERROR */
-    {
-      // CLIENT_ERROR
-      if (buffer[1] == 'L' and buffer[2] == 'I' and buffer[3] == 'E' and buffer[4] == 'N' and buffer[5] == 'T'
-          and buffer[6] == '_'
-          and buffer[7] == 'E' and buffer[8] == 'R' and buffer[9] == 'R' and buffer[10] == 'O' and buffer[11] == 'R')
-      {
-        // Move past the basic error message and whitespace
-        char *startptr= buffer + memcached_literal_param_size("CLIENT_ERROR");
-        if (startptr[0] == ' ')
-        {
-          startptr++;
-        }
-
-        char *endptr= startptr;
-        while (*endptr != '\r' && *endptr != '\n') endptr++;
-
-        return memcached_set_error(*instance, MEMCACHED_CLIENT_ERROR, MEMCACHED_AT, startptr, size_t(endptr - startptr));
-      }
-    }
-    break;
-
-  case '0': /* INCR/DECR response */
-  case '1': /* INCR/DECR response */
-  case '2': /* INCR/DECR response */
-  case '3': /* INCR/DECR response */
-  case '4': /* INCR/DECR response */
-  case '5': /* INCR/DECR response */
-  case '6': /* INCR/DECR response */
-  case '7': /* INCR/DECR response */
-  case '8': /* INCR/DECR response */
-  case '9': /* INCR/DECR response */
-    {
-      errno= 0;
-      unsigned long long int auto_return_value= strtoull(buffer, (char **)NULL, 10);
-
-      if (auto_return_value == ULLONG_MAX and errno == ERANGE)
-      {
-        result->numeric_value= UINT64_MAX;
-        return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
-                                   memcached_literal_param("Numeric response was out of range"));
-      }
-      else if (errno == EINVAL)
-      {
-        result->numeric_value= UINT64_MAX;
-        return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
-                                   memcached_literal_param("Numeric response was out of range"));
-      }
-      else if (errno != 0)
-      {
-        result->numeric_value= UINT64_MAX;
-        return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
-                                   memcached_literal_param("Numeric response was out of range"));
-      }
-
-      result->numeric_value= uint64_t(auto_return_value);
-
-      WATCHPOINT_STRING(buffer);
-      return MEMCACHED_SUCCESS;
-    }
-
-  default:
-    break;
-  }
-
-  buffer[total_read]= 0;
-#if 0
-  if (total_read >= sizeof("STORSTORED") -1)
-  {
-    fprintf(stderr, "%s:%d '%s', %.*s\n", __FILE__, __LINE__,
-            buffer, MEMCACHED_MAX_BUFFER, instance->read_buffer);
-    assert(memcmp(buffer,"STORSTORED", sizeof("STORSTORED") -1));
-  }
-#endif
-  return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
-                             buffer, total_read);
-}
-
-static memcached_return_t binary_read_one_response(memcached_instance_st* instance,
-                                                   char *buffer, const size_t buffer_length,
-                                                   memcached_result_st *result)
-{
-  memcached_return_t rc;
-  protocol_binary_response_header header;
-
-  assert(memcached_is_binary(instance->root));
-
-  if ((rc= memcached_safe_read(instance, &header.bytes, sizeof(header.bytes))) != MEMCACHED_SUCCESS)
-  {
-    WATCHPOINT_ERROR(rc);
-    return rc;
-  }
-
-  if (header.response.magic != PROTOCOL_BINARY_RES)
-  {
-    return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
-  }
-
-  /*
-   ** Convert the header to host local endian!
- */
-  header.response.keylen= ntohs(header.response.keylen);
-  header.response.status= ntohs(header.response.status);
-  header.response.bodylen= ntohl(header.response.bodylen);
-  header.response.cas= memcached_ntohll(header.response.cas);
-  uint32_t bodylen= header.response.bodylen;
-
-  if (header.response.status == PROTOCOL_BINARY_RESPONSE_SUCCESS or
-      header.response.status == PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE)
-  {
-    switch (header.response.opcode)
-    {
-    case PROTOCOL_BINARY_CMD_GETKQ:
-      /*
-       * We didn't increment the response counter for the GETKQ packet
-       * (only the final NOOP), so we need to increment the counter again.
-       */
-      memcached_server_response_increment(instance);
-      /* fall through */
-    case PROTOCOL_BINARY_CMD_GETK:
-      {
-        uint16_t keylen= header.response.keylen;
-        memcached_result_reset(result);
-        result->item_cas= header.response.cas;
-
-        if ((rc= memcached_safe_read(instance, &result->item_flags, sizeof (result->item_flags))) != MEMCACHED_SUCCESS)
-        {
-          WATCHPOINT_ERROR(rc);
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-        }
-
-        result->item_flags= ntohl(result->item_flags);
-        bodylen -= header.response.extlen;
-
-        result->key_length= keylen;
-        if (memcached_failed(rc= memcached_safe_read(instance, result->item_key, keylen)))
-        {
-          WATCHPOINT_ERROR(rc);
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-        }
-
-        // Only bother with doing this if key_length > 0
-        if (result->key_length)
-        {
-          if (memcached_array_size(instance->root->_namespace) and memcached_array_size(instance->root->_namespace) >= result->key_length)
-          {
-            return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
-          }
-
-          if (memcached_array_size(instance->root->_namespace))
-          {
-            result->key_length-= memcached_array_size(instance->root->_namespace);
-            memmove(result->item_key, result->item_key +memcached_array_size(instance->root->_namespace), result->key_length);
-          }
-        }
-
-        bodylen -= keylen;
-        if (memcached_failed(memcached_string_check(&result->value, bodylen)))
-        {
-          return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-        }
-
-        char *vptr= memcached_string_value_mutable(&result->value);
-        if (memcached_failed(rc= memcached_safe_read(instance, vptr, bodylen)))
-        {
-          WATCHPOINT_ERROR(rc);
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-        }
-
-        memcached_string_set_length(&result->value, bodylen);
-      }
-      break;
-
-    case PROTOCOL_BINARY_CMD_INCREMENT:
-    case PROTOCOL_BINARY_CMD_DECREMENT:
-      {
-        if (bodylen != sizeof(uint64_t))
-        {
-          result->numeric_value= UINT64_MAX;
-          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
-        }
-
-        uint64_t val;
-        if ((rc= memcached_safe_read(instance, &val, sizeof(val))) != MEMCACHED_SUCCESS)
-        {
-          result->numeric_value= UINT64_MAX;
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-        }
-
-        result->numeric_value= memcached_ntohll(val);
-      }
-      break;
-
-    case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS:
-      {
-        if (header.response.keylen != 0 || bodylen + 1 > buffer_length)
-        {
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-        }
-        else
-        {
-          if ((rc= memcached_safe_read(instance, buffer, bodylen)) != MEMCACHED_SUCCESS)
-          {
-            return MEMCACHED_UNKNOWN_READ_FAILURE;
-          }
-        }
-      }
-      break;
-
-    case PROTOCOL_BINARY_CMD_VERSION:
-      {
-        char version_buffer[32]; // @todo document this number
-        memset(version_buffer, 0, sizeof(version_buffer));
-
-        if (memcached_safe_read(instance, version_buffer, bodylen) != MEMCACHED_SUCCESS)
-        {
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-        }
-
-        char *endptr;
-        errno= 0;
-        long int version= strtol(version_buffer, &endptr, 10);
-        if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX or version == 0)
-        {
-          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
-          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version"));
-        }
-        instance->major_version= uint8_t(version);
-
-        endptr++;
-        errno= 0;
-        version= strtol(endptr, &endptr, 10);
-        if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX)
-        {
-          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
-          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse minor version"));
-        }
-        instance->minor_version= uint8_t(version);
-
-        endptr++;
-        errno= 0;
-        version= strtol(endptr, &endptr, 10);
-        if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX)
-        {
-          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
-          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
-        }
-        instance->micro_version= uint8_t(version);
-      }
-      break;
-
-    case PROTOCOL_BINARY_CMD_TOUCH:
-      {
-        rc= MEMCACHED_SUCCESS;
-        if (bodylen == 4) // The four byte read is a bug?
-        {
-          char touch_buffer[4]; // @todo document this number
-          rc= memcached_safe_read(instance, touch_buffer, sizeof(touch_buffer));
-#if 0
-          fprintf(stderr, "%s:%d %d %d %d %d %.*s(%d)\n", __FILE__, __LINE__,
-                  int(touch_buffer[0]),
-                  int(touch_buffer[1]),
-                  int(touch_buffer[2]),
-                  int(touch_buffer[3]),
-                  int(bodylen), touch_buffer, int(bodylen));
-#endif
-        }
-        return memcached_set_error(*instance, rc, MEMCACHED_AT);
-      }
-
-    case PROTOCOL_BINARY_CMD_FLUSH:
-    case PROTOCOL_BINARY_CMD_QUIT:
-    case PROTOCOL_BINARY_CMD_SET:
-    case PROTOCOL_BINARY_CMD_ADD:
-    case PROTOCOL_BINARY_CMD_REPLACE:
-    case PROTOCOL_BINARY_CMD_APPEND:
-    case PROTOCOL_BINARY_CMD_PREPEND:
-    case PROTOCOL_BINARY_CMD_DELETE:
-      {
-        WATCHPOINT_ASSERT(bodylen == 0);
-        return MEMCACHED_SUCCESS;
-      }
-
-    case PROTOCOL_BINARY_CMD_NOOP:
-      {
-        WATCHPOINT_ASSERT(bodylen == 0);
-        return MEMCACHED_END;
-      }
-
-    case PROTOCOL_BINARY_CMD_STAT:
-      {
-        if (bodylen == 0)
-        {
-          return MEMCACHED_END;
-        }
-        else if (bodylen + 1 > buffer_length)
-        {
-          /* not enough space in buffer.. should not happen... */
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-        }
-        else
-        {
-          size_t keylen= header.response.keylen;
-          memset(buffer, 0, buffer_length);
-          if ((rc= memcached_safe_read(instance, buffer, keylen)) != MEMCACHED_SUCCESS ||
-              (rc= memcached_safe_read(instance, buffer + keylen + 1, bodylen - keylen)) != MEMCACHED_SUCCESS)
-          {
-            WATCHPOINT_ERROR(rc);
-            return MEMCACHED_UNKNOWN_READ_FAILURE;
-          }
-        }
-      }
-      break;
-
-    case PROTOCOL_BINARY_CMD_SASL_AUTH:
-    case PROTOCOL_BINARY_CMD_SASL_STEP:
-      {
-        memcached_result_reset(result);
-        result->item_cas= header.response.cas;
-
-        if (memcached_string_check(&result->value,
-                                   bodylen) != MEMCACHED_SUCCESS)
-          return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-
-        char *vptr= memcached_string_value_mutable(&result->value);
-        if ((rc= memcached_safe_read(instance, vptr, bodylen)) != MEMCACHED_SUCCESS)
-        {
-          WATCHPOINT_ERROR(rc);
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-        }
-
-        memcached_string_set_length(&result->value, bodylen);
-      }
-      break;
-    default:
-      {
-        /* Command not implemented yet! */
-        return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
-      }
-    }
-  }
-  else if (header.response.bodylen)
-  {
-    /* What should I do with the error message??? just discard it for now */
-    char hole[SMALL_STRING_LEN];
-    while (bodylen > 0)
-    {
-      size_t nr= (bodylen > SMALL_STRING_LEN) ? SMALL_STRING_LEN : bodylen;
-      if ((rc= memcached_safe_read(instance, hole, nr)) != MEMCACHED_SUCCESS)
-      {
-        WATCHPOINT_ERROR(rc);
-        return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
-      }
-      bodylen-= (uint32_t) nr;
-    }
-
-    /* This might be an error from one of the quiet commands.. if
-     * so, just throw it away and get the next one. What about creating
-     * a callback to the user with the error information?
-   */
-    switch (header.response.opcode)
-    {
-    case PROTOCOL_BINARY_CMD_SETQ:
-    case PROTOCOL_BINARY_CMD_ADDQ:
-    case PROTOCOL_BINARY_CMD_REPLACEQ:
-    case PROTOCOL_BINARY_CMD_APPENDQ:
-    case PROTOCOL_BINARY_CMD_PREPENDQ:
-      return MEMCACHED_FETCH_NOTFINISHED;
-
-    default:
-      break;
-    }
-  }
-
-  rc= MEMCACHED_SUCCESS;
-  if (header.response.status != 0)
-  {
-    switch (header.response.status)
-    {
-    case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT:
-      rc= MEMCACHED_NOTFOUND;
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS:
-      rc= MEMCACHED_DATA_EXISTS;
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_NOT_STORED:
-      rc= MEMCACHED_NOTSTORED;
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_E2BIG:
-      rc= MEMCACHED_E2BIG;
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_ENOMEM:
-      rc= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE:
-      rc= MEMCACHED_AUTH_CONTINUE;
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_AUTH_ERROR:
-      rc= MEMCACHED_AUTH_FAILURE;
-      break;
-
-    case PROTOCOL_BINARY_RESPONSE_EINVAL:
-    case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
-    default:
-      return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
-      break;
-    }
-  }
-
-  return rc;
-}
-
-static memcached_return_t _read_one_response(memcached_instance_st* instance,
-                                             char *buffer, const size_t buffer_length,
-                                             memcached_result_st *result)
-{
-  memcached_server_response_decrement(instance);
-
-  if (result == NULL)
-  {
-    Memcached *root= (Memcached *)instance->root;
-    result = &root->result;
-  }
-
-  memcached_return_t rc;
-  if (memcached_is_binary(instance->root))
-  {
-    do {
-      rc= binary_read_one_response(instance, buffer, buffer_length, result);
-    } while (rc == MEMCACHED_FETCH_NOTFINISHED);
-  }
-  else
-  {
-    rc= textual_read_one_response(instance, buffer, buffer_length, result);
-  }
-
-  if (memcached_fatal(rc))
-  {
-    memcached_io_reset(instance);
-  }
-
-  return rc;
-}
-
-memcached_return_t memcached_read_one_response(memcached_instance_st* instance,
-                                               memcached_result_st *result)
-{
-  char buffer[SMALL_STRING_LEN];
-
-  if (memcached_is_udp(instance->root))
-  {
-    return memcached_set_error(*instance, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
-  }
-
-
-  return _read_one_response(instance, buffer, sizeof(buffer), result);
-}
-
-memcached_return_t memcached_response(memcached_instance_st* instance,
-                                      memcached_result_st *result)
-{
-  char buffer[1024];
-
-  return memcached_response(instance, buffer, sizeof(buffer), result);
-}
-
-memcached_return_t memcached_response(memcached_instance_st* instance,
-                                      char *buffer, size_t buffer_length,
-                                      memcached_result_st *result)
-{
-  if (memcached_is_udp(instance->root))
-  {
-    return memcached_set_error(*instance, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
-  }
-
-  /* We may have old commands in the buffer not sent, first purge */
-  if ((instance->root->flags.no_block) and (memcached_is_processing_input(instance->root) == false))
-  {
-    (void)memcached_io_write(instance);
-  }
-
-  /*  Before going into loop wait to see if we have any IO waiting for us */
-  if (0)
-  {
-    memcached_return_t read_rc= memcached_io_wait_for_read(instance);
-    fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, memcached_strerror(NULL, read_rc));
-  }
-
-  /*
-   * The previous implementation purged all pending requests and just
-   * returned the last one. Purge all pending messages to ensure backwards
-   * compatibility.
- */
-  if (memcached_is_binary(instance->root) == false and memcached_server_response_count(instance) > 1)
-  {
-    memcached_result_st junked_result;
-    memcached_result_st *junked_result_ptr= memcached_result_create(instance->root, &junked_result);
-
-    assert(junked_result_ptr);
-
-    while (memcached_server_response_count(instance) > 1)
-    {
-      memcached_return_t rc= _read_one_response(instance, buffer, buffer_length, junked_result_ptr);
-
-      // @TODO should we return an error on another but a bad read case?
-      if (memcached_fatal(rc))
-      {
-        memcached_result_free(junked_result_ptr);
-        return rc;
-      }
-    }
-    memcached_result_free(junked_result_ptr);
-  }
-
-  return _read_one_response(instance, buffer, buffer_length, result);
-}
diff --git a/libmemcached/response.h b/libmemcached/response.h
deleted file mode 100644 (file)
index c066f3b..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-/* Read a single response from the server */
-memcached_return_t memcached_read_one_response(memcached_instance_st* ptr,
-                                               memcached_result_st *result);
-
-memcached_return_t memcached_response(memcached_instance_st* ptr,
-                                      memcached_result_st *result);
-
-memcached_return_t memcached_response(memcached_instance_st* ptr,
-                                      char *buffer, size_t buffer_length,
-                                      memcached_result_st *result);
diff --git a/libmemcached/result.cc b/libmemcached/result.cc
deleted file mode 100644 (file)
index 6fa507b..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-/*
-  memcached_result_st are used to internally represent the return values from
-  memcached. We use a structure so that long term as identifiers are added
-  to memcached we will be able to absorb new attributes without having
-  to addjust the entire API.
-*/
-#include <libmemcached/common.h>
-
-static inline void _result_init(memcached_result_st *self,
-                                Memcached *memc)
-{
-  self->item_flags= 0;
-  self->item_expiration= 0;
-  self->key_length= 0;
-  self->item_cas= 0;
-  self->root= memc;
-  self->numeric_value= UINT64_MAX;
-  self->count= 0;
-  self->item_key[0]= 0;
-}
-
-memcached_result_st *memcached_result_create(const memcached_st *shell,
-                                             memcached_result_st *ptr)
-{
-  const Memcached* memc= memcached2Memcached(shell);
-
-  /* Saving malloc calls :) */
-  if (ptr)
-  {
-    ptr->options.is_allocated= false;
-  }
-  else
-  {
-    ptr= libmemcached_xmalloc(memc, memcached_result_st);
-
-    if (not ptr)
-    {
-      return NULL;
-    }
-
-    ptr->options.is_allocated= true;
-  }
-
-  ptr->options.is_initialized= true;
-
-  _result_init(ptr, (memcached_st *)memc);
-
-  WATCHPOINT_SET(ptr->value.options.is_initialized= false);
-  memcached_string_create((memcached_st*)memc, &ptr->value, 0);
-  WATCHPOINT_ASSERT_INITIALIZED(&ptr->value);
-  WATCHPOINT_ASSERT(ptr->value.string == NULL);
-
-  return ptr;
-}
-
-void memcached_result_reset(memcached_result_st *ptr)
-{
-  ptr->key_length= 0;
-  memcached_string_reset(&ptr->value);
-  ptr->item_flags= 0;
-  ptr->item_cas= 0;
-  ptr->item_expiration= 0;
-  ptr->numeric_value= UINT64_MAX;
-}
-
-void memcached_result_free(memcached_result_st *ptr)
-{
-  if (ptr == NULL)
-  {
-    return;
-  }
-
-  memcached_string_free(&ptr->value);
-  ptr->numeric_value= UINT64_MAX;
-
-  if (memcached_is_allocated(ptr))
-  {
-    WATCHPOINT_ASSERT(ptr->root); // Without a root, that means that result was not properly initialized.
-    libmemcached_free(ptr->root, ptr);
-  }
-  else
-  {
-    ptr->count= 0;
-    ptr->options.is_initialized= false;
-  }
-}
-
-void memcached_result_reset_value(memcached_result_st *ptr)
-{
-  memcached_string_reset(&ptr->value);
-}
-
-memcached_return_t memcached_result_set_value(memcached_result_st *ptr,
-                                              const char *value,
-                                              size_t length)
-{
-  if (memcached_failed(memcached_string_append(&ptr->value, value, length)))
-  {
-    return memcached_set_errno(*ptr->root, errno, MEMCACHED_AT);
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-const char *memcached_result_key_value(const memcached_result_st *self)
-{
-  return self->key_length ? self->item_key : NULL;
-}
-
-size_t memcached_result_key_length(const memcached_result_st *self)
-{
-  return self->key_length;
-}
-
-const char *memcached_result_value(const memcached_result_st *self)
-{
-  const memcached_string_st *sptr= &self->value;
-  return memcached_string_value(sptr);
-}
-
-size_t memcached_result_length(const memcached_result_st *self)
-{
-  const memcached_string_st *sptr= &self->value;
-  return memcached_string_length(sptr);
-}
-
-char *memcached_result_take_value(memcached_result_st *self)
-{
-  memcached_string_st *sptr= &self->value;
-  return memcached_string_take_value(sptr);
-}
-
-uint32_t memcached_result_flags(const memcached_result_st *self)
-{
-  return self->item_flags;
-}
-
-uint64_t memcached_result_cas(const memcached_result_st *self)
-{
-  return self->item_cas;
-}
-
-void memcached_result_set_flags(memcached_result_st *self, uint32_t flags)
-{
-  self->item_flags= flags;
-}
-
-void memcached_result_set_expiration(memcached_result_st *self, time_t expiration)
-{
-  self->item_expiration= expiration;
-}
diff --git a/libmemcached/result.h b/libmemcached/result.h
deleted file mode 100644 (file)
index 624ff5a..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-void memcached_result_reset_value(memcached_result_st *ptr);
diff --git a/libmemcached/sasl.cc b/libmemcached/sasl.cc
deleted file mode 100644 (file)
index 89462e5..0000000
+++ /dev/null
@@ -1,544 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libmemcached/common.h"
-#include <cassert>
-#include <atomic>
-
-#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
-
-#if defined(HAVE_LIBSASL) && HAVE_LIBSASL
-#include <sasl/sasl.h>
-#endif
-
-#define CAST_SASL_CB(cb) reinterpret_cast<int(*)()>(reinterpret_cast<intptr_t>(cb))
-
-#include <pthread.h>
-
-void memcached_set_sasl_callbacks(memcached_st *shell,
-                                  const sasl_callback_t *callbacks)
-{
-  Memcached* self= memcached2Memcached(shell);
-  if (self)
-  {
-    self->sasl.callbacks= const_cast<sasl_callback_t *>(callbacks);
-    self->sasl.is_allocated= false;
-  }
-}
-
-sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *shell)
-{
-  Memcached* self= memcached2Memcached(shell);
-  if (self)
-  {
-    return self->sasl.callbacks;
-  }
-
-  return NULL;
-}
-
-/**
- * Resolve the names for both ends of a connection
- * @param fd socket to check
- * @param laddr local address (out)
- * @param raddr remote address (out)
- * @return true on success false otherwise (errno contains more info)
- */
-static memcached_return_t resolve_names(memcached_instance_st& server, char *laddr, size_t laddr_length, char *raddr, size_t raddr_length)
-{
-  char host[MEMCACHED_NI_MAXHOST];
-  char port[MEMCACHED_NI_MAXSERV];
-  struct sockaddr_storage saddr;
-  socklen_t salen= sizeof(saddr);
-
-  if (getsockname(server.fd, (struct sockaddr *)&saddr, &salen) < 0)
-  {
-    return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
-  }
-
-  if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
-  {
-    return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
-  }
-
-  (void)snprintf(laddr, laddr_length, "%s;%s", host, port);
-  salen= sizeof(saddr);
-
-  if (getpeername(server.fd, (struct sockaddr *)&saddr, &salen) < 0)
-  {
-    return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
-  }
-
-  if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host),
-                   port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
-  {
-    return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
-  }
-
-  (void)snprintf(raddr, raddr_length, "%s;%s", host, port);
-
-  return MEMCACHED_SUCCESS;
-}
-
-extern "C" {
-
-static void sasl_shutdown_function()
-{
-  sasl_done();
-}
-
-static std::atomic<int> sasl_startup_state(SASL_OK);
-pthread_mutex_t sasl_startup_state_LOCK= PTHREAD_MUTEX_INITIALIZER;
-static pthread_once_t sasl_startup_once= PTHREAD_ONCE_INIT;
-static void sasl_startup_function(void)
-{
-  sasl_startup_state= sasl_client_init(NULL);
-
-  if (sasl_startup_state == SASL_OK)
-  {
-    (void)atexit(sasl_shutdown_function);
-  }
-}
-
-} // extern "C"
-
-memcached_return_t memcached_sasl_authenticate_connection(memcached_instance_st* server)
-{
-  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    return MEMCACHED_NOT_SUPPORTED;
-  }
-
-  if (server == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  /* SANITY CHECK: SASL can only be used with the binary protocol */
-  if (memcached_is_binary(server->root) == false)
-  {
-    return  memcached_set_error(*server, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
-                                memcached_literal_param("memcached_sasl_authenticate_connection() is not supported via the ASCII protocol"));
-  }
-
-  /* Try to get the supported mech from the server. Servers without SASL
-   * support will return UNKNOWN COMMAND, so we can just treat that
-   * as authenticated
- */
-  protocol_binary_request_no_extras request= { };
-
-  initialize_binary_request(server, request.message.header);
-
-  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SASL_LIST_MECHS;
-
-  if (memcached_io_write(server, request.bytes, sizeof(request.bytes), true) != sizeof(request.bytes))
-  {
-    return MEMCACHED_WRITE_FAILURE;
-  }
-  assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
-
-  memcached_server_response_increment(server);
-
-  char mech[MEMCACHED_MAX_BUFFER];
-  memcached_return_t rc= memcached_response(server, mech, sizeof(mech), NULL);
-  if (memcached_failed(rc))
-  {
-    if (rc == MEMCACHED_PROTOCOL_ERROR)
-    {
-      /* If the server doesn't support SASL it will return PROTOCOL_ERROR.
-       * This error may also be returned for other errors, but let's assume
-       * that the server don't support SASL and treat it as success and
-       * let the client fail with the next operation if the error was
-       * caused by another problem....
-     */
-      rc= MEMCACHED_SUCCESS;
-    }
-
-    return rc;
-  }
-  assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
-
-  /* set ip addresses */
-  char laddr[MEMCACHED_NI_MAXHOST + MEMCACHED_NI_MAXSERV];
-  char raddr[MEMCACHED_NI_MAXHOST + MEMCACHED_NI_MAXSERV];
-
-  if (memcached_failed(rc= resolve_names(*server, laddr, sizeof(laddr), raddr, sizeof(raddr))))
-  {
-    return rc;
-  }
-
-  int pthread_error;
-  if ((pthread_error= pthread_once(&sasl_startup_once, sasl_startup_function)) != 0)
-  {
-    return memcached_set_errno(*server, pthread_error, MEMCACHED_AT);
-  }
-
-  (void)pthread_mutex_lock(&sasl_startup_state_LOCK);
-  if (sasl_startup_state != SASL_OK)
-  {
-    const char *sasl_error_msg= sasl_errstring(sasl_startup_state, NULL, NULL);
-    return memcached_set_error(*server, MEMCACHED_AUTH_PROBLEM, MEMCACHED_AT, 
-                               memcached_string_make_from_cstr(sasl_error_msg));
-  }
-  (void)pthread_mutex_unlock(&sasl_startup_state_LOCK);
-
-  sasl_conn_t *conn;
-  int ret;
-  if ((ret= sasl_client_new("memcached", server->_hostname, laddr, raddr, server->root->sasl.callbacks, 0, &conn) ) != SASL_OK)
-  {
-    const char *sasl_error_msg= sasl_errstring(ret, NULL, NULL);
-
-    sasl_dispose(&conn);
-
-    return memcached_set_error(*server, MEMCACHED_AUTH_PROBLEM, MEMCACHED_AT, 
-                               memcached_string_make_from_cstr(sasl_error_msg));
-  }
-
-  const char *data;
-  const char *chosenmech;
-  unsigned int len;
-  ret= sasl_client_start(conn, mech, NULL, &data, &len, &chosenmech);
-  if (ret != SASL_OK and ret != SASL_CONTINUE)
-  {
-    const char *sasl_error_msg= sasl_errstring(ret, NULL, NULL);
-
-    sasl_dispose(&conn);
-
-    return memcached_set_error(*server, MEMCACHED_AUTH_PROBLEM, MEMCACHED_AT, 
-                               memcached_string_make_from_cstr(sasl_error_msg));
-  }
-  uint16_t keylen= (uint16_t)strlen(chosenmech);
-  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SASL_AUTH;
-  request.message.header.request.keylen= htons(keylen);
-  request.message.header.request.bodylen= htonl(len + keylen);
-
-  do {
-    /* send the packet */
-
-    libmemcached_io_vector_st vector[]=
-    {
-      { request.bytes, sizeof(request.bytes) },
-      { chosenmech, keylen },
-      { data, len }
-    };
-
-    assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
-    if (memcached_io_writev(server, vector, 3, true) == false)
-    {
-      rc= MEMCACHED_WRITE_FAILURE;
-      break;
-    }
-    assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
-    memcached_server_response_increment(server);
-
-    /* read the response */
-    assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
-    rc= memcached_response(server, NULL, 0, NULL);
-    if (rc != MEMCACHED_AUTH_CONTINUE)
-    {
-      break;
-    }
-    assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
-
-    ret= sasl_client_step(conn, memcached_result_value(&server->root->result),
-                          (unsigned int)memcached_result_length(&server->root->result),
-                          NULL, &data, &len);
-
-    if (ret != SASL_OK && ret != SASL_CONTINUE)
-    {
-      rc= MEMCACHED_AUTH_PROBLEM;
-      break;
-    }
-
-    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SASL_STEP;
-    request.message.header.request.bodylen= htonl(len + keylen);
-  } while (true);
-
-  /* Release resources */
-  sasl_dispose(&conn);
-
-  return memcached_set_error(*server, rc, MEMCACHED_AT);
-}
-
-static int get_username(void *context, int id, const char **result, unsigned int *len)
-{
-  if (!context || !result || (id != SASL_CB_USER && id != SASL_CB_AUTHNAME))
-  {
-    return SASL_BADPARAM;
-  }
-
-  *result= (char *)context;
-  if (len)
-  {
-    *len= (unsigned int)strlen(*result);
-  }
-
-  return SASL_OK;
-}
-
-static int get_password(sasl_conn_t *conn, void *context, int id,
-                        sasl_secret_t **psecret)
-{
-  if (!conn || ! psecret || id != SASL_CB_PASS)
-  {
-    return SASL_BADPARAM;
-  }
-
-  *psecret= (sasl_secret_t *)context;
-
-  return SASL_OK;
-}
-
-memcached_return_t memcached_set_sasl_auth_data(memcached_st *shell,
-                                                const char *username,
-                                                const char *password)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    return MEMCACHED_NOT_SUPPORTED;
-  }
-
-  if (ptr == NULL or username == NULL or password == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  memcached_return_t ret;
-  if (memcached_failed(ret= memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1)))
-  {
-    return memcached_set_error(*ptr, ret, MEMCACHED_AT, memcached_literal_param("Unable change to binary protocol which is required for SASL."));
-  }
-
-  memcached_destroy_sasl_auth_data(ptr);
-
-  sasl_callback_t *callbacks= libmemcached_xcalloc(ptr, 4, sasl_callback_t);
-  size_t password_length= strlen(password);
-  size_t username_length= strlen(username);
-  char *name= (char *)libmemcached_malloc(ptr, username_length +1);
-  sasl_secret_t *secret= (sasl_secret_t*)libmemcached_malloc(ptr, password_length +1 + sizeof(sasl_secret_t));
-
-  if (callbacks == NULL or name == NULL or secret == NULL)
-  {
-    libmemcached_free(ptr, callbacks);
-    libmemcached_free(ptr, name);
-    libmemcached_free(ptr, secret);
-    return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-  }
-
-  secret->len= password_length;
-  memcpy(secret->data, password, password_length);
-  secret->data[password_length]= 0;
-
-  callbacks[0].id= SASL_CB_USER;
-  callbacks[0].proc= CAST_SASL_CB(get_username);
-  callbacks[0].context= strncpy(name, username, username_length +1);
-  callbacks[1].id= SASL_CB_AUTHNAME;
-  callbacks[1].proc= CAST_SASL_CB(get_username);
-  callbacks[1].context= name;
-  callbacks[2].id= SASL_CB_PASS;
-  callbacks[2].proc= CAST_SASL_CB(get_password);
-  callbacks[2].context= secret;
-  callbacks[3].id= SASL_CB_LIST_END;
-
-  ptr->sasl.callbacks= callbacks;
-  ptr->sasl.is_allocated= true;
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *shell)
-{
-  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    return MEMCACHED_NOT_SUPPORTED;
-  }
-
-  Memcached* ptr= memcached2Memcached(shell);
-  if (ptr == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  if (ptr->sasl.callbacks == NULL)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  if (ptr->sasl.is_allocated)
-  {
-    libmemcached_free(ptr, ptr->sasl.callbacks[0].context);
-    libmemcached_free(ptr, ptr->sasl.callbacks[2].context);
-    libmemcached_free(ptr, (void*)ptr->sasl.callbacks);
-    ptr->sasl.is_allocated= false;
-  }
-
-  ptr->sasl.callbacks= NULL;
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_clone_sasl(memcached_st *clone, const  memcached_st *source)
-{
-  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    return MEMCACHED_NOT_SUPPORTED;
-  }
-
-  if (clone == NULL or source == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  if (source->sasl.callbacks == NULL)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  /* Hopefully we are using our own callback mechanisms.. */
-  if (source->sasl.callbacks[0].id == SASL_CB_USER &&
-      source->sasl.callbacks[0].proc ==  CAST_SASL_CB(get_username) &&
-      source->sasl.callbacks[1].id == SASL_CB_AUTHNAME &&
-      source->sasl.callbacks[1].proc ==  CAST_SASL_CB(get_username) &&
-      source->sasl.callbacks[2].id == SASL_CB_PASS &&
-      source->sasl.callbacks[2].proc ==  CAST_SASL_CB(get_password) &&
-      source->sasl.callbacks[3].id == SASL_CB_LIST_END)
-  {
-    sasl_secret_t *secret= (sasl_secret_t *)source->sasl.callbacks[2].context;
-    return memcached_set_sasl_auth_data(clone,
-                                        (const char*)source->sasl.callbacks[0].context,
-                                        (const char*)secret->data);
-  }
-
-  /*
-   * But we're not. It may work if we know what the user tries to pass
-   * into the list, but if we don't know the ID we don't know how to handle
-   * the context...
- */
-  ptrdiff_t total= 0;
-
-  while (source->sasl.callbacks[total].id != SASL_CB_LIST_END)
-  {
-    switch (source->sasl.callbacks[total].id)
-    {
-    case SASL_CB_USER:
-    case SASL_CB_AUTHNAME:
-    case SASL_CB_PASS:
-      break;
-    default:
-      /* I don't know how to deal with this... */
-      return MEMCACHED_NOT_SUPPORTED;
-    }
-
-    ++total;
-  }
-
-  sasl_callback_t *callbacks= libmemcached_xcalloc(clone, total +1, sasl_callback_t);
-  if (callbacks == NULL)
-  {
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-  }
-  memcpy(callbacks, source->sasl.callbacks, (total + 1) * sizeof(sasl_callback_t));
-
-  /* Now update the context... */
-  for (ptrdiff_t x= 0; x < total; ++x)
-  {
-    if (callbacks[x].id == SASL_CB_USER || callbacks[x].id == SASL_CB_AUTHNAME)
-    {
-      callbacks[x].context= (sasl_callback_t*)libmemcached_malloc(clone, strlen((const char*)source->sasl.callbacks[x].context));
-
-      if (callbacks[x].context == NULL)
-      {
-        /* Failed to allocate memory, clean up previously allocated memory */
-        for (ptrdiff_t y= 0; y < x; ++y)
-        {
-          libmemcached_free(clone, clone->sasl.callbacks[y].context);
-        }
-
-        libmemcached_free(clone, callbacks);
-        return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-      }
-      strncpy((char*)callbacks[x].context, (const char*)source->sasl.callbacks[x].context, sizeof(callbacks[x].context));
-    }
-    else
-    {
-      sasl_secret_t *src= (sasl_secret_t *)source->sasl.callbacks[x].context;
-      sasl_secret_t *n= (sasl_secret_t*)libmemcached_malloc(clone, src->len + 1 + sizeof(*n));
-      if (n == NULL)
-      {
-        /* Failed to allocate memory, clean up previously allocated memory */
-        for (ptrdiff_t y= 0; y < x; ++y)
-        {
-          libmemcached_free(clone, clone->sasl.callbacks[y].context);
-        }
-
-        libmemcached_free(clone, callbacks);
-        return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-      }
-      memcpy(n, src, src->len + 1 + sizeof(*n));
-      callbacks[x].context= n;
-    }
-  }
-
-  clone->sasl.callbacks= callbacks;
-  clone->sasl.is_allocated= true;
-
-  return MEMCACHED_SUCCESS;
-}
-
-#else
-
-void memcached_set_sasl_callbacks(memcached_st *, const sasl_callback_t *)
-{
-}
-
-sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *)
-{
-  return NULL;
-}
-
-memcached_return_t memcached_set_sasl_auth_data(memcached_st *, const char *, const char *)
-{
-  return MEMCACHED_NOT_SUPPORTED;
-}
-
-memcached_return_t memcached_clone_sasl(memcached_st *, const  memcached_st *)
-{
-  return MEMCACHED_NOT_SUPPORTED;
-}
-
-#endif
diff --git a/libmemcached/sasl.hpp b/libmemcached/sasl.hpp
deleted file mode 100644 (file)
index bda6b22..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-memcached_return_t memcached_clone_sasl(memcached_st *clone, const  memcached_st *source);
-
-memcached_return_t memcached_sasl_authenticate_connection(memcached_instance_st* server);
diff --git a/libmemcached/server.cc b/libmemcached/server.cc
deleted file mode 100644 (file)
index e2837c7..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
-  This is a partial implementation for fetching/creating memcached_server_st objects.
-*/
-#include <libmemcached/common.h>
-
-static inline void _server_init(memcached_server_st *self, Memcached *root,
-                                const memcached_string_t& hostname,
-                                in_port_t port,
-                                uint32_t weight, memcached_connection_t type)
-{
-  self->options.is_shutting_down= false;
-  self->options.is_dead= false;
-  self->number_of_hosts= 0;
-  self->cursor_active= 0;
-  self->port= port;
-  self->io_bytes_sent= 0;
-  self->request_id= 0;
-  self->server_failure_counter= 0;
-  self->server_failure_counter_query_id= 0;
-  self->server_timeout_counter= 0;
-  self->server_timeout_counter_query_id= 0;
-  self->weight= weight ? weight : 1; // 1 is the default weight value
-  self->io_wait_count.read= 0;
-  self->io_wait_count.write= 0;
-  self->io_wait_count.timeouts= 0;
-  self->io_wait_count._bytes_read= 0;
-  self->major_version= UINT8_MAX;
-  self->micro_version= UINT8_MAX;
-  self->minor_version= UINT8_MAX;
-  self->type= type;
-  self->error_messages= NULL;
-
-  self->state= MEMCACHED_SERVER_STATE_NEW;
-  self->next_retry= 0;
-
-  self->root= root;
-  if (root)
-  {
-    self->version= ++root->server_info.version;
-  }
-  else
-  {
-    self->version= UINT_MAX;
-  }
-  self->limit_maxbytes= 0;
-  memcpy(self->hostname, hostname.c_str, hostname.size);
-  self->hostname[hostname.size]= 0;
-}
-
-static memcached_server_st *_server_create(memcached_server_st *self, const Memcached *memc)
-{
-  if (self == NULL)
-  {
-   self= libmemcached_xmalloc(memc, struct memcached_server_st);
-
-    if (self == NULL)
-    {
-      return NULL; /*  MEMCACHED_MEMORY_ALLOCATION_FAILURE */
-    }
-
-    self->options.is_allocated= true;
-  }
-  else
-  {
-    self->options.is_allocated= false;
-  }
-
-  self->options.is_initialized= true;
-
-  return self;
-}
-
-memcached_server_st *__server_create_with(Memcached *memc,
-                                          memcached_server_st* allocated_instance,
-                                          const memcached_string_t& hostname,
-                                          const in_port_t port,
-                                          uint32_t weight, 
-                                          const memcached_connection_t type)
-{
-  if (memcached_is_valid_servername(hostname) == false)
-  {
-    memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid hostname provided"));
-    return NULL;
-  }
-
-  allocated_instance= _server_create(allocated_instance, memc);
-
-  if (allocated_instance == NULL)
-  {
-    return NULL;
-  }
-
-  _server_init(allocated_instance, const_cast<Memcached *>(memc), hostname, port, weight, type);
-
-  return allocated_instance;
-}
-
-void __server_free(memcached_server_st *self)
-{
-  memcached_error_free(*self);
-
-  if (memcached_is_allocated(self))
-  {
-    libmemcached_free(self->root, self);
-  }
-  else
-  {
-    self->options.is_initialized= false;
-  }
-}
-
-void memcached_server_free(memcached_server_st *self)
-{
-  if (self == NULL)
-  {
-    return;
-  }
-
-  if (memcached_server_list_count(self))
-  {
-    memcached_server_list_free(self);
-    return;
-  }
-
-  __server_free(self);
-}
-
-void memcached_server_error_reset(memcached_server_st *self)
-{
-  WATCHPOINT_ASSERT(self);
-  if (self == NULL)
-  {
-    return;
-  }
-
-  memcached_error_free(*self);
-}
-
-uint32_t memcached_servers_set_count(memcached_server_st *servers, uint32_t count)
-{
-  WATCHPOINT_ASSERT(servers);
-  if (servers == NULL)
-  {
-    return 0;
-  }
-
-  return servers->number_of_hosts= count;
-}
-
-uint32_t memcached_server_count(const memcached_st *self)
-{
-  WATCHPOINT_ASSERT(self);
-  if (self == NULL)
-    return 0;
-
-  return self->number_of_hosts;
-}
-
-const char *memcached_server_name(const memcached_instance_st * self)
-{
-  WATCHPOINT_ASSERT(self);
-  if (self)
-  {
-    return self->_hostname;
-  }
-
-  return NULL;
-}
-
-in_port_t memcached_server_port(const memcached_instance_st * self)
-{
-  WATCHPOINT_ASSERT(self);
-  if (self == NULL)
-  {
-    return 0;
-  }
-
-  return self->port();
-}
-
-in_port_t memcached_server_srcport(const memcached_instance_st * self)
-{
-  WATCHPOINT_ASSERT(self);
-  if (self == NULL || self->fd == INVALID_SOCKET || (self->type != MEMCACHED_CONNECTION_TCP && self->type != MEMCACHED_CONNECTION_UDP))
-  {
-    return 0;
-  }
-
-  struct sockaddr_in sin;
-  socklen_t addrlen= sizeof(sin);
-  if (getsockname(self->fd, (struct sockaddr*)&sin, &addrlen) != -1)
-  {
-    return ntohs(sin.sin_port);
-  }
-
-  return -1;
-}
-
-uint32_t memcached_server_response_count(const memcached_instance_st * self)
-{
-  WATCHPOINT_ASSERT(self);
-  if (self == NULL)
-  {
-    return 0;
-  }
-
-  return self->cursor_active_;
-}
-
-const char *memcached_server_type(const memcached_instance_st * ptr)
-{
-  if (ptr)
-  {
-    switch (ptr->type)
-    {
-    case MEMCACHED_CONNECTION_TCP:
-      return "TCP";
-
-    case MEMCACHED_CONNECTION_UDP:
-      return "UDP";
-
-    case MEMCACHED_CONNECTION_UNIX_SOCKET:
-      return "SOCKET";
-    }
-  }
-
-  return "UNKNOWN";
-}
-
-uint8_t memcached_server_major_version(const memcached_instance_st * instance)
-{
-  if (instance)
-  {
-    return instance->major_version;
-  }
-
-  return UINT8_MAX;
-}
-
-uint8_t memcached_server_minor_version(const memcached_instance_st * instance)
-{
-  if (instance)
-  {
-    return instance->minor_version;
-  }
-
-  return UINT8_MAX;
-}
-
-uint8_t memcached_server_micro_version(const memcached_instance_st * instance)
-{
-  if (instance)
-  {
-    return instance->micro_version;
-  }
-
-  return UINT8_MAX;
-}
diff --git a/libmemcached/server.hpp b/libmemcached/server.hpp
deleted file mode 100644 (file)
index 582356d..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#endif
-
-#include <cassert>
-
-memcached_server_st *__server_create_with(memcached_st *memc,
-                                          memcached_server_st* self,
-                                          const memcached_string_t& hostname,
-                                          const in_port_t port,
-                                          uint32_t weight, 
-                                          const memcached_connection_t type);
-
-memcached_return_t memcached_server_add_parsed(memcached_st *ptr,
-                                               const char *hostname,
-                                               size_t hostname_length,
-                                               in_port_t port,
-                                               uint32_t weight);
-
-void __server_free(memcached_server_st *);
-
-static inline bool memcached_is_valid_servername(const memcached_string_t& arg)
-{
-  return (arg.c_str != NULL or arg.size == 0) and arg.size < MEMCACHED_NI_MAXHOST;
-}
-
-static inline bool memcached_is_valid_filename(const memcached_string_t& arg)
-{
-  return arg.c_str != NULL and arg.size > 0 and arg.size < MEMCACHED_NI_MAXHOST;
-}
-
-void memcached_instance_free(memcached_instance_st *);
-
-void set_last_disconnected_host(memcached_instance_st* self);
-
-static inline void memcached_mark_server_for_timeout(memcached_instance_st* server)
-{
-  if (server->state != MEMCACHED_SERVER_STATE_IN_TIMEOUT)
-  {
-    if (server->server_timeout_counter_query_id != server->root->query_id)
-    {
-      server->server_timeout_counter++;
-      server->server_timeout_counter_query_id= server->root->query_id;
-    }
-
-    if (server->server_timeout_counter >= server->root->server_timeout_limit)
-    {
-      struct timeval next_time;
-      if (gettimeofday(&next_time, NULL) == 0)
-      {
-        server->next_retry= next_time.tv_sec +server->root->retry_timeout;
-      }
-      else
-      {
-        server->next_retry= 1; // Setting the value to 1 causes the timeout to occur immediately
-      }
-
-      server->state= MEMCACHED_SERVER_STATE_IN_TIMEOUT;
-      if (server->server_failure_counter_query_id != server->root->query_id)
-      {
-        server->server_failure_counter++;
-        server->server_failure_counter_query_id= server->root->query_id;
-      }
-      set_last_disconnected_host(server);
-    }
-  }
-}
diff --git a/libmemcached/server_instance.h b/libmemcached/server_instance.h
deleted file mode 100644 (file)
index 187f274..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-typedef struct memcached_instance_st* memcached_server_write_instance_st;
-#else
-typedef void* memcached_server_write_instance_st;
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef memcached_return_t (*memcached_server_execute_fn)(memcached_st *ptr, memcached_server_write_instance_st server, void *context);
-
-memcached_return_t memcached_server_execute(memcached_st *ptr,
-                                            memcached_server_execute_fn callback,
-                                            void *context);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-
diff --git a/libmemcached/server_list.cc b/libmemcached/server_list.cc
deleted file mode 100644 (file)
index b5d5b72..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-
-#include <libmemcached/common.h>
-
-memcached_server_list_st 
-memcached_server_list_append_with_weight(memcached_server_list_st ptr,
-                                         const char *hostname, in_port_t port,
-                                         uint32_t weight,
-                                         memcached_return_t *error)
-{
-  memcached_return_t unused;
-  if (error == NULL)
-  {
-    error= &unused;
-  }
-
-  if (hostname == NULL)
-  {
-    hostname= "localhost";
-  }
-
-  if (hostname[0] == '/')
-  {
-    port = 0;
-  }
-  else if (port == 0)
-  {
-    port= MEMCACHED_DEFAULT_PORT;
-  }
-
-
-  /* Increment count for hosts */
-  uint32_t count= 1;
-  if (ptr != NULL)
-  {
-    count+= memcached_server_list_count(ptr);
-  }
-
-  memcached_server_list_st new_host_list= (memcached_server_st*)realloc(ptr, sizeof(memcached_server_st) * count);
-  if (new_host_list == NULL)
-  {
-#if 0
-    *error= memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-#endif
-    return NULL;
-  }
-
-  memcached_string_t _hostname= { memcached_string_make_from_cstr(hostname) };
-  /* @todo Check return type */
-  if (__server_create_with(NULL, &new_host_list[count-1], _hostname, port, weight, port ? MEMCACHED_CONNECTION_TCP : MEMCACHED_CONNECTION_UNIX_SOCKET) == NULL)
-  {
-#if 0
-    *error= memcached_set_errno(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-#endif
-    free(new_host_list);
-    return NULL;
-  }
-
-#if 0
-  // Handset allocated since 
-  new_host_list->options.is_allocated= true;
-#endif
-
-  /* Backwards compatibility hack */
-  memcached_servers_set_count(new_host_list, count);
-
-  *error= MEMCACHED_SUCCESS;
-  return new_host_list;
-}
-
-memcached_server_list_st
-memcached_server_list_append(memcached_server_list_st ptr,
-                             const char *hostname, in_port_t port,
-                             memcached_return_t *error)
-{
-  return memcached_server_list_append_with_weight(ptr, hostname, port, 0, error);
-}
-
-uint32_t memcached_server_list_count(const memcached_server_list_st self)
-{
-  return (self == NULL)
-    ? 0
-    : self->number_of_hosts;
-}
-
-uint32_t memcached_instance_list_count(const memcached_st* self)
-{
-  return (self == NULL)
-    ? 0
-    : self->number_of_hosts;
-}
-
-void memcached_instance_set(memcached_st* memc, memcached_instance_st* list, const uint32_t host_list_size)
-{
-  assert(memc);
-  memc->servers= list;
-  memc->number_of_hosts= host_list_size;
-}
-
-void memcached_server_list_free(memcached_server_list_st self)
-{
-  if (self)
-  {
-    for (uint32_t x= 0; x < memcached_server_list_count(self); x++)
-    {
-      assert_msg(not memcached_is_allocated(&self[x]), "You have called memcached_server_list_free(), but you did not pass it a valid memcached_server_list_st");
-      __server_free(&self[x]);
-    }
-
-    libmemcached_free(self->root, self);
-  }
-}
-
-void memcached_instance_list_free(memcached_instance_st* self, uint32_t instance_count)
-{
-  if (self)
-  {
-    for (uint32_t x= 0; x < instance_count; x++)
-    {
-      assert_msg(memcached_is_allocated(&self[x]) == false, "You have called memcached_server_list_free(), but you did not pass it a valid memcached_server_list_st");
-      __instance_free(&self[x]);
-    }
-
-    libmemcached_free(self->root, self);
-  }
-}
diff --git a/libmemcached/server_list.hpp b/libmemcached/server_list.hpp
deleted file mode 100644 (file)
index 0280332..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-memcached_instance_st* memcached_instance_list(const memcached_st *);
-
-uint32_t memcached_instance_list_count(const memcached_st*);
-
-uint32_t memcached_servers_set_count(memcached_server_list_st servers, uint32_t count);
-
-void memcached_instance_list_free(memcached_instance_st* self, uint32_t count);
-
-void memcached_instance_set(memcached_st*, memcached_instance_st*, const uint32_t host_list_size);
diff --git a/libmemcached/socket.hpp b/libmemcached/socket.hpp
deleted file mode 100644 (file)
index a2ee941..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-/* To hide the platform differences between MS Windows and Unix, I am
- * going to use the Microsoft way and #define the Microsoft-specific
- * functions to the unix way. Microsoft use a separate subsystem for sockets,
- * but Unix normally just use a filedescriptor on the same functions. It is
- * a lot easier to map back to the unix way with macros than going the other
- * way without side effect ;-)
- */
-#if defined(WIN32) || defined(__MINGW32__)
-# include "win32/wrappers.h"
-# define get_socket_errno() WSAGetLastError()
-#else
-# include <unistd.h>
-# define INVALID_SOCKET -1
-# define SOCKET_ERROR -1
-# define closesocket(a) close(a)
-# define get_socket_errno() errno
-#endif
-
-#ifdef __cplusplus
-static inline void memcached_close_socket(memcached_socket_t& socket_fd)
-{
-  closesocket(socket_fd);
-  socket_fd= INVALID_SOCKET;
-}
-#endif
-
-#ifndef HAVE_MSG_NOSIGNAL
-# define MSG_NOSIGNAL 0
-#endif
-
-#ifndef HAVE_MSG_DONTWAIT
-# define MSG_DONTWAIT 0
-#endif
-
-#ifndef HAVE_MSG_MORE
-# define MSG_MORE 0
-#endif
-
-
diff --git a/libmemcached/stats.cc b/libmemcached/stats.cc
deleted file mode 100644 (file)
index 9e6083e..0000000
+++ /dev/null
@@ -1,846 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-static const char *memcached_stat_keys[] = {
-  "pid",
-  "uptime",
-  "time",
-  "version",
-  "pointer_size",
-  "rusage_user",
-  "rusage_system",
-  "curr_items",
-  "total_items",
-  "bytes",
-  "curr_connections",
-  "total_connections",
-  "connection_structures",
-  "cmd_get",
-  "cmd_set",
-  "get_hits",
-  "get_misses",
-  "evictions",
-  "bytes_read",
-  "bytes_written",
-  "limit_maxbytes",
-  "threads",
-  NULL
-};
-
-struct local_context
-{
-  memcached_stat_fn func;
-  void *context;
-  const char *args;
-  const size_t args_length;
-
-  local_context(memcached_stat_fn func_arg,
-                void *context_arg,
-                const char *args_arg,
-                const size_t args_length_arg) :
-    func(func_arg),
-    context(context_arg),
-    args(args_arg),
-    args_length(args_length_arg)
-  { }
-};
-
-
-static memcached_return_t set_data(memcached_stat_st *memc_stat, const char *key, const char *value)
-{
-
-  if (strlen(key) < 1)
-  {
-    WATCHPOINT_STRING(key);
-    return MEMCACHED_UNKNOWN_STAT_KEY;
-  }
-  else if (strcmp("pid", key) == 0)
-  {
-    errno= 0;
-    int64_t temp= strtoll(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-
-    if (temp <= INT32_MAX and ( sizeof(pid_t) == sizeof(int32_t) ))
-    {
-      memc_stat->pid= pid_t(temp);
-    }
-    else if (temp > -1)
-    {
-      memc_stat->pid= pid_t(temp);
-    }
-    else
-    {
-      // If we got a value less then -1 then something went wrong in the
-      // protocol
-    }
-  }
-  else if (not strcmp("uptime", key))
-  {
-    errno= 0;
-    memc_stat->uptime= strtoul(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("time", key))
-  {
-    errno= 0;
-    memc_stat->time= strtoul(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("version", key))
-  {
-    memcpy(memc_stat->version, value, strlen(value));
-    memc_stat->version[strlen(value)]= 0;
-  }
-  else if (not strcmp("pointer_size", key))
-  {
-    errno= 0;
-    memc_stat->pointer_size= strtoul(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("rusage_user", key))
-  {
-    char *walk_ptr;
-    for (walk_ptr= (char*)value; (!ispunct(*walk_ptr)); walk_ptr++) {};
-    *walk_ptr= 0;
-    walk_ptr++;
-
-    errno= 0;
-    memc_stat->rusage_user_seconds= strtoul(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-
-    errno= 0;
-    memc_stat->rusage_user_microseconds= strtoul(walk_ptr, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("rusage_system", key))
-  {
-    char *walk_ptr;
-    for (walk_ptr= (char*)value; (!ispunct(*walk_ptr)); walk_ptr++) {};
-    *walk_ptr= 0;
-    walk_ptr++;
-
-    errno= 0;
-    memc_stat->rusage_system_seconds= strtoul(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-
-    errno= 0;
-    memc_stat->rusage_system_microseconds= strtoul(walk_ptr, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("curr_items", key))
-  {
-    errno= 0;
-    memc_stat->curr_items= strtoul(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("total_items", key))
-  {
-    errno= 0;
-    memc_stat->total_items= strtoul(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("bytes_read", key))
-  {
-    errno= 0;
-    memc_stat->bytes_read= strtoull(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("bytes_written", key))
-  {
-    errno= 0;
-    memc_stat->bytes_written= strtoull(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("bytes", key))
-  {
-    errno= 0;
-    memc_stat->bytes= strtoull(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("curr_connections", key))
-  {
-    errno= 0;
-    memc_stat->curr_connections= strtoull(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("total_connections", key))
-  {
-    errno= 0;
-    memc_stat->total_connections= strtoull(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("connection_structures", key))
-  {
-    errno= 0;
-    memc_stat->connection_structures= strtoul(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("cmd_get", key))
-  {
-    errno= 0;
-    memc_stat->cmd_get= strtoull(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("cmd_set", key))
-  {
-    errno= 0;
-    memc_stat->cmd_set= strtoull(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("get_hits", key))
-  {
-    errno= 0;
-    memc_stat->get_hits= strtoull(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("get_misses", key))
-  {
-    errno= 0;
-    memc_stat->get_misses= strtoull(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("evictions", key))
-  {
-    errno= 0;
-    memc_stat->evictions= strtoull(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("limit_maxbytes", key))
-  {
-    errno= 0;
-    memc_stat->limit_maxbytes= strtoull(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if (not strcmp("threads", key))
-  {
-    errno= 0;
-    memc_stat->threads= strtoul(value, (char **)NULL, 10);
-    if (errno != 0)
-    {
-      return MEMCACHED_FAILURE;
-    }
-  }
-  else if ((strcmp("delete_misses", key) == 0 or /* New stats in the 1.3 beta */
-            strcmp("delete_hits", key) == 0 or /* Just swallow them for now.. */
-            strcmp("incr_misses", key) == 0 or
-            strcmp("incr_hits", key) == 0 or
-            strcmp("decr_misses", key) == 0 or
-            strcmp("decr_hits", key) == 0 or
-            strcmp("cas_misses", key) == 0 or
-            strcmp("cas_hits", key) == 0 or
-            strcmp("cas_badval", key) == 0 or
-            strcmp("cmd_flush", key) == 0 or
-            strcmp("accepting_conns", key) == 0 or
-            strcmp("listen_disabled_num", key) == 0 or
-            strcmp("conn_yields", key) == 0 or
-            strcmp("auth_cmds", key) == 0 or
-            strcmp("auth_errors", key) == 0 or
-            strcmp("reclaimed", key) == 0) == 0)
-  {
-    WATCHPOINT_STRING(key);
-    /* return MEMCACHED_UNKNOWN_STAT_KEY; */
-    return MEMCACHED_SUCCESS;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-char *memcached_stat_get_value(const memcached_st* shell, memcached_stat_st *memc_stat,
-                               const char *key, memcached_return_t *error)
-{
-  memcached_return_t not_used;
-  if (error == NULL)
-  {
-    error= &not_used;
-  }
-
-  if (memc_stat == NULL)
-  {
-    *error= MEMCACHED_INVALID_ARGUMENTS;
-    return NULL;
-  }
-
-  char buffer[SMALL_STRING_LEN];
-  int length;
-
-  *error= MEMCACHED_SUCCESS;
-
-  if (memcmp("pid", key, sizeof("pid") -1) == 0)
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%lld", (signed long long)memc_stat->pid);
-  }
-  else if (not memcmp("uptime", key, sizeof("uptime") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->uptime);
-  }
-  else if (not memcmp("time", key, sizeof("time") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->time);
-  }
-  else if (not memcmp("version", key, sizeof("version") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%s", memc_stat->version);
-  }
-  else if (not memcmp("pointer_size", key, sizeof("pointer_size") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->pointer_size);
-  }
-  else if (not memcmp("rusage_user", key, sizeof("rusage_user") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%lu.%lu", memc_stat->rusage_user_seconds, memc_stat->rusage_user_microseconds);
-  }
-  else if (not memcmp("rusage_system", key, sizeof("rusage_system") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%lu.%lu", memc_stat->rusage_system_seconds, memc_stat->rusage_system_microseconds);
-  }
-  else if (not memcmp("curr_items", key, sizeof("curr_items") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->curr_items);
-  }
-  else if (not memcmp("total_items", key, sizeof("total_items") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->total_items);
-  }
-  else if (not memcmp("curr_connections", key, sizeof("curr_connections") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->curr_connections);
-  }
-  else if (not memcmp("total_connections", key, sizeof("total_connections") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->total_connections);
-  }
-  else if (not memcmp("connection_structures", key, sizeof("connection_structures") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->connection_structures);
-  }
-  else if (not memcmp("cmd_get", key, sizeof("cmd_get") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->cmd_get);
-  }
-  else if (not memcmp("cmd_set", key, sizeof("cmd_set") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->cmd_set);
-  }
-  else if (not memcmp("get_hits", key, sizeof("get_hits") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->get_hits);
-  }
-  else if (not memcmp("get_misses", key, sizeof("get_misses") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->get_misses);
-  }
-  else if (not memcmp("evictions", key, sizeof("evictions") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->evictions);
-  }
-  else if (not memcmp("bytes_read", key, sizeof("bytes_read") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes_read);
-  }
-  else if (not memcmp("bytes_written", key, sizeof("bytes_written") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes_written);
-  }
-  else if (not memcmp("bytes", key, sizeof("bytes") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes);
-  }
-  else if (not memcmp("limit_maxbytes", key, sizeof("limit_maxbytes") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->limit_maxbytes);
-  }
-  else if (not memcmp("threads", key, sizeof("threads") -1))
-  {
-    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->threads);
-  }
-  else
-  {
-    Memcached* memc= (Memcached*)memcached2Memcached(shell);
-    *error= memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid key provided"));
-    return NULL;
-  }
-
-  if (length >= SMALL_STRING_LEN || length < 0)
-  {
-    Memcached* memc= (Memcached*)memcached2Memcached(shell);
-    *error= memcached_set_error(*memc, MEMCACHED_FAILURE, MEMCACHED_AT, memcached_literal_param("Internal failure occured with buffer, please report this bug."));
-    return NULL;
-  }
-
-  // User is responsible for free() memory, so use malloc()
-  char *ret= static_cast<char *>(malloc(size_t(length +1)));
-  memcpy(ret, buffer, (size_t) length);
-  ret[length]= '\0';
-
-  return ret;
-}
-
-static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat,
-                                             const char *args,
-                                             const size_t args_length,
-                                             memcached_instance_st* instance,
-                                             struct local_context *check)
-{
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  protocol_binary_request_stats request= {}; // = {.bytes= {0}};
-  memcached_return_t rc;
-
-  initialize_binary_request(instance, request.message.header);
-
-  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_STAT;
-  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-
-  if (args_length)
-  {
-    request.message.header.request.keylen= htons(uint16_t(args_length));
-    request.message.header.request.bodylen= htonl(uint32_t( args_length));
-
-    libmemcached_io_vector_st vector[]=
-    {
-      { request.bytes, sizeof(request.bytes) },
-      { args, args_length }
-    };
-
-    if (memcached_failed(rc = memcached_vdo(instance, vector, 2, true)))
-    {
-      return rc;
-    }
-  }
-  else
-  {
-    libmemcached_io_vector_st vector[]=
-    {
-      { request.bytes, sizeof(request.bytes) }
-    };
-
-    if (memcached_failed(rc = memcached_vdo(instance, vector, 1, true)))
-    {
-      return rc;
-    }
-  }
-
-  memcached_server_response_decrement(instance);
-  while (1)
-  {
-    rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
-
-    if (rc == MEMCACHED_END)
-    {
-      break;
-    }
-
-    if (rc != MEMCACHED_SUCCESS)
-    {
-      return rc;
-    }
-
-    if (check && check->func)
-    {
-      size_t key_length= strlen(buffer);
-
-      check->func(instance,
-                  buffer, key_length,
-                  buffer+key_length+1, strlen(buffer+key_length+1),
-                  check->context);
-    }
-
-    if (memc_stat)
-    {
-      if ((set_data(memc_stat, buffer, buffer + strlen(buffer) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY)
-      {
-        WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
-        WATCHPOINT_ASSERT(0);
-      }
-    }
-  }
-
-  /* 
-   * memcached_response will decrement the counter, so I need to reset it..
-   * todo: look at this and try to find a better solution.  
-   * */
-  instance->cursor_active_= 0;
-
-  return MEMCACHED_SUCCESS;
-}
-
-static memcached_return_t ascii_stats_fetch(memcached_stat_st *memc_stat,
-                                            const char *args,
-                                            const size_t args_length,
-                                            memcached_instance_st* instance,
-                                            struct local_context *check)
-{
-  libmemcached_io_vector_st vector[]=
-  {
-    { memcached_literal_param("stats ") },
-    { args, args_length },
-    { memcached_literal_param("\r\n") }
-  };
-
-  memcached_return_t rc= memcached_vdo(instance, vector, 3, true);
-  if (memcached_success(rc))
-  {
-    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-    while ((rc= memcached_response(instance, buffer, sizeof(buffer), NULL)) == MEMCACHED_STAT)
-    {
-      char *string_ptr= buffer;
-      string_ptr+= 5; /* Move past STAT */
-
-      char *end_ptr;
-      for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++) {};
-      char *key= string_ptr;
-      key[size_t(end_ptr-string_ptr)]= 0;
-
-      string_ptr= end_ptr + 1;
-      for (end_ptr= string_ptr; !(isspace(*end_ptr)); end_ptr++) {};
-      char *value= string_ptr;
-      value[(size_t)(end_ptr -string_ptr)]= 0;
-#if 0
-      bool check_bool= bool(check);
-      bool check_func_bool= bool(check) ? bool(check->func) : false;
-      fprintf(stderr, "%s:%d %s %s %d:%d\n", __FILE__, __LINE__, key, value, check_bool, check_func_bool);
-#endif
-
-      if (check and check->func)
-      {
-        check->func(instance,
-                    key, strlen(key),
-                    value, strlen(value),
-                    check->context);
-      }
-
-      if (memc_stat)
-      {
-        if((set_data(memc_stat, key, value)) == MEMCACHED_UNKNOWN_STAT_KEY)
-        {
-          WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
-          WATCHPOINT_ASSERT(0);
-        }
-      }
-    }
-  }
-
-  if (rc == MEMCACHED_ERROR)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  if (rc == MEMCACHED_END)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  return rc;
-}
-
-memcached_stat_st *memcached_stat(memcached_st *shell, char *args, memcached_return_t *error)
-{
-  Memcached* self= memcached2Memcached(shell);
-  memcached_return_t unused;
-  if (error == NULL)
-  {
-    error= &unused;
-  }
-
-  if (memcached_failed(*error= initialize_query(self, true)))
-  {
-    return NULL;
-  }
-
-  if (memcached_is_udp(self))
-  {
-    *error= memcached_set_error(*self, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
-    return NULL;
-  }
-
-  memcached_return_t rc;
-  size_t args_length= 0;
-  if (args)
-  {
-    args_length= strlen(args);
-    if (memcached_failed(rc= memcached_key_test(*self, (const char **)&args, &args_length, 1)))
-    {
-      *error= memcached_set_error(*self, rc, MEMCACHED_AT);
-      return NULL;
-    }
-  }
-
-  WATCHPOINT_ASSERT(error);
-
-  memcached_stat_st *stats= libmemcached_xcalloc(self, memcached_server_count(self), memcached_stat_st);
-  if (stats == NULL)
-  {
-    *error= memcached_set_error(*self, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-    return NULL;
-  }
-
-  WATCHPOINT_ASSERT(rc == MEMCACHED_SUCCESS);
-  rc= MEMCACHED_SUCCESS;
-  for (uint32_t x= 0; x < memcached_server_count(self); x++)
-  {
-    memcached_stat_st* stat_instance= stats +x;
-
-    stat_instance->pid= -1;
-    stat_instance->root= self;
-
-    memcached_instance_st* instance= memcached_instance_fetch(self, x);
-
-    memcached_return_t temp_return;
-    if (memcached_is_binary(self))
-    {
-      temp_return= binary_stats_fetch(stat_instance, args, args_length, instance, NULL);
-    }
-    else
-    {
-      temp_return= ascii_stats_fetch(stat_instance, args, args_length, instance, NULL);
-    }
-
-    // Special case where "args" is invalid
-    if (temp_return == MEMCACHED_INVALID_ARGUMENTS)
-    {
-      rc= MEMCACHED_INVALID_ARGUMENTS;
-      break;
-    }
-
-    if (memcached_failed(temp_return))
-    {
-      rc= MEMCACHED_SOME_ERRORS;
-    }
-  }
-
-  *error= rc;
-
-  return stats;
-}
-
-memcached_return_t memcached_stat_servername(memcached_stat_st *memc_stat, char *args,
-                                             const char *hostname, in_port_t port)
-{
-  memcached_st memc;
-
-  memcached_stat_st unused_memc_stat;
-  if (memc_stat == NULL)
-  {
-    memc_stat= &unused_memc_stat;
-  }
-
-  memset(memc_stat, 0, sizeof(memcached_stat_st));
-
-  memcached_st *memc_ptr= memcached_create(&memc);
-  if (memc_ptr == NULL)
-  {
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-  }
-
-  memcached_return_t rc;
-  if (memcached_failed(rc= memcached_server_add(&memc, hostname, port)))
-  {
-    memcached_free(&memc);
-    return rc;
-  }
-
-  if (memcached_success(rc= initialize_query(memc_ptr, true)))
-  {
-    size_t args_length= 0;
-    if (args)
-    {
-      args_length= strlen(args);
-      rc= memcached_key_test(*memc_ptr, (const char **)&args, &args_length, 1);
-    }
-
-    if (memcached_success(rc))
-    {
-      memcached_instance_st* instance= memcached_instance_fetch(memc_ptr, 0);
-      if (memc.flags.binary_protocol)
-      {
-        rc= binary_stats_fetch(memc_stat, args, args_length, instance, NULL);
-      }
-      else
-      {
-        rc= ascii_stats_fetch(memc_stat, args, args_length, instance, NULL);
-      }
-    }
-  }
-
-  memcached_free(&memc);
-
-  return rc;
-}
-
-/*
-  We make a copy of the keys since at some point in the not so distant future
-  we will add support for "found" keys.
-*/
-char ** memcached_stat_get_keys(memcached_st *shell,
-                                memcached_stat_st *,
-                                memcached_return_t *error)
-{
-  Memcached* memc= memcached2Memcached(shell);
-  if (memc)
-  {
-    char **list= static_cast<char **>(libmemcached_malloc(memc, sizeof(memcached_stat_keys)));
-    if (list == NULL)
-    {
-      if (error)
-      {
-        *error= memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-      }
-
-      return NULL;
-    }
-
-    memcpy(list, memcached_stat_keys, sizeof(memcached_stat_keys));
-
-    if (error)
-    {
-      *error= MEMCACHED_SUCCESS;
-    }
-
-    return list;
-  }
-
-  return NULL;
-}
-
-void memcached_stat_free(const memcached_st *, memcached_stat_st *memc_stat)
-{
-  WATCHPOINT_ASSERT(memc_stat); // Be polite, but when debugging catch this as an error
-  if (memc_stat)
-  {
-    libmemcached_free(memc_stat->root, memc_stat);
-  }
-}
-
-static memcached_return_t call_stat_fn(memcached_st *memc,
-                                       memcached_instance_st* instance,
-                                       void *context)
-{
-  if (memc)
-  {
-    local_context *check= (struct local_context *)context;
-
-    if (memcached_is_binary(memc))
-    {
-      return binary_stats_fetch(NULL, check->args, check->args_length, instance, check);
-    }
-    else
-    {
-      return ascii_stats_fetch(NULL, check->args, check->args_length, instance, check);
-    }
-  }
-
-  return MEMCACHED_INVALID_ARGUMENTS;
-}
-
-memcached_return_t memcached_stat_execute(memcached_st *shell, const char *args,  memcached_stat_fn func, void *context)
-{
-  Memcached* memc= memcached2Memcached(shell);
-  if (memcached_fatal(memcached_version(memc)))
-  {
-    return memcached_last_error(memc);
-  }
-
- local_context check(func, context, args, args ? strlen(args) : 0);
-
- return memcached_server_execute(memc, call_stat_fn, (void *)&check);
-}
diff --git a/libmemcached/storage.cc b/libmemcached/storage.cc
deleted file mode 100644 (file)
index 61ca827..0000000
+++ /dev/null
@@ -1,580 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libmemcached/common.h>
-
-enum memcached_storage_action_t {
-  SET_OP,
-  REPLACE_OP,
-  ADD_OP,
-  PREPEND_OP,
-  APPEND_OP,
-  CAS_OP
-};
-
-/* Inline this */
-static inline const char *storage_op_string(memcached_storage_action_t verb)
-{
-  switch (verb)
-  {
-  case REPLACE_OP:
-    return "replace ";
-
-  case ADD_OP:
-    return "add ";
-
-  case PREPEND_OP:
-    return "prepend ";
-
-  case APPEND_OP:
-    return "append ";
-
-  case CAS_OP:
-    return "cas ";
-
-  case SET_OP:
-    break;
-  }
-
-  return "set ";
-}
-
-static inline bool can_by_encrypted(const memcached_storage_action_t verb)
-{
-  switch (verb)
-  {
-  case SET_OP:
-  case ADD_OP:
-  case CAS_OP:
-  case REPLACE_OP:
-    return true;
-    
-  case APPEND_OP:
-  case PREPEND_OP:
-    break;
-  }
-
-  return false;
-}
-
-static inline uint8_t get_com_code(const memcached_storage_action_t verb, const bool reply)
-{
-  if (reply == false)
-  {
-    switch (verb)
-    {
-    case SET_OP:
-      return PROTOCOL_BINARY_CMD_SETQ;
-
-    case ADD_OP:
-      return PROTOCOL_BINARY_CMD_ADDQ;
-
-    case CAS_OP: /* FALLTHROUGH */
-    case REPLACE_OP:
-      return PROTOCOL_BINARY_CMD_REPLACEQ;
-
-    case APPEND_OP:
-      return PROTOCOL_BINARY_CMD_APPENDQ;
-
-    case PREPEND_OP:
-      return PROTOCOL_BINARY_CMD_PREPENDQ;
-    }
-  }
-
-  switch (verb)
-  {
-  case SET_OP:
-    break;
-
-  case ADD_OP:
-    return PROTOCOL_BINARY_CMD_ADD;
-
-  case CAS_OP: /* FALLTHROUGH */
-  case REPLACE_OP:
-    return PROTOCOL_BINARY_CMD_REPLACE;
-
-  case APPEND_OP:
-    return PROTOCOL_BINARY_CMD_APPEND;
-
-  case PREPEND_OP:
-    return PROTOCOL_BINARY_CMD_PREPEND;
-  }
-
-  return PROTOCOL_BINARY_CMD_SET;
-}
-
-static memcached_return_t memcached_send_binary(Memcached *ptr,
-                                                memcached_instance_st* server,
-                                                uint32_t server_key,
-                                                const char *key,
-                                                const size_t key_length,
-                                                const char *value,
-                                                const size_t value_length,
-                                                const time_t expiration,
-                                                const uint32_t flags,
-                                                const uint64_t cas,
-                                                const bool flush,
-                                                const bool reply,
-                                                memcached_storage_action_t verb)
-{
-  protocol_binary_request_set request= {};
-  size_t send_length= sizeof(request.bytes);
-
-  initialize_binary_request(server, request.message.header);
-
-  request.message.header.request.opcode= get_com_code(verb, reply);
-  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->_namespace)));
-  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-  if (verb == APPEND_OP or verb == PREPEND_OP)
-  {
-    send_length -= 8; /* append & prepend does not contain extras! */
-  }
-  else
-  {
-    request.message.header.request.extlen= 8;
-    request.message.body.flags= htonl(flags);
-    request.message.body.expiration= htonl((uint32_t)expiration);
-  }
-
-  request.message.header.request.bodylen= htonl((uint32_t) (key_length + memcached_array_size(ptr->_namespace) + value_length +
-                                                            request.message.header.request.extlen));
-
-  if (cas)
-  {
-    request.message.header.request.cas= memcached_htonll(cas);
-  }
-
-  libmemcached_io_vector_st vector[]=
-  {
-    { NULL, 0 },
-    { request.bytes, send_length },
-    { memcached_array_string(ptr->_namespace),  memcached_array_size(ptr->_namespace) },
-    { key, key_length },
-    { value, value_length }
-  };
-
-  /* write the header */
-  memcached_return_t rc;
-  if ((rc= memcached_vdo(server, vector, 5, flush)) != MEMCACHED_SUCCESS)
-  {
-    assert(memcached_last_error(server->root) != MEMCACHED_SUCCESS);
-    return memcached_last_error(server->root);
-  }
-
-  if (verb == SET_OP and ptr->number_of_replicas > 0)
-  {
-    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SETQ;
-    WATCHPOINT_STRING("replicating");
-
-    for (uint32_t x= 0; x < ptr->number_of_replicas; x++)
-    {
-      ++server_key;
-      if (server_key == memcached_server_count(ptr))
-      {
-        server_key= 0;
-      }
-
-      memcached_instance_st* instance= memcached_instance_fetch(ptr, server_key);
-
-      if (memcached_success(memcached_vdo(instance, vector, 5, false)))
-      {
-        memcached_server_response_decrement(instance);
-      }
-    }
-  }
-
-  if (flush == false)
-  {
-    return MEMCACHED_BUFFERED;
-  }
-
-  // No reply always assumes success
-  if (reply == false)
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  return memcached_response(server, NULL, 0, NULL);
-}
-
-static memcached_return_t memcached_send_ascii(Memcached *ptr,
-                                               memcached_instance_st* instance,
-                                               const char *key,
-                                               const size_t key_length,
-                                               const char *value,
-                                               const size_t value_length,
-                                               const time_t expiration,
-                                               const uint32_t flags,
-                                               const uint64_t cas,
-                                               const bool flush,
-                                               const bool reply,
-                                               const memcached_storage_action_t verb)
-{
-  char flags_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
-  int flags_buffer_length= snprintf(flags_buffer, sizeof(flags_buffer), " %u", flags);
-  if (size_t(flags_buffer_length) >= sizeof(flags_buffer) or flags_buffer_length < 0)
-  {
-    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                               memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
-  }
-
-  char expiration_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
-  int expiration_buffer_length= snprintf(expiration_buffer, sizeof(expiration_buffer), " %llu", (unsigned long long)expiration);
-  if (size_t(expiration_buffer_length) >= sizeof(expiration_buffer) or expiration_buffer_length < 0)
-  {
-    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                               memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
-  }
-
-  char value_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
-  int value_buffer_length= snprintf(value_buffer, sizeof(value_buffer), " %llu", (unsigned long long)value_length);
-  if (size_t(value_buffer_length) >= sizeof(value_buffer) or value_buffer_length < 0)
-  {
-    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                               memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
-  }
-
-  char cas_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
-  int cas_buffer_length= 0;
-  if (cas)
-  {
-    cas_buffer_length= snprintf(cas_buffer, sizeof(cas_buffer), " %llu", (unsigned long long)cas);
-    if (size_t(cas_buffer_length) >= sizeof(cas_buffer) or cas_buffer_length < 0)
-    {
-      return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                                 memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
-    }
-  }
-
-  libmemcached_io_vector_st vector[]=
-  {
-    { NULL, 0 },
-    { storage_op_string(verb), strlen(storage_op_string(verb))},
-    { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
-    { key, key_length },
-    { flags_buffer, size_t(flags_buffer_length) },
-    { expiration_buffer, size_t(expiration_buffer_length) },
-    { value_buffer, size_t(value_buffer_length) },
-    { cas_buffer, size_t(cas_buffer_length) },
-    { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
-    { memcached_literal_param("\r\n") },
-    { value, value_length },
-    { memcached_literal_param("\r\n") }
-  };
-
-  /* Send command header */
-  memcached_return_t rc=  memcached_vdo(instance, vector, 12, flush);
-
-  // If we should not reply, return with MEMCACHED_SUCCESS, unless error
-  if (reply == false)
-  {
-    return memcached_success(rc) ? MEMCACHED_SUCCESS : rc; 
-  }
-
-  if (flush == false)
-  {
-    return memcached_success(rc) ? MEMCACHED_BUFFERED : rc; 
-  }
-
-  if (rc == MEMCACHED_SUCCESS)
-  {
-    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-    rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
-
-    if (rc == MEMCACHED_STORED)
-    {
-      return MEMCACHED_SUCCESS;
-    }
-  }
-
-  assert(memcached_failed(rc));
-#if 0
-  if (memcached_has_error(ptr) == false)
-  {
-    return memcached_set_error(*ptr, rc, MEMCACHED_AT);
-  }
-#endif
-
-  return rc;
-}
-
-static inline memcached_return_t memcached_send(memcached_st *shell,
-                                                const char *group_key, size_t group_key_length,
-                                                const char *key, size_t key_length,
-                                                const char *value, size_t value_length,
-                                                const time_t expiration,
-                                                const uint32_t flags,
-                                                const uint64_t cas,
-                                                memcached_storage_action_t verb)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr, true)))
-  {
-    return rc;
-  }
-
-  if (memcached_failed(memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
-  {
-    return memcached_last_error(ptr);
-  }
-
-  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
-  memcached_instance_st* instance= memcached_instance_fetch(ptr, server_key);
-
-  WATCHPOINT_SET(instance->io_wait_count.read= 0);
-  WATCHPOINT_SET(instance->io_wait_count.write= 0);
-
-  bool flush= true;
-  if (memcached_is_buffering(instance->root) and verb == SET_OP)
-  {
-    flush= false;
-  }
-
-  bool reply= memcached_is_replying(ptr);
-
-  hashkit_string_st* destination= NULL;
-
-  if (memcached_is_encrypted(ptr))
-  {
-    if (can_by_encrypted(verb) == false)
-    {
-      return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, 
-                                 memcached_literal_param("Operation not allowed while encyrption is enabled"));
-    }
-
-    if ((destination= hashkit_encrypt(&ptr->hashkit, value, value_length)) == NULL)
-    {
-      return rc;
-    }
-    value= hashkit_string_c_str(destination);
-    value_length= hashkit_string_length(destination);
-  }
-
-  if (memcached_is_binary(ptr))
-  {
-    rc= memcached_send_binary(ptr, instance, server_key,
-                              key, key_length,
-                              value, value_length, expiration,
-                              flags, cas, flush, reply, verb);
-  }
-  else
-  {
-    rc= memcached_send_ascii(ptr, instance,
-                             key, key_length,
-                             value, value_length, expiration,
-                             flags, cas, flush, reply, verb);
-  }
-
-  hashkit_string_free(destination);
-
-  return rc;
-}
-
-
-memcached_return_t memcached_set(memcached_st *ptr, const char *key, size_t key_length,
-                                 const char *value, size_t value_length,
-                                 time_t expiration,
-                                 uint32_t flags)
-{
-  memcached_return_t rc;
-  LIBMEMCACHED_MEMCACHED_SET_START();
-  rc= memcached_send(ptr, key, key_length,
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, SET_OP);
-  LIBMEMCACHED_MEMCACHED_SET_END();
-  return rc;
-}
-
-memcached_return_t memcached_add(memcached_st *ptr,
-                                 const char *key, size_t key_length,
-                                 const char *value, size_t value_length,
-                                 time_t expiration,
-                                 uint32_t flags)
-{
-  memcached_return_t rc;
-  LIBMEMCACHED_MEMCACHED_ADD_START();
-  rc= memcached_send(ptr, key, key_length,
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, ADD_OP);
-
-  LIBMEMCACHED_MEMCACHED_ADD_END();
-  return rc;
-}
-
-memcached_return_t memcached_replace(memcached_st *ptr,
-                                     const char *key, size_t key_length,
-                                     const char *value, size_t value_length,
-                                     time_t expiration,
-                                     uint32_t flags)
-{
-  memcached_return_t rc;
-  LIBMEMCACHED_MEMCACHED_REPLACE_START();
-  rc= memcached_send(ptr, key, key_length,
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, REPLACE_OP);
-  LIBMEMCACHED_MEMCACHED_REPLACE_END();
-  return rc;
-}
-
-memcached_return_t memcached_prepend(memcached_st *ptr,
-                                     const char *key, size_t key_length,
-                                     const char *value, size_t value_length,
-                                     time_t expiration,
-                                     uint32_t flags)
-{
-  memcached_return_t rc;
-  rc= memcached_send(ptr, key, key_length,
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, PREPEND_OP);
-  return rc;
-}
-
-memcached_return_t memcached_append(memcached_st *ptr,
-                                    const char *key, size_t key_length,
-                                    const char *value, size_t value_length,
-                                    time_t expiration,
-                                    uint32_t flags)
-{
-  memcached_return_t rc;
-  rc= memcached_send(ptr, key, key_length,
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, APPEND_OP);
-  return rc;
-}
-
-memcached_return_t memcached_cas(memcached_st *ptr,
-                                 const char *key, size_t key_length,
-                                 const char *value, size_t value_length,
-                                 time_t expiration,
-                                 uint32_t flags,
-                                 uint64_t cas)
-{
-  memcached_return_t rc;
-  rc= memcached_send(ptr, key, key_length,
-                     key, key_length, value, value_length,
-                     expiration, flags, cas, CAS_OP);
-  return rc;
-}
-
-memcached_return_t memcached_set_by_key(memcached_st *ptr,
-                                        const char *group_key,
-                                        size_t group_key_length,
-                                        const char *key, size_t key_length,
-                                        const char *value, size_t value_length,
-                                        time_t expiration,
-                                        uint32_t flags)
-{
-  memcached_return_t rc;
-  LIBMEMCACHED_MEMCACHED_SET_START();
-  rc= memcached_send(ptr, group_key, group_key_length,
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, SET_OP);
-  LIBMEMCACHED_MEMCACHED_SET_END();
-  return rc;
-}
-
-memcached_return_t memcached_add_by_key(memcached_st *ptr,
-                                        const char *group_key, size_t group_key_length,
-                                        const char *key, size_t key_length,
-                                        const char *value, size_t value_length,
-                                        time_t expiration,
-                                        uint32_t flags)
-{
-  memcached_return_t rc;
-  LIBMEMCACHED_MEMCACHED_ADD_START();
-  rc= memcached_send(ptr, group_key, group_key_length,
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, ADD_OP);
-  LIBMEMCACHED_MEMCACHED_ADD_END();
-  return rc;
-}
-
-memcached_return_t memcached_replace_by_key(memcached_st *ptr,
-                                            const char *group_key, size_t group_key_length,
-                                            const char *key, size_t key_length,
-                                            const char *value, size_t value_length,
-                                            time_t expiration,
-                                            uint32_t flags)
-{
-  memcached_return_t rc;
-  LIBMEMCACHED_MEMCACHED_REPLACE_START();
-  rc= memcached_send(ptr, group_key, group_key_length,
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, REPLACE_OP);
-  LIBMEMCACHED_MEMCACHED_REPLACE_END();
-  return rc;
-}
-
-memcached_return_t memcached_prepend_by_key(memcached_st *ptr,
-                                            const char *group_key, size_t group_key_length,
-                                            const char *key, size_t key_length,
-                                            const char *value, size_t value_length,
-                                            time_t expiration,
-                                            uint32_t flags)
-{
-  return memcached_send(ptr, group_key, group_key_length,
-                        key, key_length, value, value_length,
-                        expiration, flags, 0, PREPEND_OP);
-}
-
-memcached_return_t memcached_append_by_key(memcached_st *ptr,
-                                           const char *group_key, size_t group_key_length,
-                                           const char *key, size_t key_length,
-                                           const char *value, size_t value_length,
-                                           time_t expiration,
-                                           uint32_t flags)
-{
-  return memcached_send(ptr, group_key, group_key_length,
-                        key, key_length, value, value_length,
-                        expiration, flags, 0, APPEND_OP);
-}
-
-memcached_return_t memcached_cas_by_key(memcached_st *ptr,
-                                        const char *group_key, size_t group_key_length,
-                                        const char *key, size_t key_length,
-                                        const char *value, size_t value_length,
-                                        time_t expiration,
-                                        uint32_t flags,
-                                        uint64_t cas)
-{
-  return  memcached_send(ptr, group_key, group_key_length,
-                         key, key_length, value, value_length,
-                         expiration, flags, cas, CAS_OP);
-}
-
diff --git a/libmemcached/strerror.cc b/libmemcached/strerror.cc
deleted file mode 100644 (file)
index c5615ca..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-const char *memcached_strerror(const memcached_st *, memcached_return_t rc)
-{
-  switch (rc)
-  {
-  case MEMCACHED_SUCCESS:
-    return "SUCCESS";
-
-  case MEMCACHED_FAILURE:
-    return "FAILURE";
-
-  case MEMCACHED_HOST_LOOKUP_FAILURE: // getaddrinfo only
-    return "getaddrinfo() or getnameinfo() HOSTNAME LOOKUP FAILURE";
-
-  case MEMCACHED_CONNECTION_FAILURE:
-    return "CONNECTION FAILURE";
-
-  case MEMCACHED_CONNECTION_BIND_FAILURE: // DEPRECATED, see MEMCACHED_HOST_LOOKUP_FAILURE
-    return "CONNECTION BIND FAILURE";
-
-  case MEMCACHED_READ_FAILURE:
-    return "READ FAILURE";
-
-  case MEMCACHED_UNKNOWN_READ_FAILURE:
-    return "UNKNOWN READ FAILURE";
-
-  case MEMCACHED_PROTOCOL_ERROR:
-    return "PROTOCOL ERROR";
-
-  case MEMCACHED_CLIENT_ERROR:
-    return "CLIENT ERROR";
-
-  case MEMCACHED_SERVER_ERROR:
-    return "SERVER ERROR";
-
-  case MEMCACHED_WRITE_FAILURE:
-    return "WRITE FAILURE";
-
-  case MEMCACHED_ERROR:
-    return "ERROR was returned by server";
-
-  case MEMCACHED_DATA_EXISTS:
-    return "CONNECTION DATA EXISTS";
-
-  case MEMCACHED_DATA_DOES_NOT_EXIST:
-    return "CONNECTION DATA DOES NOT EXIST";
-
-  case MEMCACHED_NOTSTORED:
-    return "NOT STORED";
-
-  case MEMCACHED_STORED:
-    return "STORED";
-
-  case MEMCACHED_NOTFOUND:
-    return "NOT FOUND";
-
-  case MEMCACHED_MEMORY_ALLOCATION_FAILURE:
-    return "MEMORY ALLOCATION FAILURE";
-
-  case MEMCACHED_PARTIAL_READ:
-    return "PARTIAL READ";
-
-  case MEMCACHED_SOME_ERRORS:
-    return "SOME ERRORS WERE REPORTED";
-
-  case MEMCACHED_NO_SERVERS:
-    return "NO SERVERS DEFINED";
-
-  case MEMCACHED_END:
-    return "SERVER END";
-
-  case MEMCACHED_DELETED:
-    return "SERVER DELETE";
-
-  case MEMCACHED_VALUE:
-    return "SERVER VALUE";
-
-  case MEMCACHED_STAT:
-    return "STAT VALUE";
-
-  case MEMCACHED_ITEM:
-    return "ITEM VALUE";
-
-  case MEMCACHED_ERRNO:
-    return "SYSTEM ERROR";
-
-  case MEMCACHED_FAIL_UNIX_SOCKET:
-    return "COULD NOT OPEN UNIX SOCKET";
-
-  case MEMCACHED_NOT_SUPPORTED:
-    return "ACTION NOT SUPPORTED";
-
-  case MEMCACHED_FETCH_NOTFINISHED:
-    return "FETCH WAS NOT COMPLETED";
-
-  case MEMCACHED_NO_KEY_PROVIDED:
-    return "A KEY LENGTH OF ZERO WAS PROVIDED";
-
-  case MEMCACHED_BUFFERED:
-    return "ACTION QUEUED";
-
-  case MEMCACHED_TIMEOUT:
-    return "A TIMEOUT OCCURRED";
-
-  case MEMCACHED_BAD_KEY_PROVIDED:
-    return "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE";
-
-  case MEMCACHED_INVALID_HOST_PROTOCOL:
-    return "THE HOST TRANSPORT PROTOCOL DOES NOT MATCH THAT OF THE CLIENT";
-
-  case MEMCACHED_SERVER_MARKED_DEAD:
-    return "SERVER IS MARKED DEAD";
-
-  case MEMCACHED_UNKNOWN_STAT_KEY:
-    return "ENCOUNTERED AN UNKNOWN STAT KEY";
-
-  case MEMCACHED_E2BIG:
-    return "ITEM TOO BIG";
-
-  case MEMCACHED_INVALID_ARGUMENTS:
-     return "INVALID ARGUMENTS";
-
-  case MEMCACHED_KEY_TOO_BIG:
-     return "KEY RETURNED FROM SERVER WAS TOO LARGE";
-
-  case MEMCACHED_AUTH_PROBLEM:
-    return "FAILED TO SEND AUTHENTICATION TO SERVER";
-
-  case MEMCACHED_AUTH_FAILURE:
-    return "AUTHENTICATION FAILURE";
-
-  case MEMCACHED_AUTH_CONTINUE:
-    return "CONTINUE AUTHENTICATION";
-
-  case MEMCACHED_PARSE_ERROR:
-    return "ERROR OCCURED WHILE PARSING";
-
-  case MEMCACHED_PARSE_USER_ERROR:
-    return "USER INITIATED ERROR OCCURED WHILE PARSING";
-
-  case MEMCACHED_DEPRECATED:
-    return "DEPRECATED";
-
-  case MEMCACHED_IN_PROGRESS:
-    return "OPERATION IN PROCESS";
-
-  case MEMCACHED_SERVER_TEMPORARILY_DISABLED:
-    return "SERVER HAS FAILED AND IS DISABLED UNTIL TIMED RETRY";
-
-  case MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE:
-    return "SERVER FAILED TO ALLOCATE OBJECT";
-
-  case MEMCACHED_UNIX_SOCKET_PATH_TOO_BIG:
-    return "UNIX SOCKET PATH TOO LARGE";
-
-  default:
-  case MEMCACHED_MAXIMUM_RETURN:
-    return "INVALID memcached_return_t";
-  }
-}
diff --git a/libmemcached/string.cc b/libmemcached/string.cc
deleted file mode 100644 (file)
index b821aca..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libmemcached/common.h>
-
-inline static memcached_return_t _string_check(memcached_string_st *string, size_t need)
-{
-  if (need && need > (size_t)(string->current_size - (size_t)(string->end - string->string)))
-  {
-    size_t current_offset= (size_t) (string->end - string->string);
-
-    /* This is the block multiplier. To keep it larger and surive division errors we must round it up */
-    size_t adjust= (need - (size_t)(string->current_size - (size_t)(string->end - string->string))) / MEMCACHED_BLOCK_SIZE;
-    adjust++;
-
-    size_t new_size= sizeof(char) * (size_t)((adjust * MEMCACHED_BLOCK_SIZE) + string->current_size);
-    /* Test for overflow */
-    if (new_size < need)
-    {
-      char error_message[1024];
-      int error_message_length= snprintf(error_message, sizeof(error_message),"Needed %ld, got %ld", (long)need, (long)new_size);
-      return memcached_set_error(*string->root, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, error_message, error_message_length);
-    }
-
-    char *new_value= libmemcached_xrealloc(string->root, string->string, new_size, char);
-
-    if (new_value == NULL)
-    {
-      return memcached_set_error(*string->root, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-    }
-
-    string->string= new_value;
-    string->end= string->string + current_offset;
-
-    string->current_size+= (MEMCACHED_BLOCK_SIZE * adjust);
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-static inline void _init_string(memcached_string_st *self)
-{
-  self->current_size= 0;
-  self->end= self->string= NULL;
-}
-
-memcached_string_st *memcached_string_create(Memcached *memc, memcached_string_st *self, size_t initial_size)
-{
-  WATCHPOINT_ASSERT(memc);
-
-  /* Saving malloc calls :) */
-  if (self)
-  {
-    WATCHPOINT_ASSERT(self->options.is_initialized == false);
-
-    memcached_set_allocated(self, false);
-  }
-  else
-  {
-    self= libmemcached_xmalloc(memc, memcached_string_st);
-
-    if (self == NULL)
-    {
-      return NULL;
-    }
-
-    memcached_set_allocated(self, true);
-  }
-  self->root= memc;
-
-  _init_string(self);
-
-  if (memcached_failed(_string_check(self, initial_size)))
-  {
-    if (memcached_is_allocated(self))
-    {
-      libmemcached_free(memc, self);
-    }
-
-    return NULL;
-  }
-
-  memcached_set_initialized(self, true);
-
-  WATCHPOINT_ASSERT(self->string == self->end);
-
-  return self;
-}
-
-static memcached_return_t memcached_string_append_null(memcached_string_st& string)
-{
-  if (memcached_failed(_string_check(&string, 1)))
-  {
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-  }
-
-  *string.end= 0;
-
-  return MEMCACHED_SUCCESS;
-}
-
-static memcached_return_t memcached_string_append_null(memcached_string_st *string)
-{
-  if (memcached_failed(_string_check(string, 1)))
-  {
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-  }
-
-  *string->end= 0;
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_string_append_character(memcached_string_st *string,
-                                                     char character)
-{
-  if (memcached_failed(_string_check(string, 1)))
-  {
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-  }
-
-  *string->end= character;
-  string->end++;
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_string_append(memcached_string_st *string,
-                                           const char *value, size_t length)
-{
-  if (memcached_failed(_string_check(string, length)))
-  {
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-  }
-
-  WATCHPOINT_ASSERT(length <= string->current_size);
-  WATCHPOINT_ASSERT(string->string);
-  WATCHPOINT_ASSERT(string->end >= string->string);
-
-  memcpy(string->end, value, length);
-  string->end+= length;
-
-  return MEMCACHED_SUCCESS;
-}
-
-char *memcached_string_c_copy(memcached_string_st *string)
-{
-  if (memcached_string_length(string) == 0)
-  {
-    return NULL;
-  }
-
-  char *c_ptr= static_cast<char *>(libmemcached_malloc(string->root, (memcached_string_length(string)+1) * sizeof(char)));
-
-  if (c_ptr == NULL)
-  {
-    return NULL;
-  }
-
-  memcpy(c_ptr, memcached_string_value(string), memcached_string_length(string));
-  c_ptr[memcached_string_length(string)]= 0;
-
-  return c_ptr;
-}
-
-bool memcached_string_set(memcached_string_st& string, const char* value, size_t length)
-{
-  memcached_string_reset(&string);
-  if (memcached_success(memcached_string_append(&string, value, length)))
-  {
-    memcached_string_append_null(string);
-    return true;
-  }
-
-  return false;
-}
-
-void memcached_string_reset(memcached_string_st *string)
-{
-  string->end= string->string;
-}
-
-void memcached_string_free(memcached_string_st& ptr)
-{
-  memcached_string_free(&ptr);
-}
-
-void memcached_string_free(memcached_string_st *ptr)
-{
-  if (ptr == NULL)
-  {
-    return;
-  }
-
-  if (ptr->string)
-  {
-    libmemcached_free(ptr->root, ptr->string);
-  }
-
-  if (memcached_is_allocated(ptr))
-  {
-    libmemcached_free(ptr->root, ptr);
-  }
-  else
-  {
-    ptr->options.is_initialized= false;
-  }
-}
-
-memcached_return_t memcached_string_check(memcached_string_st *string, size_t need)
-{
-  return _string_check(string, need);
-}
-
-bool memcached_string_resize(memcached_string_st& string, const size_t need)
-{
-  return memcached_success(_string_check(&string, need));
-}
-
-size_t memcached_string_length(const memcached_string_st *self)
-{
-  return size_t(self->end -self->string);
-}
-
-size_t memcached_string_length(const memcached_string_st& self)
-{
-  return size_t(self.end -self.string);
-}
-
-size_t memcached_string_size(const memcached_string_st *self)
-{
-  return self->current_size;
-}
-
-const char *memcached_string_value(const memcached_string_st *self)
-{
-  return self->string;
-}
-
-const char *memcached_string_value(const memcached_string_st& self)
-{
-  return self.string;
-}
-
-char *memcached_string_take_value(memcached_string_st *self)
-{
-  char* value= NULL;
-
-  assert_msg(self, "Invalid memcached_string_st");
-  if (self)
-  {
-    if (memcached_string_length(self))
-    {
-      // If we fail at adding the null, we copy and move on
-      if (memcached_failed(memcached_string_append_null(self)))
-      {
-        return NULL;
-      }
-
-      value= self->string;
-      _init_string(self);
-    }
-  }
-
-  return value;
-}
-
-char *memcached_string_value_mutable(const memcached_string_st *self)
-{
-  return self->string;
-}
-
-char *memcached_string_c_str(memcached_string_st& self)
-{
-  return self.string;
-}
-
-void memcached_string_set_length(memcached_string_st *self, size_t length)
-{
-  self->end= self->string +length;
-}
-
-void memcached_string_set_length(memcached_string_st& self, const size_t length)
-{
-  assert(self.current_size >= length);
-  size_t set_length= length;
-  if (self.current_size > length)
-  {
-    if (memcached_failed(_string_check(&self, length)))
-    {
-      set_length= self.current_size;
-    }
-  }
-  self.end= self.string +set_length;
-}
diff --git a/libmemcached/string.hpp b/libmemcached/string.hpp
deleted file mode 100644 (file)
index e2978cc..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  libmcachedd client library.
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include "util/string.hpp"
-
-#define memcached_literal_param util_literal_param
-#define memcached_literal_param_size util_literal_param_size
-#define memcached_string_make_from_cstr util_string_make_from_cstr
-#define memcached_array_length util_array_length
-
-/**
-  Strings are always under our control so we make some assumptions
-  about them.
-
-  1) is_initialized is always valid.
-  2) A string once intialized will always be, until free where we
-     unset this flag.
-  3) A string always has a root.
-*/
-
-memcached_string_st *memcached_string_create(memcached_st *ptr,
-                                             memcached_string_st *string,
-                                             size_t initial_size);
-
-memcached_return_t memcached_string_check(memcached_string_st *string, size_t need);
-
-char *memcached_string_c_copy(memcached_string_st *string);
-
-memcached_return_t memcached_string_append_character(memcached_string_st *string,
-                                                     char character);
-
-memcached_return_t memcached_string_append(memcached_string_st *string,
-                                           const char *value, size_t length);
-
-void memcached_string_reset(memcached_string_st *string);
-
-void memcached_string_free(memcached_string_st *string);
-void memcached_string_free(memcached_string_st&);
-
-size_t memcached_string_length(const memcached_string_st *self);
-size_t memcached_string_length(const memcached_string_st&);
-
-size_t memcached_string_size(const memcached_string_st *self);
-
-const char *memcached_string_value(const memcached_string_st *self);
-const char *memcached_string_value(const memcached_string_st&);
-
-char *memcached_string_take_value(memcached_string_st *self);
-
-char *memcached_string_value_mutable(const memcached_string_st *self);
-
-bool memcached_string_set(memcached_string_st&, const char*, size_t);
-
-void memcached_string_set_length(memcached_string_st *self, size_t length);
-void memcached_string_set_length(memcached_string_st&, const size_t length);
-
-bool memcached_string_resize(memcached_string_st&, const size_t);
-char *memcached_string_c_str(memcached_string_st&);
diff --git a/libmemcached/touch.cc b/libmemcached/touch.cc
deleted file mode 100644 (file)
index 9e9cbd6..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-static memcached_return_t ascii_touch(memcached_instance_st* instance,
-                                      const char *key, size_t key_length,
-                                      time_t expiration)
-{
-  char expiration_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
-  int expiration_buffer_length= snprintf(expiration_buffer, sizeof(expiration_buffer), " %llu", (unsigned long long)expiration);
-  if (size_t(expiration_buffer_length) >= sizeof(expiration_buffer)+1 or expiration_buffer_length < 0)
-  {
-    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                               memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
-  }
-
-  libmemcached_io_vector_st vector[]=
-  {
-    { NULL, 0 },
-    { memcached_literal_param("touch ") },
-    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
-    { key, key_length },
-    { expiration_buffer, size_t(expiration_buffer_length) },
-    { memcached_literal_param("\r\n") }
-  };
-
-  memcached_return_t rc;
-  if (memcached_failed(rc= memcached_vdo(instance, vector, 6, true)))
-  {
-    return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
-  }
-
-  return rc;
-}
-
-static memcached_return_t binary_touch(memcached_instance_st* instance,
-                                       const char *key, size_t key_length,
-                                       time_t expiration)
-{
-  protocol_binary_request_touch request= {}; //{.bytes= {0}};
-
-  initialize_binary_request(instance, request.message.header);
-
-  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_TOUCH;
-  request.message.header.request.extlen= 4;
-  request.message.header.request.keylen= htons((uint16_t)(key_length +memcached_array_size(instance->root->_namespace)));
-  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-  request.message.header.request.bodylen= htonl((uint32_t)(key_length +memcached_array_size(instance->root->_namespace) +request.message.header.request.extlen));
-  request.message.body.expiration= htonl((uint32_t) expiration);
-
-  libmemcached_io_vector_st vector[]=
-  {
-    { NULL, 0 },
-    { request.bytes, sizeof(request.bytes) },
-    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
-    { key, key_length }
-  };
-
-  memcached_return_t rc;
-  if (memcached_failed(rc= memcached_vdo(instance, vector, 4, true)))
-  {
-    return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
-  }
-
-  return rc;
-}
-
-memcached_return_t memcached_touch(memcached_st *ptr,
-                                   const char *key, size_t key_length,
-                                   time_t expiration)
-{
-  return memcached_touch_by_key(ptr, key, key_length, key, key_length, expiration);
-}
-
-memcached_return_t memcached_touch_by_key(memcached_st *shell,
-                                          const char *group_key, size_t group_key_length,
-                                          const char *key, size_t key_length,
-                                          time_t expiration)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  LIBMEMCACHED_MEMCACHED_TOUCH_START();
-
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr, true)))
-  {
-    return rc;
-  }
-
-  if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
-  {
-    return memcached_set_error(*ptr, rc, MEMCACHED_AT);
-  }
-
-  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
-  memcached_instance_st* instance= memcached_instance_fetch(ptr, server_key);
-
-  if (ptr->flags.binary_protocol)
-  {
-    rc= binary_touch(instance, key, key_length, expiration);
-  }
-  else
-  {
-    rc= ascii_touch(instance, key, key_length, expiration);
-  }
-
-  if (memcached_failed(rc))
-  {
-    return memcached_set_error(*instance, rc, MEMCACHED_AT, memcached_literal_param("Error occcured while writing touch command to server"));
-  }
-
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
-
-  if (rc == MEMCACHED_SUCCESS or rc == MEMCACHED_NOTFOUND)
-  {
-    return rc;
-  }
-
-  return memcached_set_error(*instance, rc, MEMCACHED_AT, memcached_literal_param("Error occcured while reading response"));
-}
diff --git a/libmemcached/udp.cc b/libmemcached/udp.cc
deleted file mode 100644 (file)
index 5d21f9f..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-/*
- * The udp request id consists of two seperate sections
- *   1) The thread id
- *   2) The message number
- * The thread id should only be set when the memcached_st struct is created
- * and should not be changed.
- *
- * The message num is incremented for each new message we send, this function
- * extracts the message number from message_id, increments it and then
- * writes the new value back into the header
- */
-void increment_udp_message_id(memcached_instance_st* ptr)
-{
-  struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
-  uint16_t cur_req= get_udp_datagram_request_id(header);
-  int msg_num= get_msg_num_from_request_id(cur_req);
-  int thread_id= get_thread_id_from_request_id(cur_req);
-
-  if (((++msg_num) & UDP_REQUEST_ID_THREAD_MASK) != 0)
-    msg_num= 0;
-
-  header->request_id= htons((uint16_t) (thread_id | msg_num));
-}
-
-bool memcached_io_init_udp_header(memcached_instance_st* ptr, const uint16_t thread_id)
-{
-  if (thread_id > UDP_REQUEST_ID_MAX_THREAD_ID)
-  {
-    return MEMCACHED_FAILURE;
-  }
-
-  struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
-  header->request_id= htons(uint16_t((generate_udp_request_thread_id(thread_id))));
-  header->num_datagrams= htons(1);
-  header->sequence_number= htons(0);
-
-  return MEMCACHED_SUCCESS;
-}
diff --git a/libmemcached/udp.hpp b/libmemcached/udp.hpp
deleted file mode 100644 (file)
index 7442c59..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#define MAX_UDP_DATAGRAM_LENGTH 1400
-#define UDP_DATAGRAM_HEADER_LENGTH 8
-#define UDP_REQUEST_ID_MSG_SIG_DIGITS 10
-#define UDP_REQUEST_ID_THREAD_MASK 0xFFFF << UDP_REQUEST_ID_MSG_SIG_DIGITS
-#define get_udp_datagram_request_id(A) ntohs((A)->request_id)
-#define get_udp_datagram_seq_num(A) ntohs((A)->sequence_number)
-#define get_udp_datagram_num_datagrams(A) ntohs((A)->num_datagrams)
-#define get_msg_num_from_request_id(A) ( (A) & (~(UDP_REQUEST_ID_THREAD_MASK)) )
-#define get_thread_id_from_request_id(A) ( (A) & (UDP_REQUEST_ID_THREAD_MASK) ) >> UDP_REQUEST_ID_MSG_SIG_DIGITS
-#define generate_udp_request_thread_id(A) (A) << UDP_REQUEST_ID_MSG_SIG_DIGITS
-#define UDP_REQUEST_ID_MAX_THREAD_ID get_thread_id_from_request_id(0xFFFF)
-
-struct udp_datagram_header_st
-{
-  uint16_t request_id;
-  uint16_t sequence_number;
-  uint16_t num_datagrams;
-  uint16_t reserved;
-};
-
-bool memcached_io_init_udp_header(memcached_instance_st*, const uint16_t thread_id);
-void increment_udp_message_id(memcached_instance_st*);
diff --git a/libmemcached/util.h b/libmemcached/util.h
deleted file mode 100644 (file)
index 03ed6da..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <libmemcachedutil-1.0/util.h>
-
diff --git a/libmemcached/util/Makefile.am b/libmemcached/util/Makefile.am
deleted file mode 100644 (file)
index bbb94dd..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-EXTRA_DIST= libmemcachedutil.ver
-
-lib_LTLIBRARIES=
-
-if BUILD_LIBMEMCACHEDUTIL
-lib_LTLIBRARIES+= libmemcachedutil.la
-endif
-
-libmemcachedutil_la_SOURCES= memcached_pool.c
-libmemcachedutil_la_LDFLAGS= -version-info $(MEMCACHEDUTIL_LIBRARY_VERSION) $(LD_UTIL_VERSION_SCRIPT)
-libmemcachedutil_la_LIBADD= ${top_builddir}/libmemcached/libmemcached.la
diff --git a/libmemcached/verbosity.cc b/libmemcached/verbosity.cc
deleted file mode 100644 (file)
index 43d7374..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-struct context_st
-{
-  size_t length;
-  const char *buffer;
-};
-
-static memcached_return_t _set_verbosity(const Memcached *,
-                                         const memcached_instance_st * server,
-                                         void *context)
-{
- libmemcached_io_vector_st *vector= (libmemcached_io_vector_st *)context;
-
-  Memcached local_memc;
-  Memcached *memc_ptr= memcached_create(&local_memc);
-
-  memcached_return_t rc= memcached_server_add(memc_ptr, memcached_server_name(server), memcached_server_port(server));
-
-  if (rc == MEMCACHED_SUCCESS)
-  {
-    memcached_instance_st* instance= memcached_instance_fetch(memc_ptr, 0);
-
-    rc= memcached_vdo(instance, vector, 2, true);
-
-    if (rc == MEMCACHED_SUCCESS)
-    {
-      char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-      rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
-    }
-  }
-
-  memcached_free(memc_ptr);
-
-  return rc;
-}
-
-memcached_return_t memcached_verbosity(memcached_st *shell, uint32_t verbosity)
-{
-  Memcached* ptr= memcached2Memcached(shell);
-  memcached_return_t rc;
-  if (memcached_failed(rc= initialize_query(ptr, false)))
-  {
-    return rc;
-  }
-
-  memcached_server_fn callbacks[1];
-
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-
-  int send_length= snprintf(buffer, sizeof(buffer), "verbosity %u\r\n", verbosity);
-  if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE or send_length < 0)
-  {
-    return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
-                               memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
-  }
-
-  libmemcached_io_vector_st vector[]=
-  {
-    { NULL, 0 },
-    { buffer, size_t(send_length) },
-  };
-
-  callbacks[0]= _set_verbosity;
-
-  return memcached_server_cursor(ptr, callbacks, vector, 1);
-}
diff --git a/libmemcached/version.cc b/libmemcached/version.cc
deleted file mode 100644 (file)
index 53d24c1..0000000
+++ /dev/null
@@ -1,250 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-#include <libmemcached/common.h>
-
-const char * memcached_lib_version(void) 
-{
-  return LIBMEMCACHED_VERSION_STRING;
-}
-
-static inline memcached_return_t memcached_version_textual(Memcached *memc)
-{
-  libmemcached_io_vector_st vector[]=
-  {
-    { memcached_literal_param("version\r\n") },
-  };
-
-  uint32_t success= 0;
-  bool errors_happened= false;
-  for (uint32_t x= 0; x < memcached_server_count(memc); x++)
-  {
-    memcached_instance_st* instance= memcached_instance_fetch(memc, x);
-
-    // Optimization, we only fetch version once.
-    if (instance->major_version != UINT8_MAX)
-    {
-      continue;
-    }
-
-    memcached_return_t rrc;
-    if (memcached_failed(rrc= memcached_vdo(instance, vector, 1, true)))
-    {
-      errors_happened= true;
-      (void)memcached_set_error(*instance, rrc, MEMCACHED_AT);
-      continue;
-    }
-    success++;
-  }
-
-  if (success)
-  {
-    // Collect the returned items
-    memcached_instance_st* instance;
-    memcached_return_t readable_error;
-    while ((instance= memcached_io_get_readable_server(memc, readable_error)))
-    {
-      memcached_return_t rrc= memcached_response(instance, NULL);
-      if (memcached_failed(rrc))
-      {
-        errors_happened= true;
-      }
-    }
-  }
-
-  return errors_happened ? MEMCACHED_SOME_ERRORS : MEMCACHED_SUCCESS;
-}
-
-static inline memcached_return_t memcached_version_binary(Memcached *memc)
-{
-  protocol_binary_request_version request= {};
-
-  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
-  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-
-  libmemcached_io_vector_st vector[]=
-  {
-    { request.bytes, sizeof(request.bytes) }
-  };
-
-  uint32_t success= 0;
-  bool errors_happened= false;
-  for (uint32_t x= 0; x < memcached_server_count(memc); x++) 
-  {
-    memcached_instance_st* instance= memcached_instance_fetch(memc, x);
-
-    initialize_binary_request(instance, request.message.header);
-
-    if (instance->major_version != UINT8_MAX)
-    {
-      continue;
-    }
-
-    memcached_return_t rrc= memcached_vdo(instance, vector, 1, true);
-    if (memcached_failed(rrc))
-    {
-      errors_happened= true;
-      continue;
-    }
-
-    success++;
-  }
-
-  if (success)
-  {
-    // Collect the returned items
-    memcached_instance_st* instance;
-    memcached_return_t readable_error;
-    while ((instance= memcached_io_get_readable_server(memc, readable_error)))
-    {
-      char buffer[32];
-      memcached_return_t rrc= memcached_response(instance, buffer, sizeof(buffer), NULL);
-      if (memcached_failed(rrc))
-      {
-        errors_happened= true;
-      }
-    }
-  }
-
-  return errors_happened ? MEMCACHED_SOME_ERRORS : MEMCACHED_SUCCESS;
-}
-
-static inline void version_ascii_instance(memcached_instance_st* instance)
-{
-  if (instance->major_version != UINT8_MAX)
-  {
-    libmemcached_io_vector_st vector[]=
-    {
-      { memcached_literal_param("version\r\n") },
-    };
-
-    (void)memcached_vdo(instance, vector, 1, false);
-  }
-}
-
-static inline void version_binary_instance(memcached_instance_st* instance)
-{
-  if (instance->major_version != UINT8_MAX)
-  {
-    protocol_binary_request_version request= {};
-
-    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
-    request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-
-    libmemcached_io_vector_st vector[]=
-    {
-      { request.bytes, sizeof(request.bytes) }
-    };
-
-    initialize_binary_request(instance, request.message.header);
-
-    (void)memcached_vdo(instance, vector, 1, false);
-  }
-}
-
-void memcached_version_instance(memcached_instance_st* instance)
-{
-  if (instance)
-  {
-    if (memcached_has_root(instance))
-    {
-      if (memcached_is_fetching_version(instance->root))
-      {
-        if (memcached_is_udp(instance->root) == false)
-        {
-
-          if (memcached_is_binary(instance->root))
-          {
-            version_binary_instance(instance);
-            return;
-          }
-
-          version_ascii_instance(instance);      
-        }
-      }
-    }
-  }
-}
-
-int8_t memcached_version_instance_cmp(memcached_instance_st *instance,
-    uint8_t maj, uint8_t min, uint8_t mic)
-{
-  if (!instance || memcached_server_major_version(instance) == UINT8_MAX) {
-    return INT8_MIN;
-  } else {
-    uint32_t sv, cv;
-
-    sv = memcached_server_micro_version(instance)
-        |memcached_server_minor_version(instance) << 8
-        |memcached_server_major_version(instance) << 16
-        ;
-    cv = mic
-        |min << 8
-        |maj << 16
-        ;
-    if (sv < cv) {
-      return -1;
-    }
-    return sv != cv;
-  }
-}
-
-memcached_return_t memcached_version(memcached_st *shell)
-{
-  Memcached* memc= memcached2Memcached(shell);
-  if (memc)
-  {
-    memcached_return_t rc;
-    if (memcached_failed(rc= initialize_query(memc, true)))
-    {
-      return rc;
-    }
-
-    if (memcached_is_udp(memc))
-    {
-      return MEMCACHED_NOT_SUPPORTED;
-    }
-
-    if (memcached_is_binary(memc))
-    {
-      return memcached_version_binary(memc);
-    }
-
-    return memcached_version_textual(memc);      
-  }
-
-  return MEMCACHED_INVALID_ARGUMENTS;
-}
diff --git a/libmemcached/version.hpp b/libmemcached/version.hpp
deleted file mode 100644 (file)
index 0c16743..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  LibMemcached
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/ All
- *  rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
-  Common include file for libmemached
-*/
-
-#pragma once
-
-void memcached_version_instance(memcached_instance_st*);
-int8_t memcached_version_instance_cmp(memcached_instance_st*,
-    uint8_t maj, uint8_t min, uint8_t mic);
diff --git a/libmemcached/virtual_bucket.c b/libmemcached/virtual_bucket.c
deleted file mode 100644 (file)
index 951881b..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcached/common.h>
-
-struct bucket_t {
-  uint32_t master;
-  uint32_t forward;
-};
-
-struct memcached_virtual_bucket_t {
-  bool has_forward;
-  uint32_t size;
-  uint32_t replicas;
-  struct bucket_t buckets[];
-};
-
-memcached_return_t memcached_virtual_bucket_create(memcached_st *self,
-                                                   const uint32_t *host_map,
-                                                   const uint32_t *forward_map,
-                                                   const uint32_t buckets,
-                                                   const uint32_t replicas)
-{
-  if (self == NULL || host_map == NULL || buckets == 0U)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  memcached_virtual_bucket_free(self);
-
-  struct memcached_virtual_bucket_t *virtual_bucket= (struct memcached_virtual_bucket_t *)malloc(sizeof(struct memcached_virtual_bucket_t) + sizeof(struct bucket_t) *buckets);
-  
-  if (virtual_bucket == NULL)
-  {
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-  }
-
-
-  virtual_bucket->size= buckets;
-  virtual_bucket->replicas= replicas;
-  self->virtual_bucket= virtual_bucket;
-
-  uint32_t x= 0;
-  for (; x < buckets; x++)
-  {
-    virtual_bucket->buckets[x].master= host_map[x];
-    if (forward_map)
-    {
-      virtual_bucket->buckets[x].forward= forward_map[x];
-    }
-    else
-    {
-      virtual_bucket->buckets[x].forward= 0;
-    }
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-void memcached_virtual_bucket_free(memcached_st *self)
-{
-  if (self)
-  {
-    if (self->virtual_bucket)
-    {
-      free(self->virtual_bucket);
-      self->virtual_bucket= NULL;
-    }
-  }
-}
-
-uint32_t memcached_virtual_bucket_get(const memcached_st *self, uint32_t digest)
-{
-  if (self)
-  {
-    if (self->virtual_bucket)
-    {
-      uint32_t result= (uint32_t) (digest & (self->virtual_bucket->size -1));
-      return self->virtual_bucket->buckets[result].master;
-    }
-
-    return (uint32_t) (digest & (self->number_of_hosts -1));
-  }
-
-  return 0;
-}
diff --git a/libmemcached/virtual_bucket.h b/libmemcached/virtual_bucket.h
deleted file mode 100644 (file)
index 9a63c38..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-memcached_return_t memcached_virtual_bucket_create(memcached_st *self,
-                                                   const uint32_t *host_map,
-                                                   const uint32_t *forward_map,
-                                                   const uint32_t buckets,
-                                                   const uint32_t replicas);
-
-uint32_t memcached_virtual_bucket_get(const memcached_st *self, uint32_t digest);
-
-void memcached_virtual_bucket_free(memcached_st *self);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcached/watchpoint.h b/libmemcached/watchpoint.h
deleted file mode 100644 (file)
index 822101e..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#define WATCHPOINT
-#define WATCHPOINT_ERROR(A)
-#define WATCHPOINT_IFERROR(__memcached_return_t) (void)(__memcached_return_t)
-#define WATCHPOINT_STRING(A)
-#define WATCHPOINT_NUMBER(A)
-#define WATCHPOINT_LABELED_NUMBER(A,B)
-#define WATCHPOINT_IF_LABELED_NUMBER(A,B,C)
-#define WATCHPOINT_ERRNO(A)
-#define WATCHPOINT_ASSERT_PRINT(A,B,C)
-#define WATCHPOINT_ASSERT(A) (void)(A)
-#define WATCHPOINT_ASSERT_INITIALIZED(A)
-#define WATCHPOINT_SET(A)
diff --git a/libmemcached/windows.hpp b/libmemcached/windows.hpp
deleted file mode 100644 (file)
index 40564b1..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Libmemcached library
- *
- * Copyright (C) 2012 Data Differential, http://datadifferential.com/
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- *     * The names of its contributors may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-# include <cerrno>
-#else
-# include <errno.h>
-#endif
-
-#ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN
-#endif
-
-#ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0501
-#endif
-
-#ifdef __MINGW32__
-# if(_WIN32_WINNT >= 0x0501)
-# else
-#  undef _WIN32_WINNT
-#  define _WIN32_WINNT 0x0501
-# endif /* _WIN32_WINNT >= 0x0501 */
-#endif /* __MINGW32__ */
-
-#if defined(HAVE_WINSOCK2_H) && HAVE_WINSOCK2_H
-# include <winsock2.h>
-#endif
-
-#if defined(HAVE_WS2TCPIP_H) && HAVE_WS2TCPIP_H
-# include <ws2tcpip.h>
-#endif
-
-#if defined(HAVE_IO_H) && HAVE_IO_H
-# include <io.h>
-#endif
-
-struct sockaddr_un
-{
-  short int sun_family;
-  char sun_path[108];
-};
-
-static inline int translate_windows_error()
-{
-  int local_errno= WSAGetLastError();
-
-  switch(local_errno) {
-  case WSAEINVAL:
-    local_errno= EINPROGRESS;
-    break;
-  case WSAEALREADY:
-  case WSAEWOULDBLOCK:
-    local_errno= EAGAIN;
-    break;
-
-  case WSAECONNREFUSED:
-    local_errno= ECONNREFUSED;
-    break;
-
-  case WSAENETUNREACH:
-    local_errno= ENETUNREACH;
-    break;
-
-  case WSAETIMEDOUT:
-    local_errno= ETIMEDOUT;
-    break;
-
-  case WSAECONNRESET:
-    local_errno= ECONNRESET;
-    break;
-
-  case WSAEADDRINUSE:
-    local_errno= EADDRINUSE;
-    break;
-
-  case WSAEOPNOTSUPP:
-    local_errno= EOPNOTSUPP;
-    break;
-
-  case WSAENOPROTOOPT:
-    local_errno= ENOPROTOOPT;
-    break;
-
-  default:
-    break;
-  }
-
-  return local_errno;
-}
diff --git a/libmemcachedprotocol-0.0/binary.h b/libmemcachedprotocol-0.0/binary.h
deleted file mode 100644 (file)
index 51e2c42..0000000
+++ /dev/null
@@ -1,728 +0,0 @@
-/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
- * Copyright (c) <2008>, Sun Microsystems, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of the  nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY SUN MICROSYSTEMS, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-/*
- * Summary: Constants used by to implement the binary protocol.
- *
- * Copy: See Copyright for the status of this software.
- *
- * Author: Trond Norbye <trond.norbye@sun.com>
- */
-
-#ifndef PROTOCOL_BINARY_H
-#define PROTOCOL_BINARY_H
-
-#include <libmemcachedprotocol-0.0/vbucket.h>
-
-/**
- * \addtogroup Protocol
- * @{
- */
-
-/**
- * This file contains definitions of the constants and packet formats
- * defined in the binary specification. Please note that you _MUST_ remember
- * to convert each multibyte field to / from network byte order to / from
- * host order.
- */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-    /**
-     * Definition of the legal "magic" values used in a packet.
-     * See section 3.1 Magic byte
-     */
-    typedef enum {
-        PROTOCOL_BINARY_REQ = 0x80,
-        PROTOCOL_BINARY_RES = 0x81
-    } protocol_binary_magic;
-
-    /**
-     * Definition of the valid response status numbers.
-     * See section 3.2 Response Status
-     */
-    typedef enum {
-        PROTOCOL_BINARY_RESPONSE_SUCCESS = 0x00,
-        PROTOCOL_BINARY_RESPONSE_KEY_ENOENT = 0x01,
-        PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS = 0x02,
-        PROTOCOL_BINARY_RESPONSE_E2BIG = 0x03,
-        PROTOCOL_BINARY_RESPONSE_EINVAL = 0x04,
-        PROTOCOL_BINARY_RESPONSE_NOT_STORED = 0x05,
-        PROTOCOL_BINARY_RESPONSE_DELTA_BADVAL = 0x06,
-        PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET = 0x07,
-        PROTOCOL_BINARY_RESPONSE_AUTH_ERROR = 0x20,
-        PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE = 0x21,
-        PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND = 0x81,
-        PROTOCOL_BINARY_RESPONSE_ENOMEM = 0x82,
-        PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED = 0x83,
-        PROTOCOL_BINARY_RESPONSE_EINTERNAL = 0x84,
-        PROTOCOL_BINARY_RESPONSE_EBUSY = 0x85,
-        PROTOCOL_BINARY_RESPONSE_ETMPFAIL = 0x86
-    } protocol_binary_response_status;
-
-    /**
-     * Defintion of the different command opcodes.
-     * See section 3.3 Command Opcodes
-     */
-    typedef enum {
-        PROTOCOL_BINARY_CMD_GET = 0x00,
-        PROTOCOL_BINARY_CMD_SET = 0x01,
-        PROTOCOL_BINARY_CMD_ADD = 0x02,
-        PROTOCOL_BINARY_CMD_REPLACE = 0x03,
-        PROTOCOL_BINARY_CMD_DELETE = 0x04,
-        PROTOCOL_BINARY_CMD_INCREMENT = 0x05,
-        PROTOCOL_BINARY_CMD_DECREMENT = 0x06,
-        PROTOCOL_BINARY_CMD_QUIT = 0x07,
-        PROTOCOL_BINARY_CMD_FLUSH = 0x08,
-        PROTOCOL_BINARY_CMD_GETQ = 0x09,
-        PROTOCOL_BINARY_CMD_NOOP = 0x0a,
-        PROTOCOL_BINARY_CMD_VERSION = 0x0b,
-        PROTOCOL_BINARY_CMD_GETK = 0x0c,
-        PROTOCOL_BINARY_CMD_GETKQ = 0x0d,
-        PROTOCOL_BINARY_CMD_APPEND = 0x0e,
-        PROTOCOL_BINARY_CMD_PREPEND = 0x0f,
-        PROTOCOL_BINARY_CMD_STAT = 0x10,
-        PROTOCOL_BINARY_CMD_SETQ = 0x11,
-        PROTOCOL_BINARY_CMD_ADDQ = 0x12,
-        PROTOCOL_BINARY_CMD_REPLACEQ = 0x13,
-        PROTOCOL_BINARY_CMD_DELETEQ = 0x14,
-        PROTOCOL_BINARY_CMD_INCREMENTQ = 0x15,
-        PROTOCOL_BINARY_CMD_DECREMENTQ = 0x16,
-        PROTOCOL_BINARY_CMD_QUITQ = 0x17,
-        PROTOCOL_BINARY_CMD_FLUSHQ = 0x18,
-        PROTOCOL_BINARY_CMD_APPENDQ = 0x19,
-        PROTOCOL_BINARY_CMD_PREPENDQ = 0x1a,
-        PROTOCOL_BINARY_CMD_VERBOSITY = 0x1b,
-        PROTOCOL_BINARY_CMD_TOUCH = 0x1c,
-        PROTOCOL_BINARY_CMD_GAT = 0x1d,
-        PROTOCOL_BINARY_CMD_GATQ = 0x1e,
-        PROTOCOL_BINARY_CMD_GATK = 0x23,
-        PROTOCOL_BINARY_CMD_GATKQ = 0x24,
-
-        PROTOCOL_BINARY_CMD_SASL_LIST_MECHS = 0x20,
-        PROTOCOL_BINARY_CMD_SASL_AUTH = 0x21,
-        PROTOCOL_BINARY_CMD_SASL_STEP = 0x22,
-
-        /* These commands are used for range operations and exist within
-         * this header for use in other projects.  Range operations are
-         * not expected to be implemented in the memcached server itself.
-         */
-        PROTOCOL_BINARY_CMD_RGET      = 0x30,
-        PROTOCOL_BINARY_CMD_RSET      = 0x31,
-        PROTOCOL_BINARY_CMD_RSETQ     = 0x32,
-        PROTOCOL_BINARY_CMD_RAPPEND   = 0x33,
-        PROTOCOL_BINARY_CMD_RAPPENDQ  = 0x34,
-        PROTOCOL_BINARY_CMD_RPREPEND  = 0x35,
-        PROTOCOL_BINARY_CMD_RPREPENDQ = 0x36,
-        PROTOCOL_BINARY_CMD_RDELETE   = 0x37,
-        PROTOCOL_BINARY_CMD_RDELETEQ  = 0x38,
-        PROTOCOL_BINARY_CMD_RINCR     = 0x39,
-        PROTOCOL_BINARY_CMD_RINCRQ    = 0x3a,
-        PROTOCOL_BINARY_CMD_RDECR     = 0x3b,
-        PROTOCOL_BINARY_CMD_RDECRQ    = 0x3c,
-        /* End Range operations */
-
-        /* VBucket commands */
-        PROTOCOL_BINARY_CMD_SET_VBUCKET = 0x3d,
-        PROTOCOL_BINARY_CMD_GET_VBUCKET = 0x3e,
-        PROTOCOL_BINARY_CMD_DEL_VBUCKET = 0x3f,
-        /* End VBucket commands */
-
-        /* TAP commands */
-        PROTOCOL_BINARY_CMD_TAP_CONNECT = 0x40,
-        PROTOCOL_BINARY_CMD_TAP_MUTATION = 0x41,
-        PROTOCOL_BINARY_CMD_TAP_DELETE = 0x42,
-        PROTOCOL_BINARY_CMD_TAP_FLUSH = 0x43,
-        PROTOCOL_BINARY_CMD_TAP_OPAQUE = 0x44,
-        PROTOCOL_BINARY_CMD_TAP_VBUCKET_SET = 0x45,
-        PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_START = 0x46,
-        PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_END = 0x47,
-        /* End TAP */
-
-        PROTOCOL_BINARY_CMD_LAST_RESERVED = 0xef,
-
-        /* Scrub the data */
-        PROTOCOL_BINARY_CMD_SCRUB = 0xf0
-    } protocol_binary_command;
-
-    /**
-     * Definition of the data types in the packet
-     * See section 3.4 Data Types
-     */
-    typedef enum {
-        PROTOCOL_BINARY_RAW_BYTES = 0x00
-    } protocol_binary_datatypes;
-
-    /**
-     * Definition of the header structure for a request packet.
-     * See section 2
-     */
-    typedef union {
-        struct {
-            uint8_t magic;
-            uint8_t opcode;
-            uint16_t keylen;
-            uint8_t extlen;
-            uint8_t datatype;
-            uint16_t vbucket;
-            uint32_t bodylen;
-            uint32_t opaque;
-            uint64_t cas;
-        } request;
-        uint8_t bytes[24];
-    } protocol_binary_request_header;
-
-    /**
-     * Definition of the header structure for a response packet.
-     * See section 2
-     */
-    typedef union {
-        struct {
-            uint8_t magic;
-            uint8_t opcode;
-            uint16_t keylen;
-            uint8_t extlen;
-            uint8_t datatype;
-            uint16_t status;
-            uint32_t bodylen;
-            uint32_t opaque;
-            uint64_t cas;
-        } response;
-        uint8_t bytes[24];
-    } protocol_binary_response_header;
-
-    /**
-     * Definition of a request-packet containing no extras
-     */
-    union protocol_binary_request_no_extras {
-        struct {
-            protocol_binary_request_header header;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header)];
-    };
-    typedef union protocol_binary_request_no_extras protocol_binary_request_no_extras;
-
-    /**
-     * Definition of a response-packet containing no extras
-     */
-    typedef union {
-        struct {
-            protocol_binary_response_header header;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_response_header)];
-    } protocol_binary_response_no_extras;
-
-    /**
-     * Definition of the packet used by the get, getq, getk and getkq command.
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_get;
-    typedef protocol_binary_request_no_extras protocol_binary_request_getq;
-    typedef protocol_binary_request_no_extras protocol_binary_request_getk;
-    typedef protocol_binary_request_no_extras protocol_binary_request_getkq;
-
-    /**
-     * Definition of the packet returned from a successful get, getq, getk and
-     * getkq.
-     * See section 4
-     */
-    typedef union {
-        struct {
-            protocol_binary_response_header header;
-            struct {
-                uint32_t flags;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_response_header) + 4];
-    } protocol_binary_response_get;
-
-    typedef protocol_binary_response_get protocol_binary_response_getq;
-    typedef protocol_binary_response_get protocol_binary_response_getk;
-    typedef protocol_binary_response_get protocol_binary_response_getkq;
-
-    /**
-     * Definition of the packet used by the delete command
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_delete;
-
-    /**
-     * Definition of the packet returned by the delete command
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_delete;
-
-    /**
-     * Definition of the packet used by the flush command
-     * See section 4
-     * Please note that the expiration field is optional, so remember to see
-     * check the header.bodysize to see if it is present.
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                uint32_t expiration;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
-    } protocol_binary_request_flush;
-
-    /**
-     * Definition of the packet returned by the flush command
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_flush;
-
-    /**
-     * Definition of the packet used by set, add and replace
-     * See section 4
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                uint32_t flags;
-                uint32_t expiration;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
-    } protocol_binary_request_set;
-    typedef protocol_binary_request_set protocol_binary_request_add;
-    typedef protocol_binary_request_set protocol_binary_request_replace;
-
-    /**
-     * Definition of the packet returned by set, add and replace
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_set;
-    typedef protocol_binary_response_no_extras protocol_binary_response_add;
-    typedef protocol_binary_response_no_extras protocol_binary_response_replace;
-
-    /**
-     * Definition of the noop packet
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_noop;
-
-    /**
-     * Definition of the packet returned by the noop command
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_noop;
-
-    /**
-     * Definition of the structure used by the increment and decrement
-     * command.
-     * See section 4
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                uint64_t delta;
-                uint64_t initial;
-                uint32_t expiration;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 20];
-    } protocol_binary_request_incr;
-    typedef protocol_binary_request_incr protocol_binary_request_decr;
-
-    /**
-     * Definition of the response from an incr or decr command
-     * command.
-     * See section 4
-     */
-    typedef union {
-        struct {
-            protocol_binary_response_header header;
-            struct {
-                uint64_t value;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_response_header) + 8];
-    } protocol_binary_response_incr;
-    typedef protocol_binary_response_incr protocol_binary_response_decr;
-
-    /**
-     * Definition of the quit
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_quit;
-
-    /**
-     * Definition of the packet returned by the quit command
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_quit;
-
-    /**
-     * Definition of the packet used by append and prepend command
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_append;
-    typedef protocol_binary_request_no_extras protocol_binary_request_prepend;
-
-    /**
-     * Definition of the packet returned from a successful append or prepend
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_append;
-    typedef protocol_binary_response_no_extras protocol_binary_response_prepend;
-
-    /**
-     * Definition of the packet used by the version command
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_version;
-
-    /**
-     * Definition of the packet returned from a successful version command
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_version;
-
-
-    /**
-     * Definition of the packet used by the stats command.
-     * See section 4
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_stats;
-
-    /**
-     * Definition of the packet returned from a successful stats command
-     * See section 4
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_stats;
-
-    /**
-     * Definition of the packet used by the verbosity command
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                uint32_t level;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
-    } protocol_binary_request_verbosity;
-
-    /**
-     * Definition of the packet returned from the verbosity command
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_verbosity;
-
-    /**
-     * Definition of the packet used by the touch command.
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                uint32_t expiration;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
-    } protocol_binary_request_touch;
-
-    /**
-     * Definition of the packet returned from the touch command
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_touch;
-
-    /**
-     * Definition of the packet used by the GAT(Q) command.
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                uint32_t expiration;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
-    } protocol_binary_request_gat;
-
-    typedef protocol_binary_request_gat protocol_binary_request_gatq;
-
-    /**
-     * Definition of the packet returned from the GAT(Q)
-     */
-    typedef protocol_binary_response_get protocol_binary_response_gat;
-    typedef protocol_binary_response_get protocol_binary_response_gatq;
-
-
-    /**
-     * Definition of a request for a range operation.
-     * See http://code.google.com/p/memcached/wiki/RangeOps
-     *
-     * These types are used for range operations and exist within
-     * this header for use in other projects.  Range operations are
-     * not expected to be implemented in the memcached server itself.
-     */
-    typedef union {
-        struct {
-            protocol_binary_response_header header;
-            struct {
-                uint16_t size;
-                uint8_t  reserved;
-                uint8_t  flags;
-                uint32_t max_results;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
-    } protocol_binary_request_rangeop;
-
-    typedef protocol_binary_request_rangeop protocol_binary_request_rget;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rset;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rsetq;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rappend;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rappendq;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rprepend;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rprependq;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rdelete;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rdeleteq;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rincr;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rincrq;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rdecr;
-    typedef protocol_binary_request_rangeop protocol_binary_request_rdecrq;
-
-
-    /**
-     * Definition of tap commands
-     * See To be written
-     *
-     */
-
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                /**
-                 * flags is a bitmask used to set properties for the
-                 * the connection. Please In order to be forward compatible
-                 * you should set all undefined bits to 0.
-                 *
-                 * If the bit require extra userdata, it will be stored
-                 * in the user-data field of the body (passed to the engine
-                 * as enginespeciffic). That means that when you parse the
-                 * flags and the engine-specific data, you have to work your
-                 * way from bit 0 and upwards to find the correct offset for
-                 * the data.
-                 *
-                 */
-                uint32_t flags;
-
-                /**
-                 * Backfill age
-                 *
-                 * By using this flag you can limit the amount of data being
-                 * transmitted. If you don't specify a backfill age, the
-                 * server will transmit everything it contains.
-                 *
-                 * The first 8 bytes in the engine specific data contains
-                 * the oldest entry (from epoc) you're interested in.
-                 * Specifying a time in the future (for the server you are
-                 * connecting to), will cause it to start streaming current
-                 * changes.
-                 */
-#define TAP_CONNECT_FLAG_BACKFILL 0x01
-                /**
-                 * Dump will cause the server to send the data stored on the
-                 * server, but disconnect when the keys stored in the server
-                 * are transmitted.
-                 */
-#define TAP_CONNECT_FLAG_DUMP 0x02
-                /**
-                 * The body contains a list of 16 bits words in network byte
-                 * order specifying the vbucket ids to monitor. The first 16
-                 * bit word contains the number of buckets. The number of 0
-                 * means "all buckets"
-                 */
-#define TAP_CONNECT_FLAG_LIST_VBUCKETS 0x04
-                /**
-                 * The responsibility of the vbuckets is to be transferred
-                 * over to the caller when all items are transferred.
-                 */
-#define TAP_CONNECT_FLAG_TAKEOVER_VBUCKETS 0x08
-                /**
-                 * The tap consumer supports ack'ing of tap messages
-                 */
-#define TAP_CONNECT_SUPPORT_ACK 0x10
-                /**
-                 * The tap consumer would prefer to just get the keys
-                 * back. If the engine supports this it will set
-                 * the TAP_FLAG_NO_VALUE flag in each of the
-                 * tap packets returned.
-                 */
-#define TAP_CONNECT_REQUEST_KEYS_ONLY 0x20
-                /**
-                 * The body contains a list of (vbucket_id, last_checkpoint_id)
-                 * pairs. This provides the checkpoint support in TAP streams.
-                 * The last checkpoint id represents the last checkpoint that
-                 * was successfully persisted.
-                 */
-#define TAP_CONNECT_CHECKPOINT 0x40
-                /**
-                 * The tap consumer is a registered tap client, which means that
-                 * the tap server will maintain its checkpoint cursor permanently.
-                 */
-#define TAP_CONNECT_REGISTERED_CLIENT 0x80
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
-    } protocol_binary_request_tap_connect;
-
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                struct {
-                    uint16_t enginespecific_length;
-                    /*
-                     * The flag section support the following flags
-                     */
-                    /**
-                     * Request that the consumer send a response packet
-                     * for this packet. The opaque field must be preserved
-                     * in the response.
-                     */
-#define TAP_FLAG_ACK 0x01
-                    /**
-                     * The value for the key is not included in the packet
-                     */
-#define TAP_FLAG_NO_VALUE 0x02
-                    uint16_t flags;
-                    uint8_t  ttl;
-                    uint8_t  res1;
-                    uint8_t  res2;
-                    uint8_t  res3;
-                } tap;
-                struct {
-                    uint32_t flags;
-                    uint32_t expiration;
-                } item;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 16];
-    } protocol_binary_request_tap_mutation;
-
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                struct {
-                    uint16_t enginespecific_length;
-                    /**
-                     * See the definition of the flags for
-                     * protocol_binary_request_tap_mutation for a description
-                     * of the available flags.
-                     */
-                    uint16_t flags;
-                    uint8_t  ttl;
-                    uint8_t  res1;
-                    uint8_t  res2;
-                    uint8_t  res3;
-                } tap;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
-    } protocol_binary_request_tap_no_extras;
-
-    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_delete;
-    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_flush;
-    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_opaque;
-    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_vbucket_set;
-
-
-    /**
-     * Definition of the packet used by the scrub.
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_scrub;
-
-    /**
-     * Definition of the packet returned from scrub.
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_scrub;
-
-
-    /**
-     * Definition of the packet used by set vbucket
-     */
-    typedef union {
-        struct {
-            protocol_binary_request_header header;
-            struct {
-                vbucket_state_t state;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_request_header) + sizeof(vbucket_state_t)];
-    } protocol_binary_request_set_vbucket;
-    /**
-     * Definition of the packet returned from set vbucket
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_set_vbucket;
-    /**
-     * Definition of the packet used by del vbucket
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_del_vbucket;
-    /**
-     * Definition of the packet returned from del vbucket
-     */
-    typedef protocol_binary_response_no_extras protocol_binary_response_del_vbucket;
-
-    /**
-     * Definition of the packet used by get vbucket
-     */
-    typedef protocol_binary_request_no_extras protocol_binary_request_get_vbucket;
-
-    /**
-     * Definition of the packet returned from get vbucket
-     */
-    typedef union {
-        struct {
-            protocol_binary_response_header header;
-            struct {
-                vbucket_state_t state;
-            } body;
-        } message;
-        uint8_t bytes[sizeof(protocol_binary_response_header) + sizeof(vbucket_state_t)];
-    } protocol_binary_response_get_vbucket;
-
-
-    /**
-     * @}
-     */
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* PROTOCOL_BINARY_H */
diff --git a/libmemcachedprotocol-0.0/callback.h b/libmemcachedprotocol-0.0/callback.h
deleted file mode 100644 (file)
index 638536c..0000000
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Summary: Definition of the callback interface
- *
- * Copy: See Copyright for the status of this software.
- *
- * Author: Trond Norbye
- */
-
-#pragma once
-
-/**
- * Callback to send data back from a successful GET/GETQ/GETK/GETKQ command
- *
- * @param cookie Just pass along the cookie supplied in the callback
- * @param key What to insert as key in the reply
- * @param keylen The length of the key
- * @param body What to store in the body of the package
- * @param bodylen The number of bytes of the body
- * @param flags The flags stored with the item
- * @param cas The CAS value to insert into the response (should be 0
- *            if you don't care)
- */
-typedef protocol_binary_response_status
-(*memcached_binary_protocol_get_response_handler)(const void *cookie,
-                                                  const void *key,
-                                                  uint16_t keylen,
-                                                  const void *body,
-                                                  uint32_t bodylen,
-                                                  uint32_t flags,
-                                                  uint64_t cas);
-/**
- * Callback to send data back from a STAT command
- *
- * @param cookie Just pass along the cookie supplied in the callback
- * @param key What to insert as key in the reply
- * @param keylen The length of the key
- * @param body What to store in the body of the package
- * @param bodylen The number of bytes of the body
- */
-typedef protocol_binary_response_status
-(*memcached_binary_protocol_stat_response_handler)(const void *cookie,
-                                                   const void *key,
-                                                   uint16_t keylen,
-                                                   const void *body,
-                                                   uint32_t bodylen);
-/**
- * Callback to send data back from a VERSION command
- *
- * @param cookie Just pass along the cookie supplied in the callback
- * @param text The version string
- * @param length The number of bytes in the version string
- */
-typedef protocol_binary_response_status
-(*memcached_binary_protocol_version_response_handler)(const void *cookie,
-                                                      const void *text,
-                                                      uint32_t length);
-
-
-/**
- * In the low level interface you need to format the response
- * packet yourself (giving you complete freedom :-)
- *
- * @param cookie Just pass along the cookie supplied in the callback
- * @param request Pointer to the request packet you are sending a reply to
- * @param response Pointer to the response packet to send
- *
- */
-typedef protocol_binary_response_status (*memcached_binary_protocol_raw_response_handler)(const void *cookie,
-                                                               protocol_binary_request_header *request,
-                                                               protocol_binary_response_header *response);
-
-/**
- * In the low lever interface you have to do most of the work by
- * yourself, but it also gives you a lot of freedom :-)
- * @param cookie identification for this connection, just pass it along to
- *               the response handler
- * @param header the command received over the wire. Never try to access
- *               <u>anything</u> outside the command.
- * @param resonse_handler call this function to send data back to the client
- */
-typedef protocol_binary_response_status (*memcached_binary_protocol_command_handler)(const void *cookie,
-                                                   protocol_binary_request_header *header,
-                                                   memcached_binary_protocol_raw_response_handler response_handler);
-
-/**
- * The raw interface to the packets is implemented in version 0. It contains
- * just an array with command handlers. The inxed in the array is the
- * com code.
- */
-typedef struct {
-   memcached_binary_protocol_command_handler comcode[256];
-} memcached_binary_protocol_callback_v0_st;
-
-
-/**
- * The first version of the callback struct containing all of the
- * documented commands in the initial release of the binary protocol
- * (aka. memcached 1.4.0).
- *
- * You might miss the Q commands (addq etc) but the response function
- * knows how to deal with them so you don't need to worry about that :-)
- */
-typedef struct {
-   /**
-    * Add an item to the cache
-    * @param cookie id of the client receiving the command
-    * @param key the key to add
-    * @param len the length of the key
-    * @param val the value to store for the key (may be NIL)
-    * @param vallen the length of the data
-    * @param flags the flags to store with the key
-    * @param exptime the expiry time for the key-value pair
-    * @param cas the resulting cas for the add operation (if success)
-    */
-   protocol_binary_response_status (*add)(const void *cookie,
-                                          const void *key,
-                                          uint16_t keylen,
-                                          const void* val,
-                                          uint32_t vallen,
-                                          uint32_t flags,
-                                          uint32_t exptime,
-                                          uint64_t *cas);
-
-   /**
-    * Append data to an <b>existing</b> key-value pair.
-    *
-    * @param cookie id of the client receiving the command
-    * @param key the key to add data to
-    * @param len the length of the key
-    * @param val the value to append to the value
-    * @param vallen the length of the data
-    * @param cas the CAS in the request
-    * @param result_cas the resulting cas for the append operation
-    *
-    */
-   protocol_binary_response_status (*append)(const void *cookie,
-                                             const void *key,
-                                             uint16_t keylen,
-                                             const void* val,
-                                             uint32_t vallen,
-                                             uint64_t cas,
-                                             uint64_t *result_cas);
-
-   /**
-    * Decrement the value for a key
-    *
-    * @param cookie id of the client receiving the command
-    * @param key the key to decrement the value for
-    * @param len the length of the key
-    * @param delta the amount to decrement
-    * @param initial initial value to store (if the key doesn't exist)
-    * @param expiration expiration time for the object (if the key doesn't exist)
-    * @param cas the CAS in the request
-    * @param result the result from the decrement
-    * @param result_cas the cas of the item
-    *
-    */
-   protocol_binary_response_status (*decrement)(const void *cookie,
-                                                const void *key,
-                                                uint16_t keylen,
-                                                uint64_t delta,
-                                                uint64_t initial,
-                                                uint32_t expiration,
-                                                uint64_t *result,
-                                                uint64_t *result_cas);
-
-   /**
-    * Delete an existing key
-    *
-    * @param cookie id of the client receiving the command
-    * @param key the key to delete_object
-    * @param len the length of the key
-    * @param cas the CAS in the request
-    */
-   protocol_binary_response_status (*delete_object)(const void *cookie,
-                                                    const void *key,
-                                                    uint16_t keylen,
-                                                    uint64_t cas);
-
-
-   /**
-    * Flush the cache
-    *
-    * @param cookie id of the client receiving the command
-    * @param when when the cache should be flushed (0 == immediately)
-    */
-   protocol_binary_response_status (*flush_object)(const void *cookie,
-                                                   uint32_t when);
-
-
-
-   /**
-    * Get a key-value pair
-    *
-    * @param cookie id of the client receiving the command
-    * @param key the key to get
-    * @param len the length of the key
-    * @param response_handler to send the result back to the client
-    */
-   protocol_binary_response_status (*get)(const void *cookie,
-                                          const void *key,
-                                          uint16_t keylen,
-                                          memcached_binary_protocol_get_response_handler response_handler);
-
-   /**
-    * Increment the value for a key
-    *
-    * @param cookie id of the client receiving the command
-    * @param key the key to increment the value on
-    * @param len the length of the key
-    * @param delta the amount to increment
-    * @param initial initial value to store (if the key doesn't exist)
-    * @param expiration expiration time for the object (if the key doesn't exist)
-    * @param cas the CAS in the request
-    * @param result the result from the decrement
-    * @param result_cas the cas of the item
-    *
-    */
-   protocol_binary_response_status (*increment)(const void *cookie,
-                                                const void *key,
-                                                uint16_t keylen,
-                                                uint64_t delta,
-                                                uint64_t initial,
-                                                uint32_t expiration,
-                                                uint64_t *result,
-                                                uint64_t *result_cas);
-
-   /**
-    * The noop command was received. This is just a notification callback (the
-    * response is automatically created).
-    *
-    * @param cookie id of the client receiving the command
-    */
-   protocol_binary_response_status (*noop)(const void *cookie);
-
-   /**
-    * Prepend data to an <b>existing</b> key-value pair.
-    *
-    * @param cookie id of the client receiving the command
-    * @param key the key to prepend data to
-    * @param len the length of the key
-    * @param val the value to prepend to the value
-    * @param vallen the length of the data
-    * @param cas the CAS in the request
-    * @param result-cas the cas id of the item
-    *
-    */
-   protocol_binary_response_status (*prepend)(const void *cookie,
-                                              const void *key,
-                                              uint16_t keylen,
-                                              const void* val,
-                                              uint32_t vallen,
-                                              uint64_t cas,
-                                              uint64_t *result_cas);
-
-   /**
-    * The quit command was received. This is just a notification callback (the
-    * response is automatically created).
-    *
-    * @param cookie id of the client receiving the command
-    */
-   protocol_binary_response_status (*quit)(const void *cookie);
-
-
-   /**
-    * Replace an <b>existing</b> item to the cache
-    *
-    * @param cookie id of the client receiving the command
-    * @param key the key to replace the content for
-    * @param len the length of the key
-    * @param val the value to store for the key (may be NIL)
-    * @param vallen the length of the data
-    * @param flags the flags to store with the key
-    * @param exptime the expiry time for the key-value pair
-    * @param cas the cas id in the request
-    * @param result_cas the cas id of the item
-    */
-   protocol_binary_response_status (*replace)(const void *cookie,
-                                              const void *key,
-                                              uint16_t keylen,
-                                              const void* val,
-                                              uint32_t vallen,
-                                              uint32_t flags,
-                                              uint32_t exptime,
-                                              uint64_t cas,
-                                              uint64_t *result_cas);
-
-
-   /**
-    * Set a key-value pair in the cache
-    *
-    * @param cookie id of the client receiving the command
-    * @param key the key to insert
-    * @param len the length of the key
-    * @param val the value to store for the key (may be NIL)
-    * @param vallen the length of the data
-    * @param flags the flags to store with the key
-    * @param exptime the expiry time for the key-value pair
-    * @param cas the cas id in the request
-    * @param result_cas the cas id of the new item
-    */
-   protocol_binary_response_status (*set)(const void *cookie,
-                                          const void *key,
-                                          uint16_t keylen,
-                                          const void* val,
-                                          uint32_t vallen,
-                                          uint32_t flags,
-                                          uint32_t exptime,
-                                          uint64_t cas,
-                                          uint64_t *result_cas);
-
-   /**
-    * Get status information
-    *
-    * @param cookie id of the client receiving the command
-    * @param key the key to get status for (or NIL to request all status).
-    *            Remember to insert the terminating packet if multiple
-    *            packets should be returned.
-    * @param keylen the length of the key
-    * @param response_handler to send the result back to the client, but
-    *                         don't send reply on success!
-    *
-    */
-   protocol_binary_response_status (*stat)(const void *cookie,
-                                           const void *key,
-                                           uint16_t keylen,
-                                           memcached_binary_protocol_stat_response_handler response_handler);
-
-   /**
-    * Get the version information
-    *
-    * @param cookie id of the client receiving the command
-    * @param response_handler to send the result back to the client, but
-    *                         don't send reply on success!
-    *
-    */
-   protocol_binary_response_status (*version)(const void *cookie,
-                                              memcached_binary_protocol_version_response_handler response_handler);
-} memcached_binary_protocol_callback_v1_st;
-
-
-/**
- * The version numbers for the different callback structures.
- */
-typedef enum {
-   /** Version 0 is a lowlevel interface that tries to maximize your freedom */
-   MEMCACHED_PROTOCOL_HANDLER_V0= 0,
-   /**
-    * Version 1 abstracts more of the protocol details, and let you work at
-    * a logical level
-    */
-   MEMCACHED_PROTOCOL_HANDLER_V1= 1
-} memcached_protocol_interface_version_t;
-
-/**
- * Definition of the protocol callback structure.
- */
-typedef struct {
-   /**
-    * The interface version you provide callbacks for.
-    */
-   memcached_protocol_interface_version_t interface_version;
-
-   /**
-    * Callback fired just before the command will be executed.
-    *
-    * @param cookie id of the client receiving the command
-    * @param header the command header as received on the wire. If you look
-    *               at the content you <b>must</b> ensure that you don't
-    *               try to access beyond the end of the message.
-    */
-   void (*pre_execute)(const void *cookie,
-                       protocol_binary_request_header *header);
-   /**
-    * Callback fired just after the command was exected (please note
-    * that the data transfer back to the client is not finished at this
-    * time).
-    *
-    * @param cookie id of the client receiving the command
-    * @param header the command header as received on the wire. If you look
-    *               at the content you <b>must</b> ensure that you don't
-    *               try to access beyond the end of the message.
-    */
-   void (*post_execute)(const void *cookie,
-                        protocol_binary_request_header *header);
-
-   /**
-    * Callback fired if no specialized callback is registered for this
-    * specific command code.
-    *
-    * @param cookie id of the client receiving the command
-    * @param header the command header as received on the wire. You <b>must</b>
-    *               ensure that you don't try to access beyond the end of the
-    *               message.
-    * @param response_handler The response handler to send data back.
-    */
-   protocol_binary_response_status (*unknown)(const void *cookie,
-                                              protocol_binary_request_header *header,
-                                              memcached_binary_protocol_raw_response_handler response_handler);
-
-   /**
-    * The different interface levels we support. A pointer is used so the
-    * size of the structure is fixed. You must ensure that the memory area
-    * passed as the pointer is valid as long as you use the protocol handler.
-    */
-   union {
-      memcached_binary_protocol_callback_v0_st v0;
-
-      /**
-       * The first version of the callback struct containing all of the
-       * documented commands in the initial release of the binary protocol
-       * (aka. memcached 1.4.0).
-       */
-      memcached_binary_protocol_callback_v1_st v1;
-   } interface;
-} memcached_binary_protocol_callback_st;
diff --git a/libmemcachedprotocol-0.0/handler.h b/libmemcachedprotocol-0.0/handler.h
deleted file mode 100644 (file)
index 113338d..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Definition of the callback interface to the protocol handler
- *
- * Author: Trond Norbye
- *
- */
-
-#pragma once
-
-#include <sys/types.h>
-#if !defined(__cplusplus)
-# include <stdbool.h>
-#endif
-
-#include <libmemcached-1.0/visibility.h>
-#include <libmemcached-1.0/platform.h>
-#include <libmemcachedprotocol-0.0/binary.h>
-#include <libmemcachedprotocol-0.0/callback.h>
-
-/* Forward declarations */
-/*
- * You should only access memcached_protocol_st from one thread!,
- * and never assume anything about the internal layout / sizes of the
- * structures.
- */
-typedef struct memcached_protocol_st memcached_protocol_st;
-typedef struct memcached_protocol_client_st memcached_protocol_client_st;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Function the protocol handler should call to receive data.
- * This function should behave exactly like read(2)
- *
- * @param cookie a cookie used to represent a given client
- * @param fd the filedescriptor associated with the client
- * @param buf destination buffer
- * @param nbuf number of bytes to receive
- * @return the number of bytes copied into buf
- *         or -1 upon error (errno should contain more information)
- */
-typedef ssize_t (*memcached_protocol_recv_func)(const void *cookie,
-                                                memcached_socket_t fd,
-                                                void *buf,
-                                                size_t nbuf);
-
-/**
- * Function the protocol handler should call to send data.
- * This function should behave exactly like write(2)
- *
- * @param cookie a cookie used to represent a given client
- * @param fd the filedescriptor associated with the client
- * @param buf the source buffer
- * @param nbuf number of bytes to send
- * @return the number of bytes sent
- *         or -1 upon error (errno should contain more information)
- */
-typedef ssize_t (*memcached_protocol_send_func)(const void *cookie,
-                                                memcached_socket_t fd,
-                                                const void *buf,
-                                                size_t nbuf);
-
-/**
- * Create an instance of the protocol handler
- *
- * @return NULL if allocation of an instance fails
- */
-LIBMEMCACHED_API
-memcached_protocol_st *memcached_protocol_create_instance(void);
-
-/**
- * Get the callbacks associated with a protocol handler instance
- * @return the callbacks currently used
- */
-LIBMEMCACHED_API
-memcached_binary_protocol_callback_st *memcached_binary_protocol_get_callbacks(memcached_protocol_st *instance);
-
-/**
- * Set the callbacks to be used by the given protocol handler instance
- * @param instance the instance to update
- * @param callback the callbacks to use
- */
-LIBMEMCACHED_API
-void memcached_binary_protocol_set_callbacks(memcached_protocol_st *instance, memcached_binary_protocol_callback_st *callback);
-
-/**
- * Should the library inspect the packages being sent and received and verify
- * that they are according to the specification? If it encounters an invalid
- * packet, it will return an EINVAL packet.
- *
- * @param instance the instance to update
- * @param enable true if you want the library to check packages, false otherwise
- */
-LIBMEMCACHED_API
-void memcached_binary_protocol_set_pedantic(memcached_protocol_st *instance, bool enable);
-
-/**
- * Is the library inpecting each package?
- * @param instance the instance to check
- * @return true it the library is inspecting each package, false otherwise
- */
-LIBMEMCACHED_API
-bool memcached_binary_protocol_get_pedantic(memcached_protocol_st *instance);
-
-/**
- * Destroy an instance of the protocol handler
- *
- * @param instance The instance to destroy
- */
-LIBMEMCACHED_API
-void memcached_protocol_destroy_instance(memcached_protocol_st *instance);
-
-/**
- * Set the IO functions used by the instance to send and receive data. The
- * functions should behave like recv(3socket) and send(3socket).
- *
- * @param instance the instance to specify the IO functions for
- * @param recv the function to call for reciving data
- * @param send the function to call for sending data
- */
-LIBMEMCACHED_API
-void memached_protocol_set_io_functions(memcached_protocol_st *instance,
-                                        memcached_protocol_recv_func recv,
-                                        memcached_protocol_send_func send);
-
-
-/**
- * Create a new client instance and associate it with a socket
- * @param instance the protocol instance to bind the client to
- * @param sock the client socket
- * @return NULL if allocation fails, otherwise an instance
- */
-LIBMEMCACHED_API
-memcached_protocol_client_st *memcached_protocol_create_client(memcached_protocol_st *instance, memcached_socket_t sock);
-
-/**
- * Destroy a client handle.
- * The caller needs to close the socket accociated with the client
- * <b>before</b> calling this function. This function invalidates the
- * client memory area.
- *
- * @param client the client to destroy
- */
-LIBMEMCACHED_API
-void memcached_protocol_client_destroy(memcached_protocol_client_st *client);
-
-LIBMEMCACHED_API
-void memcached_protocol_client_set_verbose(struct memcached_protocol_client_st *client, bool arg);
-
-/**
- * Error event means that the client encountered an error with the
- * connection so you should shut it down
- */
-#define MEMCACHED_PROTOCOL_ERROR_EVENT 1
-/**
- * Please notify when there is more data available to read
- */
-#define MEMCACHED_PROTOCOL_READ_EVENT 2
-/**
- * Please notify when it is possible to send more data
- */
-#define MEMCACHED_PROTOCOL_WRITE_EVENT 4
-/**
- * Backed paused the execution for this client
- */
-#define MEMCACHED_PROTOCOL_PAUSE_EVENT 8
-
-/**
- * The different events the client is interested in. This is a bitmask of
- * the constants defined above.
- */
-typedef uint32_t memcached_protocol_event_t;
-
-/**
- * Let the client do some work. This might involve reading / sending data
- * to/from the client, or perform callbacks to execute a command.
- * @param client the client structure to work on
- * @return The next event the protocol handler will be notified for
- */
-LIBMEMCACHED_API
-memcached_protocol_event_t memcached_protocol_client_work(memcached_protocol_client_st *client);
-
-/**
- * Get the socket attached to a client handle
- * @param client the client to query
- * @return the socket handle
- */
-LIBMEMCACHED_API
-memcached_socket_t memcached_protocol_client_get_socket(memcached_protocol_client_st *client);
-
-/**
- * Get the error id socket attached to a client handle
- * @param client the client to query for an error code
- * @return the OS error code from the client
- */
-LIBMEMCACHED_API
-int memcached_protocol_client_get_errno(memcached_protocol_client_st *client);
-
-/**
- * Get a raw response handler for the given cookie
- * @param cookie the cookie passed along into the callback
- * @return the raw reponse handler you may use if you find
- *         the generic callback too limiting
- */
-LIBMEMCACHED_API
-memcached_binary_protocol_raw_response_handler memcached_binary_protocol_get_raw_response_handler(const void *cookie);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcachedprotocol-0.0/vbucket.h b/libmemcachedprotocol-0.0/vbucket.h
deleted file mode 100644 (file)
index e2cc563..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-typedef enum {
-    vbucket_state_active = 1, /**< Actively servicing a vbucket. */
-    vbucket_state_replica, /**< Servicing a vbucket as a replica only. */
-    vbucket_state_pending, /**< Pending active. */
-    vbucket_state_dead /**< Not in use, pending deletion. */
-} vbucket_state_t;
-
-#define is_valid_vbucket_state_t(state) \
-    (state == vbucket_state_active || \
-     state == vbucket_state_replica || \
-     state == vbucket_state_pending || \
-     state == vbucket_state_dead)
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcachedprotocol/ascii_handler.c b/libmemcachedprotocol/ascii_handler.c
deleted file mode 100644 (file)
index 449b650..0000000
+++ /dev/null
@@ -1,1161 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcachedprotocol/common.h>
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-
-static void print_ascii_command(memcached_protocol_client_st *client)
-{
-  if (client->is_verbose)
-  {
-    switch (client->ascii_command)
-    {
-    case SET_CMD:
-      fprintf(stderr, "%s:%d SET_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case ADD_CMD:
-      fprintf(stderr, "%s:%d ADD_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case REPLACE_CMD:
-      fprintf(stderr, "%s:%d REPLACE_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case CAS_CMD:
-      fprintf(stderr, "%s:%d CAS_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case APPEND_CMD:
-      fprintf(stderr, "%s:%d APPEND_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case PREPEND_CMD:
-      fprintf(stderr, "%s:%d PREPEND_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case DELETE_CMD:
-      fprintf(stderr, "%s:%d DELETE_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case INCR_CMD: /* FALLTHROUGH */
-      fprintf(stderr, "%s:%d INCR_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case DECR_CMD:
-      fprintf(stderr, "%s:%d DECR_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case STATS_CMD:
-      fprintf(stderr, "%s:%d STATS_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case FLUSH_ALL_CMD:
-      fprintf(stderr, "%s:%d FLUSH_ALL_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case VERSION_CMD:
-      fprintf(stderr, "%s:%d VERSION_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case QUIT_CMD:
-      fprintf(stderr, "%s:%d QUIT_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case VERBOSITY_CMD:
-      fprintf(stderr, "%s:%d VERBOSITY_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case GET_CMD:
-      fprintf(stderr, "%s:%d GET_CMD\n", __FILE__, __LINE__);
-      break;
-
-    case GETS_CMD:
-      fprintf(stderr, "%s:%d GETS_CMD\n", __FILE__, __LINE__);
-      break;
-
-    default:
-    case UNKNOWN_CMD:
-      fprintf(stderr, "%s:%d UNKNOWN_CMD\n", __FILE__, __LINE__);
-      break;
-
-    }
-  }
-}
-
-/**
- * Try to parse a key from the string.
- * @pointer start pointer to a pointer to the string (IN and OUT)
- * @return length of the string of -1 if this was an illegal key (invalid
- *         characters or invalid length)
- * @todo add length!
- */
-static uint16_t parse_ascii_key(char **start)
-{
-  uint16_t len= 0;
-  char *c= *start;
-  /* Strip leading whitespaces */
-  while (isspace(*c))
-  {
-    ++c;
-  }
-
-  *start= c;
-
-  while (*c != '\0' && !isspace(*c) && !iscntrl(*c))
-  {
-    ++c;
-    ++len;
-  }
-
-
-  if (len == 0 || len > 240 || (*c != '\0' && *c != '\r' && iscntrl(*c)))
-  {
-    return 0;
-  }
-
-  return len;
-}
-
-/**
- * Spool a zero-terminated string
- * @param client destination
- * @param text the text to spool
- * @return status of the spool operation
- */
-static protocol_binary_response_status raw_response_handler(memcached_protocol_client_st *client, const char *text)
-{
-  if (client->is_verbose)
-  {
-    fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, text);
-  }
-
-  if (client->root->drain(client) == false)
-  {
-    return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
-  }
-
-  assert(client->output != NULL);
-#if 0
-  if (client->output == NULL)
-  {
-    /* I can write directly to the socket.... */
-    do
-    {
-      size_t num_bytes= len -offset;
-      ssize_t nw= client->root->send(client,
-                                     client->sock,
-                                     ptr + offset,
-                                     num_bytes);
-      if (nw == -1)
-      {
-        if (get_socket_errno() == EWOULDBLOCK)
-        {
-          break;
-        }
-        else if (get_socket_errno() != EINTR)
-        {
-          client->error= errno;
-          return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
-        }
-      }
-      else
-      {
-        offset += (size_t)nw;
-      }
-    } while (offset < len);
-  }
-#endif
-
-  return client->root->spool(client, text, strlen(text));
-}
-
-/**
- * Send a "CLIENT_ERROR" message back to the client with the correct
- * format of the command being sent
- * @param client the client to send the message to
- */
-static void send_command_usage(memcached_protocol_client_st *client)
-{
-  const char *errmsg[]= {
-    [GET_CMD]= "CLIENT_ERROR: Syntax error: get <key>*\r\n",
-    [GETS_CMD]= "CLIENT_ERROR: Syntax error: gets <key>*\r\n",
-    [SET_CMD]= "CLIENT_ERROR: Syntax error: set <key> <flags> <exptime> <bytes> [noreply]\r\n",
-    [ADD_CMD]= "CLIENT_ERROR: Syntax error: add <key> <flags> <exptime> <bytes> [noreply]\r\n",
-    [REPLACE_CMD]= "CLIENT_ERROR: Syntax error: replace <key> <flags> <exptime> <bytes> [noreply]\r\n",
-    [CAS_CMD]= "CLIENT_ERROR: Syntax error: cas <key> <flags> <exptime> <bytes> <casid> [noreply]\r\n",
-    [APPEND_CMD]= "CLIENT_ERROR: Syntax error: append <key> <flags> <exptime> <bytes> [noreply]\r\n",
-    [PREPEND_CMD]= "CLIENT_ERROR: Syntax error: prepend <key> <flags> <exptime> <bytes> [noreply]\r\n",
-    [DELETE_CMD]= "CLIENT_ERROR: Syntax error: delete_object <key> [noreply]\r\n",
-    [INCR_CMD]= "CLIENT_ERROR: Syntax error: incr <key> <value> [noreply]\r\n",
-    [DECR_CMD]= "CLIENT_ERROR: Syntax error: decr <key> <value> [noreply]\r\n",
-    [STATS_CMD]= "CLIENT_ERROR: Syntax error: stats [key]\r\n",
-    [FLUSH_ALL_CMD]= "CLIENT_ERROR: Syntax error: flush_all [timeout] [noreply]\r\n",
-    [VERSION_CMD]= "CLIENT_ERROR: Syntax error: version\r\n",
-    [QUIT_CMD]="CLIENT_ERROR: Syntax error: quit\r\n",
-
-    [VERBOSITY_CMD]= "CLIENT_ERROR: Syntax error: verbosity <num>\r\n",
-    [UNKNOWN_CMD]= "CLIENT_ERROR: Unknown command\r\n",
-  };
-
-  client->mute = false;
-  raw_response_handler(client, errmsg[client->ascii_command]);
-}
-
-/**
- * Callback for the VERSION responses
- * @param cookie client identifier
- * @param text the length of the body
- * @param textlen the length of the body
- */
-static protocol_binary_response_status ascii_version_response_handler(const void *cookie,
-                                                                      const void *text,
-                                                                      uint32_t textlen)
-{
-  memcached_protocol_client_st *client= (memcached_protocol_client_st*)cookie;
-  raw_response_handler(client, "VERSION ");
-  client->root->spool(client, text, textlen);
-  raw_response_handler(client, "\r\n");
-  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Callback for the GET/GETQ/GETK and GETKQ responses
- * @param cookie client identifier
- * @param key the key for the item
- * @param keylen the length of the key
- * @param body the length of the body
- * @param bodylen the length of the body
- * @param flags the flags for the item
- * @param cas the CAS id for the item
- */
-static protocol_binary_response_status
-ascii_get_response_handler(const void *cookie,
-                           const void *key,
-                           uint16_t keylen,
-                           const void *body,
-                           uint32_t bodylen,
-                           uint32_t flags,
-                           uint64_t cas)
-{
-  memcached_protocol_client_st *client= (void*)cookie;
-  char buffer[300];
-  strcpy(buffer, "VALUE ");
-  const char *source= key;
-  char *dest= buffer + 6;
-
-  for (int x= 0; x < keylen; ++x)
-  {
-    if (*source != '\0' && !isspace(*source) && !iscntrl(*source))
-    {
-      *dest= *source;
-    }
-    else
-    {
-      return PROTOCOL_BINARY_RESPONSE_EINVAL; /* key constraints in ascii */
-    }
-
-    ++dest;
-    ++source;
-  }
-
-  size_t used= (size_t)(dest - buffer);
-
-  if (client->ascii_command == GETS_CMD)
-  {
-    snprintf(dest, sizeof(buffer) - used, " %u %u %" PRIu64 "\r\n", flags,
-             bodylen, cas);
-  }
-  else
-  {
-    snprintf(dest, sizeof(buffer) - used, " %u %u\r\n", flags, bodylen);
-  }
-
-  client->root->spool(client, buffer, strlen(buffer));
-  client->root->spool(client, body, bodylen);
-  client->root->spool(client, "\r\n", 2);
-
-  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Callback for the STAT responses
- * @param cookie client identifier
- * @param key the key for the item
- * @param keylen the length of the key
- * @param body the length of the body
- * @param bodylen the length of the body
- */
-static protocol_binary_response_status ascii_stat_response_handler(const void *cookie,
-                                                                   const void *key,
-                                                                   uint16_t keylen,
-                                                                   const void *body,
-                                                                   uint32_t bodylen)
-{
-
-  memcached_protocol_client_st *client= (void*)cookie;
-
-  if (key != NULL)
-  {
-    raw_response_handler(client, "STAT ");
-    client->root->spool(client, key, keylen);
-    raw_response_handler(client, " ");
-    client->root->spool(client, body, bodylen);
-    raw_response_handler(client, "\r\n");
-  }
-  else
-  {
-    raw_response_handler(client, "END\r\n");
-  }
-
-  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Process a get or a gets request.
- * @param client the client handle
- * @param buffer the complete get(s) command
- * @param end the last character in the command
- */
-static void ascii_process_gets(memcached_protocol_client_st *client,
-                               char *buffer, char *end)
-{
-  char *key= buffer;
-
-  /* Skip command */
-  key += (client->ascii_command == GETS_CMD) ? 5 : 4;
-
-  int num_keys= 0;
-  while (key < end)
-  {
-    uint16_t nkey= parse_ascii_key(&key);
-    if (nkey == 0) /* Invalid key... stop processing this line */
-    {
-      break;
-    }
-
-    (void)client->root->callback->interface.v1.get(client, key, nkey,
-                                                   ascii_get_response_handler);
-    key += nkey;
-    ++num_keys;
-  }
-
-  if (num_keys == 0)
-  {
-    send_command_usage(client);
-  }
-  else
-  {
-    client->root->spool(client, "END\r\n", 5);
-  }
-}
-
-/**
- * Try to split up the command line "asdf asdf asdf asdf\n" into an
- * argument vector for easier parsing.
- * @param start the first character in the command line
- * @param end the last character in the command line ("\n")
- * @param vec the vector to insert the pointers into
- * @size the number of elements in the vector
- * @return the number of tokens in the vector
- */
-static int ascii_tokenize_command(char *str, char *end, char **vec, int size)
-{
-  int elem= 0;
-
-  while (str < end)
-  {
-    /* Skip leading blanks */
-    while (str < end && isspace(*str))
-    {
-      ++str;
-    }
-
-    if (str == end)
-    {
-      return elem;
-    }
-
-    vec[elem++]= str;
-    /* find the next non-blank field */
-    while (str < end && !isspace(*str))
-    {
-      ++str;
-    }
-
-    /* zero-terminate it for easier parsing later on */
-    *str= '\0';
-    ++str;
-
-    /* Is the vector full? */
-    if (elem == size)
-    {
-      break;
-    }
-  }
-
-  return elem;
-}
-
-/**
- * If we for some reasons needs to push the line back to read more
- * data we have to reverse the tokenization. Just do the brain-dead replace
- * of all '\0' to ' ' and set the last character to '\n'. We could have used
- * the vector we created, but then we would have to search for all of the
- * spaces we ignored...
- * @param start pointer to the first character in the buffer to recover
- * @param end pointer to the last character in the buffer to recover
- */
-static void recover_tokenize_command(char *start, char *end)
-{
-  while (start < end)
-  {
-    if (*start == '\0')
-      *start= ' ';
-    ++start;
-  }
-
-  *end= '\n';
-}
-
-/**
- * Convert the textual command into a comcode
- */
-static enum ascii_cmd ascii_to_cmd(char *start, size_t length)
-{
-  struct {
-    const char *cmd;
-    size_t len;
-    enum ascii_cmd cc;
-  } commands[]= {
-    { .cmd= "get", .len= 3, .cc= GET_CMD },
-    { .cmd= "gets", .len= 4, .cc= GETS_CMD },
-    { .cmd= "set", .len= 3, .cc= SET_CMD },
-    { .cmd= "add", .len= 3, .cc= ADD_CMD },
-    { .cmd= "replace", .len= 7, .cc= REPLACE_CMD },
-    { .cmd= "cas", .len= 3, .cc= CAS_CMD },
-    { .cmd= "append", .len= 6, .cc= APPEND_CMD },
-    { .cmd= "prepend", .len= 7, .cc= PREPEND_CMD },
-    { .cmd= "delete_object", .len= 6, .cc= DELETE_CMD },
-    { .cmd= "incr", .len= 4, .cc= INCR_CMD },
-    { .cmd= "decr", .len= 4, .cc= DECR_CMD },
-    { .cmd= "stats", .len= 5, .cc= STATS_CMD },
-    { .cmd= "flush_all", .len= 9, .cc= FLUSH_ALL_CMD },
-    { .cmd= "version", .len= 7, .cc= VERSION_CMD },
-    { .cmd= "quit", .len= 4, .cc= QUIT_CMD },
-    { .cmd= "verbosity", .len= 9, .cc= VERBOSITY_CMD },
-    { .cmd= NULL, .len= 0, .cc= UNKNOWN_CMD }};
-
-  int x= 0;
-  while (commands[x].len > 0) {
-    if (length >= commands[x].len)
-    {
-      if (strncmp(start, commands[x].cmd, commands[x].len) == 0)
-      {
-        /* Potential hit */
-        if (length == commands[x].len || isspace(*(start + commands[x].len)))
-        {
-          return commands[x].cc;
-        }
-      }
-    }
-    ++x;
-  }
-
-  return UNKNOWN_CMD;
-}
-
-/**
- * Perform a delete_object operation.
- *
- * @param client client requesting the deletion
- * @param tokens the command as a vector
- * @param ntokens the number of items in the vector
- */
-static void process_delete(memcached_protocol_client_st *client,
-                           char **tokens, int ntokens)
-{
-  char *key= tokens[1];
-  uint16_t nkey;
-
-  if (ntokens != 2 || (nkey= parse_ascii_key(&key)) == 0)
-  {
-    send_command_usage(client);
-    return;
-  }
-
-  if (client->root->callback->interface.v1.delete_object == NULL)
-  {
-    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
-    return;
-  }
-
-  protocol_binary_response_status rval= client->root->callback->interface.v1.delete_object(client, key, nkey, 0);
-
-  if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
-  {
-    raw_response_handler(client, "DELETED\r\n");
-  }
-  else if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT)
-  {
-    raw_response_handler(client, "NOT_FOUND\r\n");
-  }
-  else
-  {
-    char msg[80];
-    snprintf(msg, sizeof(msg), "SERVER_ERROR: delete_object failed %u\r\n",(uint32_t)rval);
-    raw_response_handler(client, msg);
-  }
-}
-
-static void process_arithmetic(memcached_protocol_client_st *client,
-                               char **tokens, int ntokens)
-{
-  char *key= tokens[1];
-  uint16_t nkey;
-
-  if (ntokens != 3 || (nkey= parse_ascii_key(&key)) == 0)
-  {
-    send_command_usage(client);
-    return;
-  }
-
-  uint64_t cas;
-  uint64_t result;
-  errno= 0;
-  uint64_t delta= strtoull(tokens[2], NULL, 10);
-  if (errno != 0)
-  {
-    return; // Error
-  }
-
-  protocol_binary_response_status rval;
-  if (client->ascii_command == INCR_CMD)
-  {
-    if (client->root->callback->interface.v1.increment == NULL)
-    {
-      raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
-      return;
-    }
-    rval= client->root->callback->interface.v1.increment(client,
-                                                         key, nkey,
-                                                         delta, 0,
-                                                         0,
-                                                         &result,
-                                                         &cas);
-  }
-  else
-  {
-    if (client->root->callback->interface.v1.decrement == NULL)
-    {
-      raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
-      return;
-    }
-    rval= client->root->callback->interface.v1.decrement(client,
-                                                         key, nkey,
-                                                         delta, 0,
-                                                         0,
-                                                         &result,
-                                                         &cas);
-  }
-
-  if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
-  {
-    char buffer[80];
-    snprintf(buffer, sizeof(buffer), "%"PRIu64"\r\n", result);
-    raw_response_handler(client, buffer);
-  }
-  else
-  {
-    raw_response_handler(client, "NOT_FOUND\r\n");
-  }
-}
-
-/**
- * Process the stats command (with or without a key specified)
- * @param key pointer to the first character after "stats"
- * @param end pointer to the "\n"
- */
-static void process_stats(memcached_protocol_client_st *client,
-                          char *key, char *end)
-{
-  if (client->root->callback->interface.v1.stat == NULL)
-  {
-    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
-    return;
-  }
-
-  while (isspace(*key))
-  {
-    key++;
-  }
-
-  uint16_t nkey= (uint16_t)(end - key);
-  (void)client->root->callback->interface.v1.stat(client, key, nkey,
-                                                  ascii_stat_response_handler);
-}
-
-static void process_version(memcached_protocol_client_st *client,
-                            char **tokens, int ntokens)
-{
-  (void)tokens;
-  if (ntokens != 1)
-  {
-    send_command_usage(client);
-    return;
-  }
-
-  if (client->root->callback->interface.v1.version == NULL)
-  {
-    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
-    return;
-  }
-
- client->root->callback->interface.v1.version(client,
-                                              ascii_version_response_handler);
-}
-
-static void process_flush(memcached_protocol_client_st *client,
-                          char **tokens, int ntokens)
-{
-  if (ntokens > 2)
-  {
-    send_command_usage(client);
-    return;
-  }
-
-  if (client->root->callback->interface.v1.flush_object == NULL)
-  {
-    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
-    return;
-  }
-
-  uint32_t timeout= 0;
-  if (ntokens == 2)
-  {
-    errno= 0;
-    timeout= (uint32_t)strtoul(tokens[1], NULL, 10);
-    if (errno != 0)
-    {
-      return; // Error
-    }
-  }
-
-  protocol_binary_response_status rval;
-  rval= client->root->callback->interface.v1.flush_object(client, timeout);
-  if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
-    raw_response_handler(client, "OK\r\n");
-  else
-    raw_response_handler(client, "SERVER_ERROR: internal error\r\n");
-}
-
-/**
- * Process one of the storage commands
- * @param client the client performing the operation
- * @param tokens the command tokens
- * @param ntokens the number of tokens
- * @param start pointer to the first character in the line
- * @param end pointer to the pointer where the last character of this
- *            command is (IN and OUT)
- * @param length the number of bytes available
- * @return -1 if an error occurs (and we should just terminate the connection
- *            because we are out of sync)
- *         0 storage command completed, continue processing
- *         1 We need more data, so just go ahead and wait for more!
- */
-static inline int process_storage_command(memcached_protocol_client_st *client,
-                                          char **tokens, int ntokens, char *start,
-                                          char **end, ssize_t length)
-{
-  (void)ntokens; /* already checked */
-  char *key= tokens[1];
-  uint16_t nkey= parse_ascii_key(&key);
-  if (nkey == 0)
-  {
-    /* return error */
-    raw_response_handler(client, "CLIENT_ERROR: bad key\r\n");
-    return -1;
-  }
-
-  errno= 0;
-  uint32_t flags= (uint32_t)strtoul(tokens[2], NULL, 10);
-  if (errno != 0)
-  {
-    /* return error */
-    raw_response_handler(client, "CLIENT_ERROR: bad key\r\n");
-    return -1;
-  }
-
-  uint32_t timeout= (uint32_t)strtoul(tokens[3], NULL, 10);
-  if (errno != 0)
-  {
-    /* return error */
-    raw_response_handler(client, "CLIENT_ERROR: bad key\r\n");
-    return -1;
-  }
-
-  unsigned long nbytes= strtoul(tokens[4], NULL, 10);
-  if (errno != 0)
-  {
-    /* return error */
-    raw_response_handler(client, "CLIENT_ERROR: bad key\r\n");
-    return -1;
-  }
-
-  /* Do we have all data? */
-  unsigned long need= nbytes + (unsigned long)((*end - start) + 1) + 2; /* \n\r\n */
-  if ((ssize_t)need > length)
-  {
-    /* Keep on reading */
-    recover_tokenize_command(start, *end);
-    return 1;
-  }
-
-  void *data= (*end) + 1;
-  uint64_t cas= 0;
-  uint64_t result_cas;
-  protocol_binary_response_status rval;
-  switch (client->ascii_command)
-  {
-  case SET_CMD:
-    rval= client->root->callback->interface.v1.set(client, key,
-                                                   (uint16_t)nkey,
-                                                   data,
-                                                   (uint32_t)nbytes,
-                                                   flags,
-                                                   timeout, cas,
-                                                   &result_cas);
-    break;
-  case ADD_CMD:
-    rval= client->root->callback->interface.v1.add(client, key,
-                                                   (uint16_t)nkey,
-                                                   data,
-                                                   (uint32_t)nbytes,
-                                                   flags,
-                                                   timeout, &result_cas);
-    break;
-  case CAS_CMD:
-    errno= 0;
-    cas= strtoull(tokens[5], NULL, 10);
-    if (errno != 0)
-    {
-      /* return error */
-      raw_response_handler(client, "CLIENT_ERROR: bad key\r\n");
-      return -1;
-    }
-    /* FALLTHROUGH */
-  case REPLACE_CMD:
-    rval= client->root->callback->interface.v1.replace(client, key,
-                                                       (uint16_t)nkey,
-                                                       data,
-                                                       (uint32_t)nbytes,
-                                                       flags,
-                                                       timeout, cas,
-                                                       &result_cas);
-    break;
-  case APPEND_CMD:
-    rval= client->root->callback->interface.v1.append(client, key,
-                                                      (uint16_t)nkey,
-                                                      data,
-                                                      (uint32_t)nbytes,
-                                                      cas,
-                                                      &result_cas);
-    break;
-  case PREPEND_CMD:
-    rval= client->root->callback->interface.v1.prepend(client, key,
-                                                       (uint16_t)nkey,
-                                                       data,
-                                                       (uint32_t)nbytes,
-                                                       cas,
-                                                       &result_cas);
-    break;
-
-    /* gcc complains if I don't put all of the enums in here.. */
-  case GET_CMD:
-  case GETS_CMD:
-  case DELETE_CMD:
-  case DECR_CMD:
-  case INCR_CMD:
-  case STATS_CMD:
-  case FLUSH_ALL_CMD:
-  case VERSION_CMD:
-  case QUIT_CMD:
-  case VERBOSITY_CMD:
-  case UNKNOWN_CMD:
-  default:
-    abort(); /* impossible */
-  }
-
-  if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
-  {
-    raw_response_handler(client, "STORED\r\n");
-  }
-  else
-  {
-    if (client->ascii_command == CAS_CMD)
-    {
-      if (rval == PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS)
-      {
-        raw_response_handler(client, "EXISTS\r\n");
-      }
-      else if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT)
-      {
-        raw_response_handler(client, "NOT_FOUND\r\n");
-      }
-      else
-      {
-        raw_response_handler(client, "NOT_STORED\r\n");
-      }
-    }
-    else
-    {
-      raw_response_handler(client, "NOT_STORED\r\n");
-    }
-  }
-
-  *end += nbytes + 2;
-
-  return 0;
-}
-
-static int process_cas_command(memcached_protocol_client_st *client,
-                                char **tokens, int ntokens, char *start,
-                                char **end, ssize_t length)
-{
-  if (ntokens != 6)
-  {
-    send_command_usage(client);
-    return false;
-  }
-
-  if (client->root->callback->interface.v1.replace == NULL)
-  {
-    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
-    return false;
-  }
-
-  return process_storage_command(client, tokens, ntokens, start, end, length);
-}
-
-static int process_set_command(memcached_protocol_client_st *client,
-                                char **tokens, int ntokens, char *start,
-                                char **end, ssize_t length)
-{
-  if (ntokens != 5)
-  {
-    send_command_usage(client);
-    return false;
-  }
-
-  if (client->root->callback->interface.v1.set == NULL)
-  {
-    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
-    return false;
-  }
-
-  return process_storage_command(client, tokens, ntokens, start, end, length);
-}
-
-static int process_add_command(memcached_protocol_client_st *client,
-                                char **tokens, int ntokens, char *start,
-                                char **end, ssize_t length)
-{
-  if (ntokens != 5)
-  {
-    send_command_usage(client);
-    return false;
-  }
-
-  if (client->root->callback->interface.v1.add == NULL)
-  {
-    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
-    return false;
-  }
-
-  return process_storage_command(client, tokens, ntokens, start, end, length);
-}
-
-static int process_replace_command(memcached_protocol_client_st *client,
-                                    char **tokens, int ntokens, char *start,
-                                    char **end, ssize_t length)
-{
-  if (ntokens != 5)
-  {
-    send_command_usage(client);
-    return false;
-  }
-
-  if (client->root->callback->interface.v1.replace == NULL)
-  {
-    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
-    return false;
-  }
-
-  return process_storage_command(client, tokens, ntokens, start, end, length);
-}
-
-static int process_append_command(memcached_protocol_client_st *client,
-                                   char **tokens, int ntokens, char *start,
-                                   char **end, ssize_t length)
-{
-  if (ntokens != 5)
-  {
-    send_command_usage(client);
-    return false;
-  }
-
-  if (client->root->callback->interface.v1.append == NULL)
-  {
-    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
-    return false;
-  }
-
-  return process_storage_command(client, tokens, ntokens, start, end, length);
-}
-
-static int process_prepend_command(memcached_protocol_client_st *client,
-                                    char **tokens, int ntokens, char *start,
-                                    char **end, ssize_t length)
-{
-  if (ntokens != 5)
-  {
-    send_command_usage(client);
-    return false;
-  }
-
-  if (client->root->callback->interface.v1.prepend == NULL)
-  {
-    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
-    return false;
-  }
-
-  return process_storage_command(client, tokens, ntokens, start, end, length);
-}
-
-/**
- * The ASCII protocol support is just one giant big hack. Instead of adding
- * a optimal ascii support, I just convert the ASCII commands to the binary
- * protocol and calls back into the command handlers for the binary protocol ;)
- */
-memcached_protocol_event_t memcached_ascii_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr)
-{
-  char *ptr= (char*)client->root->input_buffer;
-  *endptr= ptr;
-
-  do {
-    /* Do we have \n (indicating the command preamble)*/
-    char *end= memchr(ptr, '\n', (size_t)*length);
-    if (end == NULL)
-    {
-      *endptr= ptr;
-      return MEMCACHED_PROTOCOL_READ_EVENT;
-    }
-
-    client->ascii_command= ascii_to_cmd(ptr, (size_t)(*length));
-
-    /* we got all data available, execute the callback! */
-    if (client->root->callback->pre_execute != NULL)
-    {
-      client->root->callback->pre_execute(client, NULL);
-    }
-
-
-    /* A multiget lists all of the keys, and I don't want to have an
-     * avector of let's say 512 pointers to tokenize all of them, so let's
-     * just handle them immediately
-     */
-    if (client->ascii_command == GET_CMD ||
-        client->ascii_command == GETS_CMD)
-    {
-      if (client->root->callback->interface.v1.get != NULL)
-      {
-        ascii_process_gets(client, ptr, end);
-      }
-      else
-      {
-        raw_response_handler(client, "SERVER_ERROR: Command not implemented\n");
-      }
-    }
-    else
-    {
-      /* None of the defined commands takes 10 parameters, so lets just use
-       * that as a maximum limit.
-     */
-      char *tokens[10];
-      int ntokens= ascii_tokenize_command(ptr, end, tokens, 10);
-
-      if (ntokens < 10)
-      {
-        client->mute= strcmp(tokens[ntokens - 1], "noreply") == 0;
-        if (client->mute)
-        {
-          --ntokens; /* processed noreply token*/
-        }
-      }
-
-      int error= 0;
-
-      print_ascii_command(client);
-      switch (client->ascii_command)
-      {
-      case SET_CMD:
-        error= process_set_command(client, tokens, ntokens, ptr, &end, *length);
-        break;
-
-      case ADD_CMD:
-        error= process_add_command(client, tokens, ntokens, ptr, &end, *length);
-        break;
-
-      case REPLACE_CMD:
-        error= process_replace_command(client, tokens, ntokens, ptr, &end, *length);
-        break;
-
-      case CAS_CMD:
-        error= process_cas_command(client, tokens, ntokens, ptr, &end, *length);
-        break;
-
-      case APPEND_CMD:
-        error= process_append_command(client, tokens, ntokens, ptr, &end, *length);
-        break;
-
-      case PREPEND_CMD:
-        error= process_prepend_command(client, tokens, ntokens, ptr, &end, *length);
-        break;
-
-      case DELETE_CMD:
-        process_delete(client, tokens, ntokens);
-        break;
-
-      case INCR_CMD: /* FALLTHROUGH */
-      case DECR_CMD:
-        process_arithmetic(client, tokens, ntokens);
-        break;
-
-      case STATS_CMD:
-        if (client->mute)
-        {
-          send_command_usage(client);
-        }
-        else
-        {
-          recover_tokenize_command(ptr, end);
-          process_stats(client, ptr + 6, end);
-        }
-        break;
-
-      case FLUSH_ALL_CMD:
-        process_flush(client, tokens, ntokens);
-        break;
-
-      case VERSION_CMD:
-        if (client->mute)
-        {
-          send_command_usage(client);
-        }
-        else
-        {
-          process_version(client, tokens, ntokens);
-        }
-        break;
-
-      case QUIT_CMD:
-        if (ntokens != 1 || client->mute)
-        {
-          send_command_usage(client);
-        }
-        else
-        {
-          if (client->root->callback->interface.v1.quit != NULL)
-          {
-            client->root->callback->interface.v1.quit(client);
-          }
-
-          return MEMCACHED_PROTOCOL_ERROR_EVENT;
-        }
-        break;
-
-      case VERBOSITY_CMD:
-        if (ntokens != 2)
-        {
-          send_command_usage(client);
-        }
-        else
-        {
-          raw_response_handler(client, "OK\r\n");
-        }
-        break;
-
-      case UNKNOWN_CMD:
-        send_command_usage(client);
-        break;
-
-      case GET_CMD:
-      case GETS_CMD:
-      default:
-        /* Should already be handled */
-        abort();
-      }
-
-      if (error == -1)
-      {
-        return MEMCACHED_PROTOCOL_ERROR_EVENT;
-      }
-      else if (error == 1)
-      {
-        return MEMCACHED_PROTOCOL_READ_EVENT;
-      }
-    }
-
-    if (client->root->callback->post_execute != NULL)
-    {
-      client->root->callback->post_execute(client, NULL);
-    }
-
-    /* Move past \n */
-    ++end;
-    *length -= end - ptr;
-    ptr= end;
-  } while (*length > 0);
-
-  *endptr= ptr;
-  return MEMCACHED_PROTOCOL_READ_EVENT;
-}
diff --git a/libmemcachedprotocol/ascii_handler.h b/libmemcachedprotocol/ascii_handler.h
deleted file mode 100644 (file)
index 02f8831..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-LIBMEMCACHED_LOCAL
-memcached_protocol_event_t memcached_ascii_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr);
diff --git a/libmemcachedprotocol/binary_handler.c b/libmemcachedprotocol/binary_handler.c
deleted file mode 100644 (file)
index d720424..0000000
+++ /dev/null
@@ -1,1198 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <libmemcachedprotocol/common.h>
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <string.h>
-#include <stdio.h>
-
-/*
-** **********************************************************************
-** INTERNAL INTERFACE
-** **********************************************************************
-*/
-
-/**
- * Send a preformatted packet back to the client. If the connection is in
- * pedantic mode, it will validate the packet and refuse to send it if it
- * breaks the specification.
- *
- * @param cookie client identification
- * @param request the original request packet
- * @param response the packet to send
- * @return The status of the operation
- */
-static protocol_binary_response_status raw_response_handler(const void *cookie,
-                                                            protocol_binary_request_header *request,
-                                                            protocol_binary_response_header *response)
-{
-  memcached_protocol_client_st *client= (void*)cookie;
-
-  if (client->root->pedantic &&
-      !memcached_binary_protocol_pedantic_check_response(request, response))
-  {
-    return PROTOCOL_BINARY_RESPONSE_EINVAL;
-  }
-
-  if (client->root->drain(client) == false)
-  {
-    return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
-  }
-
-  size_t len= sizeof(protocol_binary_response_header) + htonl(response->response.bodylen);
-  size_t offset= 0;
-  char *ptr= (void*)response;
-
-  if (client->output == NULL)
-  {
-    /* I can write directly to the socket.... */
-    do
-    {
-      size_t num_bytes= len - offset;
-      ssize_t nw= client->root->send(client,
-                                     client->sock,
-                                     ptr + offset,
-                                     num_bytes);
-      if (nw == -1)
-      {
-        if (get_socket_errno() == EWOULDBLOCK)
-        {
-          break;
-        }
-        else if (get_socket_errno() != EINTR)
-        {
-          client->error= errno;
-          return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
-        }
-      }
-      else
-      {
-        offset += (size_t)nw;
-      }
-    } while (offset < len);
-  }
-
-  return client->root->spool(client, ptr, len - offset);
-}
-
-static void print_cmd(protocol_binary_command cmd)
-{
-  switch (cmd)
-  {
-  case PROTOCOL_BINARY_CMD_GET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GET\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_SET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SET\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_ADD: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_ADD\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_REPLACE: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_REPLACE\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_DELETE: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_DELETE\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_INCREMENT: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_INCREMENT\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_DECREMENT: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_DECREMENT\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_QUIT: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_QUIT\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_FLUSH: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_FLUSH\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_GETQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GETQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_NOOP: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_NOOP\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_VERSION: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_VERSION\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_GETK: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GETK\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_GETKQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GETKQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_APPEND: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_APPEND\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_PREPEND: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_PREPEND\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_STAT: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_STAT\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_SETQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SETQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_ADDQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_ADDQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_REPLACEQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_REPLACEQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_DELETEQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_DELETEQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_INCREMENTQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_INCREMENTQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_DECREMENTQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_DECREMENTQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_QUITQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_QUITQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_FLUSHQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_FLUSHQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_APPENDQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_APPENDQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_PREPENDQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_PREPENDQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_VERBOSITY: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_VERBOSITY\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_TOUCH: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TOUCH\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_GAT: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GAT\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_GATQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GATQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SASL_LIST_MECHS\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_SASL_AUTH: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SASL_AUTH\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_SASL_STEP: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SASL_STEP\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_RGET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RGET\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_RSET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RSET\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_RSETQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RSETQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_RAPPEND: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RAPPEND\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_RAPPENDQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RAPPENDQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_RPREPEND: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RPREPEND\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_RPREPENDQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RPREPENDQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_RDELETE: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RDELETE\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_RDELETEQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RDELETEQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_RINCR: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RINCR\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_RINCRQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RINCRQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_RDECR: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RDECR\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_RDECRQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RDECRQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_SET_VBUCKET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SET_VBUCKET\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_GET_VBUCKET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GET_VBUCKET\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_DEL_VBUCKET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_DEL_VBUCKET\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_TAP_CONNECT: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_CONNECT\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_TAP_MUTATION: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_MUTATION\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_TAP_DELETE: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_DELETE\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_TAP_FLUSH: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_FLUSH\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_TAP_OPAQUE: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_OPAQUE\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_TAP_VBUCKET_SET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_VBUCKET_SET\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_START: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_START\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_END: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_END\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_LAST_RESERVED: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_LAST_RESERVED\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_GATK: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GATK\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_GATKQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GATKQ\n", __FILE__, __LINE__); return;
-  case PROTOCOL_BINARY_CMD_SCRUB: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SCRUB\n", __FILE__, __LINE__); return;
-  default:
-                                  abort();
-  }
-}
-
-/*
- * Version 0 of the interface is really low level and protocol specific,
- * while the version 1 of the interface is more API focused. We need a
- * way to translate between the command codes on the wire and the
- * application level interface in V1, so let's just use the V0 of the
- * interface as a map instead of creating a huuuge switch :-)
- */
-
-/**
- * Callback for the GET/GETQ/GETK and GETKQ responses
- * @param cookie client identifier
- * @param key the key for the item
- * @param keylen the length of the key
- * @param body the length of the body
- * @param bodylen the length of the body
- * @param flags the flags for the item
- * @param cas the CAS id for the item
- */
-static protocol_binary_response_status get_response_handler(const void *cookie,
-                                                            const void *key,
-                                                            uint16_t keylen,
-                                                            const void *body,
-                                                            uint32_t bodylen,
-                                                            uint32_t flags,
-                                                            uint64_t cas)
-{
-  memcached_protocol_client_st *client= (void*)cookie;
-  uint8_t opcode= client->current_command->request.opcode;
-
-  if (opcode == PROTOCOL_BINARY_CMD_GET || opcode == PROTOCOL_BINARY_CMD_GETQ)
-  {
-    keylen= 0;
-  }
-
-  protocol_binary_response_get response= {
-    .message.header.response= {
-      .magic= PROTOCOL_BINARY_RES,
-      .opcode= opcode,
-      .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-      .opaque= client->current_command->request.opaque,
-      .cas= memcached_htonll(cas),
-      .keylen= htons(keylen),
-      .extlen= 4,
-      .bodylen= htonl(bodylen + keylen + 4),
-    },
-  };
-
-  response.message.body.flags= htonl(flags);
-
-  protocol_binary_response_status rval;
-  const protocol_binary_response_status success= PROTOCOL_BINARY_RESPONSE_SUCCESS;
-  if ((rval= client->root->spool(client, response.bytes, sizeof(response.bytes))) != success ||
-      (rval= client->root->spool(client, key, keylen)) != success ||
-      (rval= client->root->spool(client, body, bodylen)) != success)
-  {
-    return rval;
-  }
-
-  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Callback for the STAT responses
- * @param cookie client identifier
- * @param key the key for the item
- * @param keylen the length of the key
- * @param body the length of the body
- * @param bodylen the length of the body
- */
-static protocol_binary_response_status stat_response_handler(const void *cookie,
-                                                             const void *key,
-                                                             uint16_t keylen,
-                                                             const void *body,
-                                                             uint32_t bodylen)
-{
-
-  memcached_protocol_client_st *client= (void*)cookie;
-
-  protocol_binary_response_no_extras response= {
-    .message.header.response= {
-      .magic= PROTOCOL_BINARY_RES,
-      .opcode= client->current_command->request.opcode,
-      .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-      .opaque= client->current_command->request.opaque,
-      .keylen= htons(keylen),
-      .bodylen= htonl(bodylen + keylen),
-      .cas= 0
-    },
-  };
-
-  protocol_binary_response_status rval;
-  const protocol_binary_response_status success= PROTOCOL_BINARY_RESPONSE_SUCCESS;
-  if ((rval= client->root->spool(client, response.bytes, sizeof(response.bytes))) != success ||
-      (rval= client->root->spool(client, key, keylen)) != success ||
-      (rval= client->root->spool(client, body, bodylen)) != success)
-  {
-    return rval;
-  }
-
-  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Callback for the VERSION responses
- * @param cookie client identifier
- * @param text the length of the body
- * @param textlen the length of the body
- */
-static protocol_binary_response_status version_response_handler(const void *cookie,
-                                                                const void *text,
-                                                                uint32_t textlen)
-{
-
-  memcached_protocol_client_st *client= (void*)cookie;
-
-  protocol_binary_response_no_extras response= {
-    .message.header.response= {
-      .magic= PROTOCOL_BINARY_RES,
-      .opcode= client->current_command->request.opcode,
-      .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-      .opaque= client->current_command->request.opaque,
-      .bodylen= htonl(textlen),
-      .cas= 0
-    },
-  };
-
-  protocol_binary_response_status rval;
-  const protocol_binary_response_status success= PROTOCOL_BINARY_RESPONSE_SUCCESS;
-  if ((rval= client->root->spool(client, response.bytes, sizeof(response.bytes))) != success ||
-      (rval= client->root->spool(client, text, textlen)) != success)
-  {
-    return rval;
-  }
-
-  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Callback for ADD and ADDQ
- * @param cookie the calling client
- * @param header the add/addq command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-add_command_handler(const void *cookie,
-                    protocol_binary_request_header *header,
-                    memcached_binary_protocol_raw_response_handler response_handler)
-{
-  protocol_binary_response_status rval;
-
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.add != NULL)
-  {
-    uint16_t keylen= ntohs(header->request.keylen);
-    uint32_t datalen= ntohl(header->request.bodylen) - keylen - 8;
-    protocol_binary_request_add *request= (void*)header;
-    uint32_t flags= ntohl(request->message.body.flags);
-    uint32_t timeout= ntohl(request->message.body.expiration);
-    char *key= ((char*)header) + sizeof(*header) + 8;
-    char *data= key + keylen;
-    uint64_t cas;
-
-    rval= client->root->callback->interface.v1.add(cookie, key, keylen,
-                                                   data, datalen, flags,
-                                                   timeout, &cas);
-
-    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
-        header->request.opcode == PROTOCOL_BINARY_CMD_ADD)
-    {
-      /* Send a positive request */
-      protocol_binary_response_no_extras response= {
-        .message= {
-          .header.response= {
-            .magic= PROTOCOL_BINARY_RES,
-            .opcode= PROTOCOL_BINARY_CMD_ADD,
-            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-            .opaque= header->request.opaque,
-            .cas= memcached_ntohll(cas)
-          }
-        }
-      };
-      rval= response_handler(cookie, header, (void*)&response);
-    }
-  }
-  else
-  {
-    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
-  }
-
-  return rval;
-}
-
-/**
- * Callback for DECREMENT and DECREMENTQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-decrement_command_handler(const void *cookie,
-                          protocol_binary_request_header *header,
-                          memcached_binary_protocol_raw_response_handler response_handler)
-{
-  (void)response_handler;
-  protocol_binary_response_status rval;
-
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.decrement != NULL)
-  {
-    uint16_t keylen= ntohs(header->request.keylen);
-    protocol_binary_request_decr *request= (void*)header;
-    uint64_t init= memcached_ntohll(request->message.body.initial);
-    uint64_t delta= memcached_ntohll(request->message.body.delta);
-    uint32_t timeout= ntohl(request->message.body.expiration);
-    void *key= request->bytes + sizeof(request->bytes);
-    uint64_t result;
-    uint64_t cas;
-
-    rval= client->root->callback->interface.v1.decrement(cookie, key, keylen,
-                                                         delta, init, timeout,
-                                                         &result, &cas);
-    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
-        header->request.opcode == PROTOCOL_BINARY_CMD_DECREMENT)
-    {
-      /* Send a positive request */
-      protocol_binary_response_decr response= {
-        .message= {
-          .header.response= {
-            .magic= PROTOCOL_BINARY_RES,
-            .opcode= PROTOCOL_BINARY_CMD_DECREMENT,
-            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-            .opaque= header->request.opaque,
-            .cas= memcached_ntohll(cas),
-            .bodylen= htonl(8)
-          },
-          .body.value= memcached_htonll(result)
-        }
-      };
-      rval= response_handler(cookie, header, (void*)&response);
-    }
-  }
-  else
-  {
-    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
-  }
-
-  return rval;
-}
-
-/**
- * Callback for DELETE and DELETEQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status delete_command_handler(const void *cookie,
-                                                              protocol_binary_request_header *header,
-                                                              memcached_binary_protocol_raw_response_handler response_handler)
-{
-  (void)response_handler;
-  protocol_binary_response_status rval;
-
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.delete_object != NULL)
-  {
-    uint16_t keylen= ntohs(header->request.keylen);
-    void *key= (header +1);
-    uint64_t cas= memcached_ntohll(header->request.cas);
-    rval= client->root->callback->interface.v1.delete_object(cookie, key, keylen, cas);
-    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
-        header->request.opcode == PROTOCOL_BINARY_CMD_DELETE)
-    {
-      /* Send a positive request */
-      protocol_binary_response_no_extras response= {
-        .message= {
-          .header.response= {
-            .magic= PROTOCOL_BINARY_RES,
-            .opcode= PROTOCOL_BINARY_CMD_DELETE,
-            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-            .opaque= header->request.opaque,
-          }
-        }
-      };
-      rval= response_handler(cookie, header, (void*)&response);
-    }
-  }
-  else
-  {
-    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
-  }
-
-  return rval;
-}
-
-/**
- * Callback for FLUSH and FLUSHQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-flush_command_handler(const void *cookie,
-                      protocol_binary_request_header *header,
-                      memcached_binary_protocol_raw_response_handler response_handler)
-{
-  (void)response_handler;
-  protocol_binary_response_status rval;
-
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.flush_object != NULL)
-  {
-    protocol_binary_request_flush *flush_object= (void*)header;
-    uint32_t timeout= 0;
-    if (htonl(header->request.bodylen) == 4)
-    {
-      timeout= ntohl(flush_object->message.body.expiration);
-    }
-
-    rval= client->root->callback->interface.v1.flush_object(cookie, timeout);
-    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
-        header->request.opcode == PROTOCOL_BINARY_CMD_FLUSH)
-    {
-      /* Send a positive request */
-      protocol_binary_response_no_extras response= {
-        .message= {
-          .header.response= {
-            .magic= PROTOCOL_BINARY_RES,
-            .opcode= PROTOCOL_BINARY_CMD_FLUSH,
-            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-            .opaque= header->request.opaque,
-          }
-        }
-      };
-      rval= response_handler(cookie, header, (void*)&response);
-    }
-  }
-  else
-  {
-    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
-  }
-
-  return rval;
-}
-
-/**
- * Callback for GET, GETK, GETQ, GETKQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-get_command_handler(const void *cookie,
-                    protocol_binary_request_header *header,
-                    memcached_binary_protocol_raw_response_handler response_handler)
-{
-  (void)response_handler;
-  protocol_binary_response_status rval;
-
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.get != NULL)
-  {
-    uint16_t keylen= ntohs(header->request.keylen);
-    void *key= (header + 1);
-    rval= client->root->callback->interface.v1.get(cookie, key, keylen,
-                                                   get_response_handler);
-
-    if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT &&
-        (header->request.opcode == PROTOCOL_BINARY_CMD_GETQ ||
-         header->request.opcode == PROTOCOL_BINARY_CMD_GETKQ))
-    {
-      /* Quiet commands shouldn't respond on cache misses */
-      rval= PROTOCOL_BINARY_RESPONSE_SUCCESS;
-    }
-  }
-  else
-  {
-    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
-  }
-
-  return rval;
-}
-
-/**
- * Callback for INCREMENT and INCREMENTQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-increment_command_handler(const void *cookie,
-                          protocol_binary_request_header *header,
-                          memcached_binary_protocol_raw_response_handler response_handler)
-{
-  (void)response_handler;
-  protocol_binary_response_status rval;
-
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.increment != NULL)
-  {
-    uint16_t keylen= ntohs(header->request.keylen);
-    protocol_binary_request_incr *request= (void*)header;
-    uint64_t init= memcached_ntohll(request->message.body.initial);
-    uint64_t delta= memcached_ntohll(request->message.body.delta);
-    uint32_t timeout= ntohl(request->message.body.expiration);
-    void *key= request->bytes + sizeof(request->bytes);
-    uint64_t cas;
-    uint64_t result;
-
-    rval= client->root->callback->interface.v1.increment(cookie, key, keylen,
-                                                         delta, init, timeout,
-                                                         &result, &cas);
-    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
-        header->request.opcode == PROTOCOL_BINARY_CMD_INCREMENT)
-    {
-      /* Send a positive request */
-      protocol_binary_response_incr response= {
-        .message= {
-          .header.response= {
-            .magic= PROTOCOL_BINARY_RES,
-            .opcode= PROTOCOL_BINARY_CMD_INCREMENT,
-            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-            .opaque= header->request.opaque,
-            .cas= memcached_ntohll(cas),
-            .bodylen= htonl(8)
-          },
-          .body.value= memcached_htonll(result)
-        }
-      };
-
-      rval= response_handler(cookie, header, (void*)&response);
-    }
-  }
-  else
-  {
-    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
-  }
-
-  return rval;
-}
-
-/**
- * Callback for noop. Inform the v1 interface about the noop packet, and
- * create and send a packet back to the client
- *
- * @param cookie the calling client
- * @param header the command
- * @param response_handler the response handler
- * @return the result of the operation
- */
-static protocol_binary_response_status
-noop_command_handler(const void *cookie,
-                     protocol_binary_request_header *header,
-                     memcached_binary_protocol_raw_response_handler response_handler)
-{
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.noop != NULL)
-  {
-    client->root->callback->interface.v1.noop(cookie);
-  }
-
-  protocol_binary_response_no_extras response= {
-    .message= {
-      .header.response= {
-        .magic= PROTOCOL_BINARY_RES,
-        .opcode= PROTOCOL_BINARY_CMD_NOOP,
-        .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-        .opaque= header->request.opaque,
-      }
-    }
-  };
-
-  return response_handler(cookie, header, (void*)&response);
-}
-
-/**
- * Callback for APPEND and APPENDQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-append_command_handler(const void *cookie,
-                       protocol_binary_request_header *header,
-                       memcached_binary_protocol_raw_response_handler response_handler)
-{
-  (void)response_handler;
-  protocol_binary_response_status rval;
-
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.append != NULL)
-  {
-    uint16_t keylen= ntohs(header->request.keylen);
-    uint32_t datalen= ntohl(header->request.bodylen) - keylen;
-    char *key= (void*)(header +1);
-    char *data= key +keylen;
-    uint64_t cas= memcached_ntohll(header->request.cas);
-    uint64_t result_cas;
-
-    rval= client->root->callback->interface.v1.append(cookie, key, keylen,
-                                                      data, datalen, cas,
-                                                      &result_cas);
-    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
-        header->request.opcode == PROTOCOL_BINARY_CMD_APPEND)
-    {
-      /* Send a positive request */
-      protocol_binary_response_no_extras response= {
-        .message= {
-          .header.response= {
-            .magic= PROTOCOL_BINARY_RES,
-            .opcode= PROTOCOL_BINARY_CMD_APPEND,
-            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-            .opaque= header->request.opaque,
-            .cas= memcached_ntohll(result_cas),
-          },
-        }
-      };
-      rval= response_handler(cookie, header, (void*)&response);
-    }
-  }
-  else
-  {
-    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
-  }
-
-  return rval;
-}
-
-/**
- * Callback for PREPEND and PREPENDQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-prepend_command_handler(const void *cookie,
-                        protocol_binary_request_header *header,
-                        memcached_binary_protocol_raw_response_handler response_handler)
-{
-  (void)response_handler;
-  protocol_binary_response_status rval;
-
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.prepend != NULL)
-  {
-    uint16_t keylen= ntohs(header->request.keylen);
-    uint32_t datalen= ntohl(header->request.bodylen) - keylen;
-    char *key= (char*)(header + 1);
-    char *data= key + keylen;
-    uint64_t cas= memcached_ntohll(header->request.cas);
-    uint64_t result_cas;
-    rval= client->root->callback->interface.v1.prepend(cookie, key, keylen,
-                                                       data, datalen, cas,
-                                                       &result_cas);
-    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
-        header->request.opcode == PROTOCOL_BINARY_CMD_PREPEND)
-    {
-      /* Send a positive request */
-      protocol_binary_response_no_extras response= {
-        .message= {
-          .header.response= {
-            .magic= PROTOCOL_BINARY_RES,
-            .opcode= PROTOCOL_BINARY_CMD_PREPEND,
-            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-            .opaque= header->request.opaque,
-            .cas= memcached_ntohll(result_cas),
-          },
-        }
-      };
-      rval= response_handler(cookie, header, (void*)&response);
-    }
-  }
-  else
-  {
-    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
-  }
-
-  return rval;
-}
-
-/**
- * Callback for QUIT and QUITQ. Notify the client and shut down the connection
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-quit_command_handler(const void *cookie,
-                     protocol_binary_request_header *header,
-                     memcached_binary_protocol_raw_response_handler response_handler)
-{
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.quit != NULL)
-  {
-    client->root->callback->interface.v1.quit(cookie);
-  }
-
-  protocol_binary_response_no_extras response= {
-    .message= {
-      .header.response= {
-        .magic= PROTOCOL_BINARY_RES,
-        .opcode= PROTOCOL_BINARY_CMD_QUIT,
-        .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-        .opaque= header->request.opaque
-      }
-    }
-  };
-
-  if (header->request.opcode == PROTOCOL_BINARY_CMD_QUIT)
-  {
-    response_handler(cookie, header, (void*)&response);
-  }
-
-  /* I need a better way to signal to close the connection */
-  return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
-}
-
-/**
- * Callback for REPLACE and REPLACEQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-replace_command_handler(const void *cookie,
-                        protocol_binary_request_header *header,
-                        memcached_binary_protocol_raw_response_handler response_handler)
-{
-  (void)response_handler;
-  protocol_binary_response_status rval;
-
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.replace != NULL)
-  {
-    uint16_t keylen= ntohs(header->request.keylen);
-    uint32_t datalen= ntohl(header->request.bodylen) - keylen - 8;
-    protocol_binary_request_replace *request= (void*)header;
-    uint32_t flags= ntohl(request->message.body.flags);
-    uint32_t timeout= ntohl(request->message.body.expiration);
-    char *key= ((char*)header) + sizeof(*header) + 8;
-    char *data= key + keylen;
-    uint64_t cas= memcached_ntohll(header->request.cas);
-    uint64_t result_cas;
-
-    rval= client->root->callback->interface.v1.replace(cookie, key, keylen,
-                                                       data, datalen, flags,
-                                                       timeout, cas,
-                                                       &result_cas);
-    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
-        header->request.opcode == PROTOCOL_BINARY_CMD_REPLACE)
-    {
-      /* Send a positive request */
-      protocol_binary_response_no_extras response= {
-        .message= {
-          .header.response= {
-            .magic= PROTOCOL_BINARY_RES,
-            .opcode= PROTOCOL_BINARY_CMD_REPLACE,
-            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-            .opaque= header->request.opaque,
-            .cas= memcached_ntohll(result_cas),
-          },
-        }
-      };
-      rval= response_handler(cookie, header, (void*)&response);
-    }
-  }
-  else
-  {
-    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
-  }
-
-  return rval;
-}
-
-/**
- * Callback for SET and SETQ
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status set_command_handler(const void *cookie,
-                                                           protocol_binary_request_header *header,
-                                                           memcached_binary_protocol_raw_response_handler response_handler)
-{
-  (void)response_handler;
-  protocol_binary_response_status rval;
-
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.set != NULL)
-  {
-    uint16_t keylen= ntohs(header->request.keylen);
-    uint32_t datalen= ntohl(header->request.bodylen) - keylen - 8;
-    protocol_binary_request_replace *request= (void*)header;
-    uint32_t flags= ntohl(request->message.body.flags);
-    uint32_t timeout= ntohl(request->message.body.expiration);
-    char *key= ((char*)header) + sizeof(*header) + 8;
-    char *data= key + keylen;
-    uint64_t cas= memcached_ntohll(header->request.cas);
-    uint64_t result_cas;
-
-
-    rval= client->root->callback->interface.v1.set(cookie, key, keylen,
-                                                   data, datalen, flags,
-                                                   timeout, cas, &result_cas);
-    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
-        header->request.opcode == PROTOCOL_BINARY_CMD_SET)
-    {
-      /* Send a positive request */
-      protocol_binary_response_no_extras response= {
-        .message= {
-          .header.response= {
-            .magic= PROTOCOL_BINARY_RES,
-            .opcode= PROTOCOL_BINARY_CMD_SET,
-            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
-            .opaque= header->request.opaque,
-            .cas= memcached_ntohll(result_cas),
-          },
-        }
-      };
-      rval= response_handler(cookie, header, (void*)&response);
-    }
-  }
-  else
-  {
-    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
-  }
-
-  return rval;
-}
-
-/**
- * Callback for STAT
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-stat_command_handler(const void *cookie,
-                     protocol_binary_request_header *header,
-                     memcached_binary_protocol_raw_response_handler response_handler)
-{
-  (void)response_handler;
-  protocol_binary_response_status rval;
-
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.stat != NULL)
-  {
-    uint16_t keylen= ntohs(header->request.keylen);
-
-    rval= client->root->callback->interface.v1.stat(cookie,
-                                                    (void*)(header + 1),
-                                                    keylen,
-                                                    stat_response_handler);
-  }
-  else
-  {
-    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
-  }
-
-  return rval;
-}
-
-/**
- * Callback for VERSION
- * @param cookie the calling client
- * @param header the command
- * @param response_handler not used
- * @return the result of the operation
- */
-static protocol_binary_response_status
-version_command_handler(const void *cookie,
-                        protocol_binary_request_header *header,
-                        memcached_binary_protocol_raw_response_handler response_handler)
-{
-  (void)response_handler;
-  (void)header;
-  protocol_binary_response_status rval;
-
-  memcached_protocol_client_st *client= (void*)cookie;
-  if (client->root->callback->interface.v1.version != NULL)
-  {
-    rval= client->root->callback->interface.v1.version(cookie,
-                                                       version_response_handler);
-  }
-  else
-  {
-    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
-  }
-
-  return rval;
-}
-
-/**
- * The map to remap between the com codes and the v1 logical setting
- */
-static memcached_binary_protocol_command_handler comcode_v0_v1_remap[256]= {
-  [PROTOCOL_BINARY_CMD_ADDQ]= add_command_handler,
-  [PROTOCOL_BINARY_CMD_ADD]= add_command_handler,
-  [PROTOCOL_BINARY_CMD_APPENDQ]= append_command_handler,
-  [PROTOCOL_BINARY_CMD_APPEND]= append_command_handler,
-  [PROTOCOL_BINARY_CMD_DECREMENTQ]= decrement_command_handler,
-  [PROTOCOL_BINARY_CMD_DECREMENT]= decrement_command_handler,
-  [PROTOCOL_BINARY_CMD_DELETEQ]= delete_command_handler,
-  [PROTOCOL_BINARY_CMD_DELETE]= delete_command_handler,
-  [PROTOCOL_BINARY_CMD_FLUSHQ]= flush_command_handler,
-  [PROTOCOL_BINARY_CMD_FLUSH]= flush_command_handler,
-  [PROTOCOL_BINARY_CMD_GETKQ]= get_command_handler,
-  [PROTOCOL_BINARY_CMD_GETK]= get_command_handler,
-  [PROTOCOL_BINARY_CMD_GETQ]= get_command_handler,
-  [PROTOCOL_BINARY_CMD_GET]= get_command_handler,
-  [PROTOCOL_BINARY_CMD_INCREMENTQ]= increment_command_handler,
-  [PROTOCOL_BINARY_CMD_INCREMENT]= increment_command_handler,
-  [PROTOCOL_BINARY_CMD_NOOP]= noop_command_handler,
-  [PROTOCOL_BINARY_CMD_PREPENDQ]= prepend_command_handler,
-  [PROTOCOL_BINARY_CMD_PREPEND]= prepend_command_handler,
-  [PROTOCOL_BINARY_CMD_QUITQ]= quit_command_handler,
-  [PROTOCOL_BINARY_CMD_QUIT]= quit_command_handler,
-  [PROTOCOL_BINARY_CMD_REPLACEQ]= replace_command_handler,
-  [PROTOCOL_BINARY_CMD_REPLACE]= replace_command_handler,
-  [PROTOCOL_BINARY_CMD_SETQ]= set_command_handler,
-  [PROTOCOL_BINARY_CMD_SET]= set_command_handler,
-  [PROTOCOL_BINARY_CMD_STAT]= stat_command_handler,
-  [PROTOCOL_BINARY_CMD_VERSION]= version_command_handler,
-};
-
-/**
- * Try to execute a command. Fire the pre/post functions and the specialized
- * handler function if it's set. If not, the unknown probe should be fired
- * if it's present.
- * @param client the client connection to operate on
- * @param header the command to execute
- * @return true if success or false if a fatal error occured so that the
- *         connection should be shut down.
- */
-static protocol_binary_response_status execute_command(memcached_protocol_client_st *client, protocol_binary_request_header *header)
-{
-  if (client->root->pedantic &&
-      memcached_binary_protocol_pedantic_check_request(header))
-  {
-      /* @todo return invalid command packet */
-  }
-
-  /* we got all data available, execute the callback! */
-  if (client->root->callback->pre_execute != NULL)
-  {
-    client->root->callback->pre_execute(client, header);
-  }
-
-  protocol_binary_response_status rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
-  uint8_t cc= header->request.opcode;
-
-  if (client->is_verbose)
-  {
-    print_cmd(cc);
-  }
-
-  switch (client->root->callback->interface_version)
-  {
-  case 0:
-    if (client->root->callback->interface.v0.comcode[cc] != NULL)
-    {
-      rval= client->root->callback->interface.v0.comcode[cc](client, header, raw_response_handler);
-    }
-    break;
-
-  case 1:
-    if (comcode_v0_v1_remap[cc] != NULL)
-    {
-      rval= comcode_v0_v1_remap[cc](client, header, raw_response_handler);
-    }
-    break;
-
-  default:
-    /* Unknown interface.
-     * It should be impossible to get here so I'll just call abort
-     * to avoid getting a compiler warning :-)
-     */
-    abort();
-  }
-
-
-  if (rval == PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND &&
-      client->root->callback->unknown != NULL)
-  {
-    rval= client->root->callback->unknown(client, header, raw_response_handler);
-  }
-
-  if (rval != PROTOCOL_BINARY_RESPONSE_SUCCESS &&
-      rval != PROTOCOL_BINARY_RESPONSE_EINTERNAL &&
-      rval != PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED)
-  {
-    protocol_binary_response_no_extras response= {
-      .message= {
-        .header.response= {
-          .magic= PROTOCOL_BINARY_RES,
-          .opcode= cc,
-          .status= htons(rval),
-          .opaque= header->request.opaque,
-        },
-      }
-    };
-    rval= raw_response_handler(client, header, (void*)&response);
-  }
-
-  if (client->root->callback->post_execute != NULL)
-  {
-    client->root->callback->post_execute(client, header);
-  }
-
-  return rval;
-}
-
-/*
-** **********************************************************************
-** "PROTOECTED" INTERFACE
-** **********************************************************************
-*/
-memcached_protocol_event_t memcached_binary_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr)
-{
-  /* try to parse all of the received packets */
-  protocol_binary_request_header *header;
-  header= (void*)client->root->input_buffer;
-  if (header->request.magic != (uint8_t)PROTOCOL_BINARY_REQ)
-  {
-    client->error= EINVAL;
-    return MEMCACHED_PROTOCOL_ERROR_EVENT;
-  }
-  ssize_t len= *length;
-
-  while (len >= (ssize_t)sizeof(*header) &&
-         (len >= (ssize_t)(sizeof(*header) + ntohl(header->request.bodylen))))
-  {
-    /* I have the complete package */
-    client->current_command= header;
-    protocol_binary_response_status rv= execute_command(client, header);
-
-    if (rv == PROTOCOL_BINARY_RESPONSE_EINTERNAL)
-    {
-      *length= len;
-      *endptr= (void*)header;
-      return MEMCACHED_PROTOCOL_ERROR_EVENT;
-    }
-    else if (rv == PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED)
-    {
-      return MEMCACHED_PROTOCOL_PAUSE_EVENT;
-    }
-
-    ssize_t total= (ssize_t)(sizeof(*header) + ntohl(header->request.bodylen));
-    len -= total;
-    if (len > 0)
-    {
-      intptr_t ptr= (intptr_t)header;
-      ptr += total;
-      if ((ptr % 8) == 0)
-      {
-        header= (void*)ptr;
-      }
-      else
-      {
-        /* Fix alignment */
-        memmove(client->root->input_buffer, (void*)ptr, (size_t)len);
-        header= (void*)client->root->input_buffer;
-      }
-    }
-    *length= len;
-    *endptr= (void*)header;
-  }
-
-  return MEMCACHED_PROTOCOL_READ_EVENT;
-}
-
-/*
-** **********************************************************************
-** PUBLIC INTERFACE
-** **********************************************************************
-*/
-memcached_binary_protocol_callback_st *memcached_binary_protocol_get_callbacks(memcached_protocol_st *instance)
-{
-  return instance->callback;
-}
-
-void memcached_binary_protocol_set_callbacks(memcached_protocol_st *instance, memcached_binary_protocol_callback_st *callback)
-{
-  instance->callback= callback;
-}
-
-memcached_binary_protocol_raw_response_handler memcached_binary_protocol_get_raw_response_handler(const void *cookie)
-{
-  (void)cookie;
-  return raw_response_handler;
-}
-
-void memcached_binary_protocol_set_pedantic(memcached_protocol_st *instance, bool enable)
-{
-  instance->pedantic= enable;
-}
-
-bool memcached_binary_protocol_get_pedantic(memcached_protocol_st *instance)
-{
-  return instance->pedantic;
-}
-
diff --git a/libmemcachedprotocol/binary_handler.h b/libmemcachedprotocol/binary_handler.h
deleted file mode 100644 (file)
index d5a74e7..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-LIBMEMCACHED_LOCAL
-bool memcached_binary_protocol_pedantic_check_request(const protocol_binary_request_header *request);
-
-LIBMEMCACHED_LOCAL
-bool memcached_binary_protocol_pedantic_check_response(const protocol_binary_request_header *request,
-                                                       const protocol_binary_response_header *response);
-
-LIBMEMCACHED_LOCAL
-memcached_protocol_event_t memcached_binary_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr);
diff --git a/libmemcachedprotocol/cache.c b/libmemcachedprotocol/cache.c
deleted file mode 100644 (file)
index 67c72ea..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-#include "mem_config.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <inttypes.h>
-
-#ifndef NDEBUG
-#include <signal.h>
-#endif
-
-#include <libmemcachedprotocol/common.h>
-
-#ifndef NDEBUG
-const uint64_t redzone_pattern = 0xdeadbeefcafebabe;
-int cache_error = 0;
-#endif
-
-const size_t initial_pool_size = 64;
-
-cache_t* cache_create(const char *name, size_t bufsize, size_t align,
-                      cache_constructor_t* constructor,
-                      cache_destructor_t* destructor) {
-    cache_t* ret = calloc(1, sizeof(cache_t));
-    size_t name_length= strlen(name);
-    char* nm= calloc(1, (sizeof(char) * name_length) +1);
-    memcpy(nm, name, name_length);
-    void** ptr = calloc(initial_pool_size, bufsize);
-    if (ret == NULL || nm == NULL || ptr == NULL ||
-        pthread_mutex_init(&ret->mutex, NULL) == -1) {
-        free(ret);
-        free(nm);
-        free(ptr);
-        return NULL;
-    }
-
-    ret->name = nm;
-    ret->ptr = ptr;
-    ret->freetotal = initial_pool_size;
-    ret->constructor = constructor;
-    ret->destructor = destructor;
-
-#ifndef NDEBUG
-    ret->bufsize = bufsize + 2 * sizeof(redzone_pattern);
-#else
-    ret->bufsize = bufsize;
-#endif
-
-    (void)align;
-
-    return ret;
-}
-
-static inline void* get_object(void *ptr) {
-#ifndef NDEBUG
-    uint64_t *pre = ptr;
-    return pre + 1;
-#else
-    return ptr;
-#endif
-}
-
-void cache_destroy(cache_t *cache) {
-    while (cache->freecurr > 0) {
-        void *ptr = cache->ptr[--cache->freecurr];
-        if (cache->destructor) {
-            cache->destructor(get_object(ptr), NULL);
-        }
-        free(ptr);
-    }
-    free(cache->name);
-    free(cache->ptr);
-    pthread_mutex_destroy(&cache->mutex);
-}
-
-void* cache_alloc(cache_t *cache) {
-    void *ret;
-    void *object;
-    pthread_mutex_lock(&cache->mutex);
-    if (cache->freecurr > 0) {
-        ret = cache->ptr[--cache->freecurr];
-        object = get_object(ret);
-    } else {
-        object = ret = malloc(cache->bufsize);
-        if (ret != NULL) {
-            object = get_object(ret);
-
-            if (cache->constructor != NULL &&
-                cache->constructor(object, NULL, 0) != 0) {
-                free(ret);
-                object = NULL;
-            }
-        }
-    }
-    pthread_mutex_unlock(&cache->mutex);
-
-#ifndef NDEBUG
-    if (object != NULL) {
-        /* add a simple form of buffer-check */
-        uint64_t *pre = ret;
-        *pre = redzone_pattern;
-        ret = pre+1;
-        memcpy(((char*)ret) + cache->bufsize - (2 * sizeof(redzone_pattern)),
-               &redzone_pattern, sizeof(redzone_pattern));
-    }
-#endif
-
-    return object;
-}
-
-void cache_free(cache_t *cache, void *ptr) {
-    pthread_mutex_lock(&cache->mutex);
-
-#ifndef NDEBUG
-    /* validate redzone... */
-    if (memcmp(((char*)ptr) + cache->bufsize - (2 * sizeof(redzone_pattern)),
-               &redzone_pattern, sizeof(redzone_pattern)) != 0) {
-        raise(SIGABRT);
-        cache_error = 1;
-        pthread_mutex_unlock(&cache->mutex);
-        return;
-    }
-    uint64_t *pre = ptr;
-    --pre;
-    if (*pre != redzone_pattern) {
-        raise(SIGABRT);
-        cache_error = -1;
-        pthread_mutex_unlock(&cache->mutex);
-        return;
-    }
-    ptr = pre;
-#endif
-    if (cache->freecurr < cache->freetotal) {
-        cache->ptr[cache->freecurr++] = ptr;
-    } else {
-        /* try to enlarge free connections array */
-        size_t newtotal = cache->freetotal * 2;
-        void **new_free = realloc(cache->ptr, sizeof(char *) * newtotal);
-        if (new_free) {
-            cache->freetotal = newtotal;
-            cache->ptr = new_free;
-            cache->ptr[cache->freecurr++] = ptr;
-        } else {
-            if (cache->destructor) {
-                cache->destructor(ptr, NULL);
-            }
-            free(ptr);
-
-        }
-    }
-    pthread_mutex_unlock(&cache->mutex);
-}
-
diff --git a/libmemcachedprotocol/cache.h b/libmemcachedprotocol/cache.h
deleted file mode 100644 (file)
index 6f84fea..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-#pragma once
-
-#include <pthread.h>
-
-#ifdef HAVE_UMEM_H
-# include <umem.h>
-# define cache_t umem_cache_t
-# define cache_alloc(a) umem_cache_alloc(a, UMEM_DEFAULT)
-# define cache_free(a, b) umem_cache_free(a, b)
-# define cache_create(a,b,c,d,e) umem_cache_create((char*)a, b, c, d, e, NULL, NULL, NULL, 0)
-# define cache_destroy(a) umem_cache_destroy(a);
-#else
-# ifndef NDEBUG
-/* may be used for debug purposes */
-extern int cache_error;
-# endif
-
-/**
- * Constructor used to initialize allocated objects
- *
- * @param obj pointer to the object to initialized.
- * @param notused1 This parameter is currently not used.
- * @param notused2 This parameter is currently not used.
- * @return you should return 0, but currently this is not checked
- */
-typedef int cache_constructor_t(void* obj, void* notused1, int notused2);
-/**
- * Destructor used to clean up allocated objects before they are
- * returned to the operating system.
- *
- * @param obj pointer to the object to initialized.
- * @param notused1 This parameter is currently not used.
- * @param notused2 This parameter is currently not used.
- * @return you should return 0, but currently this is not checked
- */
-typedef void cache_destructor_t(void* obj, void* notused);
-
-/**
- * Definition of the structure to keep track of the internal details of
- * the cache allocator. Touching any of these variables results in
- * undefined behavior.
- */
-typedef struct {
-    /** Mutex to protect access to the structure */
-    pthread_mutex_t mutex;
-    /** Name of the cache objects in this cache (provided by the caller) */
-    char *name;
-    /** List of pointers to available buffers in this cache */
-    void **ptr;
-    /** The size of each element in this cache */
-    size_t bufsize;
-    /** The capacity of the list of elements */
-    size_t freetotal;
-    /** The current number of free elements */
-    size_t freecurr;
-    /** The constructor to be called each time we allocate more memory */
-    cache_constructor_t* constructor;
-    /** The destructor to be called each time before we release memory */
-    cache_destructor_t* destructor;
-} cache_t;
-
-/**
- * Create an object cache.
- *
- * The object cache will let you allocate objects of the same size. It is fully
- * MT safe, so you may allocate objects from multiple threads without having to
- * do any syncrhonization in the application code.
- *
- * @param name the name of the object cache. This name may be used for debug purposes
- *             and may help you track down what kind of object you have problems with
- *             (buffer overruns, leakage etc)
- * @param bufsize the size of each object in the cache
- * @param align the alignment requirements of the objects in the cache.
- * @param constructor the function to be called to initialize memory when we need
- *                    to allocate more memory from the os.
- * @param destructor the function to be called before we release the memory back
- *                   to the os.
- * @return a handle to an object cache if successful, NULL otherwise.
- */
-cache_t* cache_create(const char* name, size_t bufsize, size_t align,
-                      cache_constructor_t* constructor,
-                      cache_destructor_t* destructor);
-/**
- * Destroy an object cache.
- *
- * Destroy and invalidate an object cache. You should return all buffers allocated
- * with cache_alloc by using cache_free before calling this function. Not doing
- * so results in undefined behavior (the buffers may or may not be invalidated)
- *
- * @param handle the handle to the object cache to destroy.
- */
-void cache_destroy(cache_t* handle);
-/**
- * Allocate an object from the cache.
- *
- * @param handle the handle to the object cache to allocate from
- * @return a pointer to an initialized object from the cache, or NULL if
- *         the allocation cannot be satisfied.
- */
-void* cache_alloc(cache_t* handle);
-/**
- * Return an object back to the cache.
- *
- * The caller should return the object in an initialized state so that
- * the object may be returned in an expected state from cache_alloc.
- *
- * @param handle handle to the object cache to return the object to
- * @param ptr pointer to the object to return.
- */
-void cache_free(cache_t* handle, void* ptr);
-#endif //  HAVE_UMEM_H
diff --git a/libmemcachedprotocol/common.h b/libmemcachedprotocol/common.h
deleted file mode 100644 (file)
index a4ddc2c..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include "mem_config.h"
-#include <assert.h>
-
-#include <libmemcachedprotocol-0.0/handler.h>
-#include <libmemcachedprotocol/cache.h>
-#include <libmemcached/byteorder.h>
-#include <libmemcached/socket.hpp>
-
-/*
- * I don't really need the following two functions as function pointers
- * in the instance handle, but I don't want to put them in the global
- * namespace for those linking statically (personally I don't like that,
- * but some people still do). If it ever shows up as a performance thing
- * I'll look into optimizing this ;-)
- */
-typedef bool (*drain_func)(memcached_protocol_client_st *client);
-typedef protocol_binary_response_status (*spool_func)(memcached_protocol_client_st *client,
-                                                      const void *data,
-                                                      size_t length);
-
-/**
- * Definition of the per instance structure.
- */
-struct memcached_protocol_st {
-  memcached_binary_protocol_callback_st *callback;
-  memcached_protocol_recv_func recv;
-  memcached_protocol_send_func send;
-
-  /*
-   * I really don't need these as funciton pointers, but I don't want
-   * to clutter the namespace if someone links statically.
-   */
-  drain_func drain;
-  spool_func spool;
-
-  /*
-   * To avoid keeping a buffer in each client all the time I have a
-   * bigger buffer in the instance that I read to initially, and then
-   * I try to parse and execute as much from the buffer. If I wasn't able
-   * to process all data I'll keep that in a per-connection buffer until
-   * the next time I can read from the socket.
-   */
-  uint8_t *input_buffer;
-  size_t input_buffer_size;
-
-  bool pedantic;
-  /* @todo use multiple sized buffers */
-  cache_t *buffer_cache;
-};
-
-struct chunk_st {
-  /* Pointer to the data */
-  char *data;
-  /* The offset to the first byte into the buffer that is used */
-  size_t offset;
-  /* The offset into the buffer for the first free byte */
-  size_t nbytes;
-  /* The number of bytes in the buffer */
-  size_t size;
-  /* Pointer to the next buffer in the chain */
-  struct chunk_st *next;
-};
-
-#define CHUNK_BUFFERSIZE 2048
-
-typedef memcached_protocol_event_t (*process_data)(struct memcached_protocol_client_st *client, ssize_t *length, void **endptr);
-
-enum ascii_cmd {
-  GET_CMD,
-  GETS_CMD,
-  SET_CMD,
-  ADD_CMD,
-  REPLACE_CMD,
-  CAS_CMD,
-  APPEND_CMD,
-  PREPEND_CMD,
-  DELETE_CMD,
-  INCR_CMD,
-  DECR_CMD,
-  STATS_CMD,
-  FLUSH_ALL_CMD,
-  VERSION_CMD,
-  QUIT_CMD,
-  VERBOSITY_CMD,
-  UNKNOWN_CMD
-};
-
-struct memcached_protocol_client_st {
-  bool is_verbose;
-  memcached_protocol_st *root;
-  memcached_socket_t sock;
-  int error;
-
-  /* Linked list of data to send */
-  struct chunk_st *output;
-  struct chunk_st *output_tail;
-
-  /*
-   * While we process input data, this is where we spool incomplete commands
-   * if we need to receive more data....
-   * @todo use the buffercace
-   */
-  uint8_t *input_buffer;
-  size_t input_buffer_size;
-  size_t input_buffer_offset;
-
-  /* The callback to the protocol handler to use (ascii or binary) */
-  process_data work;
-
-  /*
-   * Should the spool data discard the data to send or not? (aka noreply in
-   * the ascii protocol..
-   */
-  bool mute;
-
-  /* Members used by the binary protocol */
-  protocol_binary_request_header *current_command;
-
-  /* Members used by the ascii protocol */
-  enum ascii_cmd ascii_command;
-};
-
-#include "ascii_handler.h"
-#include "binary_handler.h"
diff --git a/libmemcachedprotocol/handler.c b/libmemcachedprotocol/handler.c
deleted file mode 100644 (file)
index afd7086..0000000
+++ /dev/null
@@ -1,441 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-#include <libmemcachedprotocol/common.h>
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <string.h>
-#include <strings.h>
-#include <ctype.h>
-#include <stdio.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-/*
-** **********************************************************************
-** INTERNAL INTERFACE
-** **********************************************************************
-*/
-
-/**
- * The default function to receive data from the client. This function
- * just wraps the recv function to receive from a socket.
- * See man -s3socket recv for more information.
- *
- * @param cookie cookie indentifying a client, not used
- * @param sock socket to read from
- * @param buf the destination buffer
- * @param nbytes the number of bytes to read
- * @return the number of bytes transferred of -1 upon error
- */
-static ssize_t default_recv(const void *cookie,
-                            memcached_socket_t sock,
-                            void *buf,
-                            size_t nbytes)
-{
-  (void)cookie;
-  return recv(sock, buf, nbytes, 0);
-}
-
-/**
- * The default function to send data to the server. This function
- * just wraps the send function to send through a socket.
- * See man -s3socket send for more information.
- *
- * @param cookie cookie indentifying a client, not used
- * @param sock socket to send to
- * @param buf the source buffer
- * @param nbytes the number of bytes to send
- * @return the number of bytes transferred of -1 upon error
- */
-static ssize_t default_send(const void *cookie,
-                            memcached_socket_t fd,
-                            const void *buf,
-                            size_t nbytes)
-{
-  (void)cookie;
-  return send(fd, buf, nbytes, MSG_NOSIGNAL);
-}
-
-/**
- * Try to drain the output buffers without blocking
- *
- * @param client the client to drain
- * @return false if an error occured (connection should be shut down)
- *         true otherwise (please note that there may be more data to
- *              left in the buffer to send)
- */
-static bool drain_output(struct memcached_protocol_client_st *client)
-{
-  if (client->is_verbose)
-  {
-    fprintf(stderr, "%s:%d %s mute:%d output:%s length:%d\n", __FILE__, __LINE__, __func__, (int)client->mute,
-            client->output ? "yes" : "no",
-            client->output ? (int)(client->output->nbytes - client->output->offset) : 0);
-  }
-
-  /* Do we have pending data to send? */
-  while (client->output != NULL)
-  {
-    ssize_t len= client->root->send(client,
-                            client->sock,
-                            client->output->data + client->output->offset,
-                            client->output->nbytes - client->output->offset);
-
-    if (len == -1)
-    {
-      if (get_socket_errno() == EWOULDBLOCK)
-      {
-        return true;
-      }
-      else if (get_socket_errno() != EINTR)
-      {
-        client->error= get_socket_errno();
-        return false;
-      }
-    }
-    else
-    {
-      client->output->offset += (size_t)len;
-      if (client->output->offset == client->output->nbytes)
-      {
-        /* This was the complete buffer */
-        struct chunk_st *old= client->output;
-        client->output= client->output->next;
-        if (client->output == NULL)
-        {
-          client->output_tail= NULL;
-        }
-        cache_free(client->root->buffer_cache, old);
-      }
-    }
-  }
-
-  return true;
-}
-
-/**
- * Allocate an output buffer and chain it into the output list
- *
- * @param client the client that needs the buffer
- * @return pointer to the new chunk if the allocation succeeds, NULL otherwise
- */
-static struct chunk_st *allocate_output_chunk(struct memcached_protocol_client_st *client)
-{
-  struct chunk_st *ret= cache_alloc(client->root->buffer_cache);
-
-  if (ret == NULL)
-  {
-    return NULL;
-  }
-
-  ret->offset= ret->nbytes= 0;
-  ret->next= NULL;
-  ret->size= CHUNK_BUFFERSIZE;
-  ret->data= (void*)(ret + 1);
-  if (client->output == NULL)
-  {
-    client->output= client->output_tail= ret;
-  }
-  else
-  {
-    client->output_tail->next= ret;
-    client->output_tail= ret;
-  }
-
-  return ret;
-}
-
-/**
- * Spool data into the send-buffer for a client.
- *
- * @param client the client to spool the data for
- * @param data the data to spool
- * @param length the number of bytes of data to spool
- * @return PROTOCOL_BINARY_RESPONSE_SUCCESS if success,
- *         PROTOCOL_BINARY_RESPONSE_ENOMEM if we failed to allocate memory
- */
-static protocol_binary_response_status spool_output(struct memcached_protocol_client_st *client,
-                                                    const void *data,
-                                                    size_t length)
-{
-  if (client->is_verbose)
-  {
-    fprintf(stderr, "%s:%d %s mute:%d length:%d\n", __FILE__, __LINE__, __func__, (int)client->mute, (int)length);
-  }
-
-  if (client->mute)
-  {
-    return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-  }
-
-  size_t offset= 0;
-
-  struct chunk_st *chunk= client->output;
-  while (offset < length)
-  {
-    if (chunk == NULL || (chunk->size - chunk->nbytes) == 0)
-    {
-      if ((chunk= allocate_output_chunk(client)) == NULL)
-      {
-        return PROTOCOL_BINARY_RESPONSE_ENOMEM;
-      }
-    }
-
-    size_t bulk= length - offset;
-    if (bulk > chunk->size - chunk->nbytes)
-    {
-      bulk= chunk->size - chunk->nbytes;
-    }
-
-    memcpy(chunk->data + chunk->nbytes, data, bulk);
-    chunk->nbytes += bulk;
-    offset += bulk;
-  }
-
-  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
-}
-
-/**
- * Try to determine the protocol used on this connection.
- * If the first byte contains the magic byte PROTOCOL_BINARY_REQ we should
- * be using the binary protocol on the connection. I implemented the support
- * for the ASCII protocol by wrapping into the simple interface (aka v1),
- * so the implementors needs to provide an implementation of that interface
- *
- */
-static memcached_protocol_event_t determine_protocol(struct memcached_protocol_client_st *client, ssize_t *length, void **endptr)
-{
-  if (*client->root->input_buffer == (uint8_t)PROTOCOL_BINARY_REQ)
-  {
-    if (client->is_verbose)
-    {
-      fprintf(stderr, "%s:%d PROTOCOL: memcached_binary_protocol_process_data\n", __FILE__, __LINE__);
-    }
-    client->work= memcached_binary_protocol_process_data;
-  }
-  else if (client->root->callback->interface_version == 1)
-  {
-    if (client->is_verbose)
-    {
-      fprintf(stderr, "%s:%d PROTOCOL: memcached_ascii_protocol_process_data\n", __FILE__, __LINE__);
-    }
-
-    /*
-     * The ASCII protocol can only be used if the implementors provide
-     * an implementation for the version 1 of the interface..
-     *
-     * @todo I should allow the implementors to provide an implementation
-     *       for version 0 and 1 at the same time and set the preferred
-     *       interface to use...
-     */
-    client->work= memcached_ascii_protocol_process_data;
-  }
-  else
-  {
-    if (client->is_verbose)
-    {
-      fprintf(stderr, "%s:%d PROTOCOL: Unsupported protocol\n", __FILE__, __LINE__);
-    }
-
-    /* Let's just output a warning the way it is supposed to look like
-     * in the ASCII protocol...
-     */
-    const char *err= "CLIENT_ERROR: Unsupported protocol\r\n";
-    client->root->spool(client, err, strlen(err));
-    client->root->drain(client);
-
-    return MEMCACHED_PROTOCOL_ERROR_EVENT; /* Unsupported protocol */
-  }
-
-  return client->work(client, length, endptr);
-}
-
-/*
-** **********************************************************************
-** * PUBLIC INTERFACE
-** * See protocol_handler.h for function description
-** **********************************************************************
-*/
-struct memcached_protocol_st *memcached_protocol_create_instance(void)
-{
-  struct memcached_protocol_st *ret= calloc(1, sizeof(*ret));
-  if (ret != NULL)
-  {
-    ret->recv= default_recv;
-    ret->send= default_send;
-    ret->drain= drain_output;
-    ret->spool= spool_output;
-    ret->input_buffer_size= 1 * 1024 * 1024;
-    ret->input_buffer= malloc(ret->input_buffer_size);
-    if (ret->input_buffer == NULL)
-    {
-      free(ret);
-      ret= NULL;
-
-      return NULL;
-    }
-
-    ret->buffer_cache= cache_create("protocol_handler",
-                                     CHUNK_BUFFERSIZE + sizeof(struct chunk_st),
-                                     0, NULL, NULL);
-    if (ret->buffer_cache == NULL)
-    {
-      free(ret->input_buffer);
-      free(ret);
-      ret= NULL;
-    }
-  }
-
-  return ret;
-}
-
-void memcached_protocol_destroy_instance(struct memcached_protocol_st *instance)
-{
-  cache_destroy(instance->buffer_cache);
-  free(instance->input_buffer);
-  free(instance);
-}
-
-struct memcached_protocol_client_st *memcached_protocol_create_client(struct memcached_protocol_st *instance, memcached_socket_t sock)
-{
-  struct memcached_protocol_client_st *ret= calloc(1, sizeof(memcached_protocol_client_st));
-  if (ret != NULL)
-  {
-    ret->root= instance;
-    ret->sock= sock;
-    ret->work= determine_protocol;
-  }
-
-  return ret;
-}
-
-void memcached_protocol_client_destroy(struct memcached_protocol_client_st *client)
-{
-  free(client);
-}
-
-void memcached_protocol_client_set_verbose(struct memcached_protocol_client_st *client, bool arg)
-{
-  if (client)
-  {
-    client->is_verbose= arg;
-  }
-}
-
-memcached_protocol_event_t memcached_protocol_client_work(struct memcached_protocol_client_st *client)
-{
-  /* Try to send data and read from the socket */
-  bool more_data= true;
-  do
-  {
-    ssize_t len= client->root->recv(client,
-                                    client->sock,
-                                    client->root->input_buffer + client->input_buffer_offset,
-                                    client->root->input_buffer_size - client->input_buffer_offset);
-
-    if (len > 0)
-    {
-      /* Do we have the complete packet? */
-      if (client->input_buffer_offset > 0)
-      {
-        memcpy(client->root->input_buffer, client->input_buffer,
-               client->input_buffer_offset);
-        len += (ssize_t)client->input_buffer_offset;
-
-        /* @todo use buffer-cache! */
-        free(client->input_buffer);
-        client->input_buffer_offset= 0;
-      }
-
-      void *endptr;
-      memcached_protocol_event_t events= client->work(client, &len, &endptr);
-      if (events == MEMCACHED_PROTOCOL_ERROR_EVENT)
-      {
-        return MEMCACHED_PROTOCOL_ERROR_EVENT;
-      }
-
-      if (len > 0)
-      {
-        /* save the data for later on */
-        /* @todo use buffer-cache */
-        client->input_buffer= malloc((size_t)len);
-        if (client->input_buffer == NULL)
-        {
-          client->error= ENOMEM;
-          return MEMCACHED_PROTOCOL_ERROR_EVENT;
-        }
-        memcpy(client->input_buffer, endptr, (size_t)len);
-        client->input_buffer_offset= (size_t)len;
-        more_data= false;
-      }
-    }
-    else if (len == 0)
-    {
-      /* Connection closed */
-      drain_output(client);
-      return MEMCACHED_PROTOCOL_ERROR_EVENT;
-    }
-    else
-    {
-      if (get_socket_errno() != EWOULDBLOCK)
-      {
-        client->error= get_socket_errno();
-        /* mark this client as terminated! */
-        return MEMCACHED_PROTOCOL_ERROR_EVENT;
-      }
-      more_data= false;
-    }
-  } while (more_data);
-
-  if (!drain_output(client))
-  {
-    return MEMCACHED_PROTOCOL_ERROR_EVENT;
-  }
-
-  memcached_protocol_event_t ret= MEMCACHED_PROTOCOL_READ_EVENT;
-  if (client->output)
-  {
-    ret|= MEMCACHED_PROTOCOL_READ_EVENT;
-  }
-
-  return ret;
-}
diff --git a/libmemcachedprotocol/pedantic.c b/libmemcachedprotocol/pedantic.c
deleted file mode 100644 (file)
index 54a2add..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-#include <libmemcachedprotocol/common.h>
-
-#include <sys/types.h>
-
-#define ensure(a) if (!(a)) { return false; }
-
-bool memcached_binary_protocol_pedantic_check_request(const protocol_binary_request_header *request)
-{
-  ensure(request->request.magic == PROTOCOL_BINARY_REQ);
-  ensure(request->request.datatype == PROTOCOL_BINARY_RAW_BYTES);
-
-  ensure(request->bytes[6] == 0);
-  ensure(request->bytes[7] == 0);
-
-  uint8_t opcode= request->request.opcode;
-  uint16_t keylen= ntohs(request->request.keylen);
-  uint8_t extlen= request->request.extlen;
-  uint32_t bodylen= ntohl(request->request.bodylen);
-
-  ensure(bodylen >= (keylen + extlen));
-
-  switch (opcode) {
-  case PROTOCOL_BINARY_CMD_GET:
-  case PROTOCOL_BINARY_CMD_GETK:
-  case PROTOCOL_BINARY_CMD_GETKQ:
-  case PROTOCOL_BINARY_CMD_GETQ:
-    ensure(extlen == 0);
-    ensure(keylen > 0);
-    ensure(keylen == bodylen);
-    ensure(request->request.cas == 0);
-    break;
-
-  case PROTOCOL_BINARY_CMD_ADD:
-  case PROTOCOL_BINARY_CMD_ADDQ:
-    /* it makes no sense to run add with a cas value */
-    ensure(request->request.cas == 0);
-    /* FALLTHROUGH */
-  case PROTOCOL_BINARY_CMD_SET:
-  case PROTOCOL_BINARY_CMD_SETQ:
-  case PROTOCOL_BINARY_CMD_REPLACE:
-  case PROTOCOL_BINARY_CMD_REPLACEQ:
-    ensure(keylen > 0);
-    ensure(extlen == 8);
-    break;
-
-  case PROTOCOL_BINARY_CMD_DELETE:
-  case PROTOCOL_BINARY_CMD_DELETEQ:
-    ensure(extlen == 0);
-    ensure(keylen > 0);
-    ensure(keylen == bodylen);
-    break;
-
-  case PROTOCOL_BINARY_CMD_INCREMENT:
-  case PROTOCOL_BINARY_CMD_INCREMENTQ:
-  case PROTOCOL_BINARY_CMD_DECREMENT:
-  case PROTOCOL_BINARY_CMD_DECREMENTQ:
-    ensure(extlen == 20);
-    ensure(keylen > 0);
-    ensure(keylen + extlen == bodylen);
-    break;
-
-  case PROTOCOL_BINARY_CMD_QUIT:
-  case PROTOCOL_BINARY_CMD_QUITQ:
-  case PROTOCOL_BINARY_CMD_NOOP:
-  case PROTOCOL_BINARY_CMD_VERSION:
-    ensure(extlen == 0);
-    ensure(keylen == 0);
-    ensure(bodylen == 0);
-    break;
-
-  case PROTOCOL_BINARY_CMD_FLUSH:
-  case PROTOCOL_BINARY_CMD_FLUSHQ:
-    ensure(extlen == 0 || extlen == 4);
-    ensure(keylen == 0);
-    ensure(bodylen == extlen);
-    break;
-
-  case PROTOCOL_BINARY_CMD_STAT:
-    ensure(extlen == 0);
-    /* May have key, but not value */
-    ensure(keylen == bodylen);
-    break;
-
-  case PROTOCOL_BINARY_CMD_APPEND:
-  case PROTOCOL_BINARY_CMD_APPENDQ:
-  case PROTOCOL_BINARY_CMD_PREPEND:
-  case PROTOCOL_BINARY_CMD_PREPENDQ:
-    ensure(extlen == 0);
-    ensure(keylen > 0);
-    break;
-  default:
-    /* Unknown command */
-    ;
-  }
-
-  return true;
-}
-
-bool memcached_binary_protocol_pedantic_check_response(const protocol_binary_request_header *request,
-                                                       const protocol_binary_response_header *response)
-{
-  ensure(response->response.magic == PROTOCOL_BINARY_RES);
-  ensure(response->response.datatype == PROTOCOL_BINARY_RAW_BYTES);
-  ensure(response->response.opaque == request->request.opaque);
-
-  uint16_t status= ntohs(response->response.status);
-  uint8_t opcode= response->response.opcode;
-
-  if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS)
-  {
-    switch (opcode) {
-    case PROTOCOL_BINARY_CMD_ADDQ:
-    case PROTOCOL_BINARY_CMD_APPENDQ:
-    case PROTOCOL_BINARY_CMD_DECREMENTQ:
-    case PROTOCOL_BINARY_CMD_DELETEQ:
-    case PROTOCOL_BINARY_CMD_FLUSHQ:
-    case PROTOCOL_BINARY_CMD_INCREMENTQ:
-    case PROTOCOL_BINARY_CMD_PREPENDQ:
-    case PROTOCOL_BINARY_CMD_QUITQ:
-    case PROTOCOL_BINARY_CMD_REPLACEQ:
-    case PROTOCOL_BINARY_CMD_SETQ:
-      /* Quiet command shouldn't return on success */
-      return false;
-    default:
-      break;
-    }
-
-    switch (opcode) {
-    case PROTOCOL_BINARY_CMD_ADD:
-    case PROTOCOL_BINARY_CMD_REPLACE:
-    case PROTOCOL_BINARY_CMD_SET:
-    case PROTOCOL_BINARY_CMD_APPEND:
-    case PROTOCOL_BINARY_CMD_PREPEND:
-      ensure(response->response.keylen == 0);
-      ensure(response->response.extlen == 0);
-      ensure(response->response.bodylen == 0);
-      ensure(response->response.cas != 0);
-      break;
-    case PROTOCOL_BINARY_CMD_FLUSH:
-    case PROTOCOL_BINARY_CMD_NOOP:
-    case PROTOCOL_BINARY_CMD_QUIT:
-    case PROTOCOL_BINARY_CMD_DELETE:
-      ensure(response->response.keylen == 0);
-      ensure(response->response.extlen == 0);
-      ensure(response->response.bodylen == 0);
-      ensure(response->response.cas == 0);
-      break;
-
-    case PROTOCOL_BINARY_CMD_DECREMENT:
-    case PROTOCOL_BINARY_CMD_INCREMENT:
-      ensure(response->response.keylen == 0);
-      ensure(response->response.extlen == 0);
-      ensure(ntohl(response->response.bodylen) == 8);
-      ensure(response->response.cas != 0);
-      break;
-
-    case PROTOCOL_BINARY_CMD_STAT:
-      ensure(response->response.extlen == 0);
-      /* key and value exists in all packets except in the terminating */
-      ensure(response->response.cas == 0);
-      break;
-
-    case PROTOCOL_BINARY_CMD_VERSION:
-      ensure(response->response.keylen == 0);
-      ensure(response->response.extlen == 0);
-      ensure(response->response.bodylen != 0);
-      ensure(response->response.cas == 0);
-      break;
-
-    case PROTOCOL_BINARY_CMD_GET:
-    case PROTOCOL_BINARY_CMD_GETQ:
-      ensure(response->response.keylen == 0);
-      ensure(response->response.extlen == 4);
-      ensure(response->response.cas != 0);
-      break;
-
-    case PROTOCOL_BINARY_CMD_GETK:
-    case PROTOCOL_BINARY_CMD_GETKQ:
-      ensure(response->response.keylen != 0);
-      ensure(response->response.extlen == 4);
-      ensure(response->response.cas != 0);
-      break;
-
-    default:
-      /* Undefined command code */
-      break;
-    }
-  }
-  else
-  {
-    ensure(response->response.cas == 0);
-    ensure(response->response.extlen == 0);
-    if (opcode != PROTOCOL_BINARY_CMD_GETK)
-    {
-      ensure(response->response.keylen == 0);
-    }
-  }
-
-  return true;
-}
diff --git a/libmemcachedutil-1.0/CMakeLists.txt b/libmemcachedutil-1.0/CMakeLists.txt
deleted file mode 100644 (file)
index c613887..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-
-install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
-        FILES_MATCHING REGEX "\\.h(pp)?$"
-        )
diff --git a/libmemcachedutil-1.0/flush.h b/libmemcachedutil-1.0/flush.h
deleted file mode 100644 (file)
index dd7e779..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-bool libmemcached_util_flush(const char *hostname, in_port_t port, memcached_return_t *ret);
-
-#ifdef __cplusplus
-}
-#endif
-
diff --git a/libmemcachedutil-1.0/ostream.hpp b/libmemcachedutil-1.0/ostream.hpp
deleted file mode 100644 (file)
index cce7bfc..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-static inline std::ostream& operator<<(std::ostream& output, const enum memcached_return_t &arg)
-{
-  output << memcached_strerror(NULL, arg);
-  return output;
-}
-
-static inline std::ostream& operator<<(std::ostream& output, const memcached_st &arg)
-{
-  output << " query_id: " <<  memcached_query_id(&arg);
-  output << " error: " <<  memcached_last_error_message(&arg);
-  return output;
-}
diff --git a/libmemcachedutil-1.0/pid.h b/libmemcachedutil-1.0/pid.h
deleted file mode 100644 (file)
index 3ce0131..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifndef _WIN32
-# include <netdb.h>
-#endif
-
-#include <sys/types.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_return_t *ret);
-
-LIBMEMCACHED_API
-pid_t libmemcached_util_getpid2(const char *hostname, in_port_t port, const char *username, const char *password,  memcached_return_t *ret);
-
-#ifdef __cplusplus
-}
-#endif
-
diff --git a/libmemcachedutil-1.0/ping.h b/libmemcachedutil-1.0/ping.h
deleted file mode 100644 (file)
index faea8b2..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret);
-
-LIBMEMCACHED_API
-bool libmemcached_util_ping2(const char *hostname, in_port_t port, const char *username, const char *password,  memcached_return_t *ret);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcachedutil-1.0/pool.h b/libmemcachedutil-1.0/pool.h
deleted file mode 100644 (file)
index a11117c..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#include <libmemcached-1.0/memcached.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct memcached_pool_st;
-typedef struct memcached_pool_st memcached_pool_st;
-
-LIBMEMCACHED_API
-memcached_pool_st *memcached_pool_create(memcached_st* mmc, uint32_t initial, uint32_t max);
-
-LIBMEMCACHED_API
-memcached_pool_st *memcached_pool(const char *option_string, size_t option_string_length);
-
-LIBMEMCACHED_API
-memcached_st* memcached_pool_destroy(memcached_pool_st* pool);
-
-LIBMEMCACHED_API
-memcached_st* memcached_pool_pop(memcached_pool_st* pool,
-                                 bool block,
-                                 memcached_return_t* rc);
-LIBMEMCACHED_API
-  memcached_return_t memcached_pool_push(memcached_pool_st* pool,
-                                         memcached_st* mmc);
-LIBMEMCACHED_API
-  memcached_return_t memcached_pool_release(memcached_pool_st* pool, memcached_st* mmc);
-
-LIBMEMCACHED_API
-memcached_st* memcached_pool_fetch(memcached_pool_st*, struct timespec* relative_time, memcached_return_t* rc);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_pool_behavior_set(memcached_pool_st *ptr,
-                                               memcached_behavior_t flag,
-                                               uint64_t data);
-LIBMEMCACHED_API
-memcached_return_t memcached_pool_behavior_get(memcached_pool_st *ptr,
-                                               memcached_behavior_t flag,
-                                               uint64_t *value);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/libmemcachedutil-1.0/util.h b/libmemcachedutil-1.0/util.h
deleted file mode 100644 (file)
index d362098..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <libmemcached-1.0/memcached.h>
-
-#include <libmemcachedutil-1.0/pid.h>
-#include <libmemcachedutil-1.0/flush.h>
-#include <libmemcachedutil-1.0/ping.h>
-#include <libmemcachedutil-1.0/pool.h>
-#include <libmemcachedutil-1.0/version.h>
diff --git a/libmemcachedutil-1.0/version.h b/libmemcachedutil-1.0/version.h
deleted file mode 100644 (file)
index 372283a..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-  bool libmemcached_util_version_check(memcached_st *memc, 
-                                       uint8_t major_version,
-                                       uint8_t minor_version,
-                                       uint8_t micro_version);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/libmemcachedutil/CMakeLists.txt b/libmemcachedutil/CMakeLists.txt
deleted file mode 100644 (file)
index 6ef3a75..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-
-add_library(libmemcachedutil SHARED
-        ../libmemcached/backtrace.cc
-        flush.cc
-        pid.cc
-        ping.cc
-        pool.cc
-        version.cc
-        )
-add_library(memcachedutil ALIAS libmemcachedutil)
-set_target_properties(libmemcachedutil PROPERTIES LIBRARY_OUTPUT_NAME memcachedutil)
-target_include_directories(libmemcachedutil PRIVATE ..)
-target_compile_definitions(libmemcachedutil PRIVATE -DBUILDING_LIBMEMCACHED)
-target_link_libraries(libmemcachedutil libmemcached Threads::Threads)
-
-set_target_properties(libmemcachedutil PROPERTIES SOVERSION ${LIBMEMCACHEDUTIL_SO_VERSION})
-install(TARGETS libmemcachedutil EXPORT libmemcachedutil
-        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
-export(EXPORT libmemcachedutil)
-install(EXPORT libmemcachedutil DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake)
diff --git a/libmemcachedutil/common.h b/libmemcachedutil/common.h
deleted file mode 100644 (file)
index 5e39354..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached Utility library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Summary: connects to a host, and then flushes it (memcached_flush(3)).
- *
- */
-
-#pragma once
-
-#include "mem_config.h"
-
-#include <cstddef>
-#include <cstdlib>
-#include <cstdio>
-
-#include "libmemcachedutil-1.0/util.h"
-#include "libmemcached/assert.hpp"
-#include "libmemcached/backtrace.hpp"
diff --git a/libmemcachedutil/flush.cc b/libmemcachedutil/flush.cc
deleted file mode 100644 (file)
index 6a99603..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Summary: connects to a host, and then flushes it (memcached_flush(3)).
- *
- */
-
-#include <libmemcachedutil/common.h>
-
-
-bool libmemcached_util_flush(const char *hostname, in_port_t port, memcached_return_t *ret)
-{
-  memcached_st *memc_ptr= memcached_create(NULL);
-
-  memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
-  if (memcached_success(rc))
-  {
-    rc= memcached_flush(memc_ptr, 0);
-  }
-
-  memcached_free(memc_ptr);
-
-  if (ret)
-  {
-    *ret= rc;
-  }
-
-  return memcached_success(rc);
-}
diff --git a/libmemcachedutil/pid.cc b/libmemcachedutil/pid.cc
deleted file mode 100644 (file)
index 3465611..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Summary: connects to a host, and determines what its pid is
- *
- */
-
-#include <libmemcachedutil/common.h>
-
-
-// Never look at the stat object directly.
-
-
-pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_return_t *ret)
-{
-  pid_t pid= -1;
-
-  memcached_return_t unused;
-  if (ret == NULL)
-  {
-    ret= &unused;
-  }
-
-  memcached_st *memc_ptr= memcached_create(NULL);
-  if (memc_ptr == NULL)
-  {
-    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-    return -1;
-  }
-
-  memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
-  if (memcached_success(rc))
-  {
-    memcached_stat_st *stat= memcached_stat(memc_ptr, NULL, &rc);
-    if (memcached_success(rc) and stat and stat->pid != -1)
-    {
-      pid= stat->pid;
-    }
-    else if (memcached_success(rc))
-    {
-      rc= MEMCACHED_UNKNOWN_STAT_KEY; // Something went wrong if this happens
-    }
-    else if (rc == MEMCACHED_SOME_ERRORS) // Generic answer, we will now find the specific reason (if one exists)
-    {
-      const memcached_instance_st * instance= memcached_server_instance_by_position(memc_ptr, 0);
-
-      assert_msg(instance and memcached_server_error(instance), " ");
-      if (instance and memcached_server_error(instance))
-      {
-        rc= memcached_server_error_return(instance);
-      }
-    }
-
-    memcached_stat_free(memc_ptr, stat);
-  }
-  memcached_free(memc_ptr);
-
-  *ret= rc;
-
-  return pid;
-}
-
-pid_t libmemcached_util_getpid2(const char *hostname, in_port_t port, const char *username, const char *password,  memcached_return_t *ret)
-{
-  if (username == NULL)
-  {
-    return libmemcached_util_getpid(hostname, port, ret);
-  }
-
-  pid_t pid= -1;
-
-  memcached_return_t unused;
-  if (not ret)
-    ret= &unused;
-
-  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    *ret= MEMCACHED_NOT_SUPPORTED;
-    return pid;
-  }
-
-  memcached_st *memc_ptr= memcached_create(NULL);
-  if (not memc_ptr)
-  {
-    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-    return -1;
-  }
-
-  if (memcached_failed(*ret= memcached_set_sasl_auth_data(memc_ptr, username, password)))
-  {
-    memcached_free(memc_ptr);
-    return false;
-  }
-
-
-  memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
-  if (memcached_success(rc))
-  {
-    memcached_stat_st *stat= memcached_stat(memc_ptr, NULL, &rc);
-    if (memcached_success(rc) and stat and stat->pid != -1)
-    {
-      pid= stat->pid;
-    }
-    else if (memcached_success(rc))
-    {
-      rc= MEMCACHED_UNKNOWN_STAT_KEY; // Something went wrong if this happens
-    }
-    else if (rc == MEMCACHED_SOME_ERRORS) // Generic answer, we will now find the specific reason (if one exists)
-    {
-      const memcached_instance_st * instance=
-        memcached_server_instance_by_position(memc_ptr, 0);
-
-#if 0
-      assert_msg(instance and instance->error_messages, " ");
-#endif
-      if (instance and memcached_server_error(instance))
-      {
-        rc= memcached_server_error_return(instance);
-      }
-    }
-
-    memcached_stat_free(memc_ptr, stat);
-  }
-  memcached_free(memc_ptr);
-
-  *ret= rc;
-
-  return pid;
-}
diff --git a/libmemcachedutil/ping.cc b/libmemcachedutil/ping.cc
deleted file mode 100644 (file)
index a867c56..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Summary: connects to a host, and makes sure it is alive.
- *
- */
-
-#include <libmemcachedutil/common.h>
-
-bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret)
-{
-  memcached_return_t unused;
-  if (ret == NULL)
-  {
-    ret= &unused;
-  }
-
-  memcached_st *memc_ptr= memcached_create(NULL);
-  if (memc_ptr == NULL)
-  {
-    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-    return false;
-  }
-
-  if (memcached_success((*ret= memcached_behavior_set(memc_ptr, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, 400000))))
-  {
-    memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
-    if (memcached_success(rc))
-    {
-      rc= memcached_version(memc_ptr);
-    }
-
-    if (memcached_failed(rc) and rc == MEMCACHED_SOME_ERRORS)
-    {
-      const memcached_instance_st * instance=
-        memcached_server_instance_by_position(memc_ptr, 0);
-
-      assert_msg(instance and memcached_server_error(instance), " ");
-      if (instance and memcached_server_error(instance))
-      {
-        rc= memcached_server_error_return(instance);
-      }
-    }
-
-    *ret= rc;
-  }
-  memcached_free(memc_ptr);
-
-  return memcached_success(*ret);
-}
-
-bool libmemcached_util_ping2(const char *hostname, in_port_t port, const char *username, const char *password,  memcached_return_t *ret)
-{
-  if (username == NULL)
-  {
-    return libmemcached_util_ping(hostname, port, ret);
-  }
-
-  memcached_return_t unused;
-  if (not ret)
-    ret= &unused;
-
-  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
-  {
-    *ret= MEMCACHED_NOT_SUPPORTED;
-    return false;
-  }
-
-  memcached_st *memc_ptr= memcached_create(NULL);
-  if (not memc_ptr)
-  {
-    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-    return false;
-  }
-
-  if (memcached_failed(*ret= memcached_set_sasl_auth_data(memc_ptr, username, password)))
-  {
-    memcached_free(memc_ptr);
-    return false;
-  }
-
-  memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
-  if (memcached_success(rc))
-  {
-    rc= memcached_version(memc_ptr);
-  }
-
-  if (memcached_failed(rc) and rc == MEMCACHED_SOME_ERRORS)
-  {
-    const memcached_instance_st * instance=
-      memcached_server_instance_by_position(memc_ptr, 0);
-
-    assert_msg(instance and memcached_server_error(instance), " ");
-    if (instance and memcached_server_error(instance))
-    {
-      rc= memcached_server_error_return(instance);
-    }
-  }
-  memcached_free(memc_ptr);
-
-  *ret= rc;
-
-  return memcached_success(rc);
-}
diff --git a/libmemcachedutil/pool.cc b/libmemcachedutil/pool.cc
deleted file mode 100644 (file)
index 8d76024..0000000
+++ /dev/null
@@ -1,523 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libmemcachedutil/common.h>
-
-#include <cassert>
-#include <cerrno>
-#include <pthread.h>
-#include <memory>
-
-struct memcached_pool_st
-{
-  pthread_mutex_t mutex;
-  pthread_cond_t cond;
-  memcached_st *master;
-  memcached_st **server_pool;
-  int firstfree;
-  const uint32_t size;
-  uint32_t current_size;
-  bool _owns_master;
-  struct timespec _timeout;
-
-  memcached_pool_st(memcached_st *master_arg, size_t max_arg) :
-    master(master_arg),
-    server_pool(NULL),
-    firstfree(-1),
-    size(uint32_t(max_arg)),
-    current_size(0),
-    _owns_master(false)
-  {
-    pthread_mutex_init(&mutex, NULL);
-    pthread_cond_init(&cond, NULL);
-    _timeout.tv_sec= 5;
-    _timeout.tv_nsec= 0;
-  }
-
-  const struct timespec& timeout() const
-  {
-    return _timeout;
-  }
-
-  bool release(memcached_st*, memcached_return_t& rc);
-
-  memcached_st *fetch(memcached_return_t& rc);
-  memcached_st *fetch(const struct timespec&, memcached_return_t& rc);
-
-  bool init(uint32_t initial);
-
-  ~memcached_pool_st()
-  {
-    for (int x= 0; x <= firstfree; ++x)
-    {
-      memcached_free(server_pool[x]);
-      server_pool[x]= NULL;
-    }
-
-    int error;
-    if ((error= pthread_mutex_destroy(&mutex)) != 0)
-    {
-      assert_vmsg(error != 0, "pthread_mutex_destroy() %s(%d)", strerror(error), error);
-    }
-
-    if ((error= pthread_cond_destroy(&cond)) != 0)
-    {
-      assert_vmsg(error != 0, "pthread_cond_destroy() %s", strerror(error));
-    }
-
-    delete [] server_pool;
-    if (_owns_master)
-    {
-      memcached_free(master);
-    }
-  }
-
-  void increment_version()
-  {
-    ++master->configure.version;
-  }
-
-  bool compare_version(const memcached_st *arg) const
-  {
-    return (arg->configure.version == version());
-  }
-
-  int32_t version() const
-  {
-    return master->configure.version;
-  }
-};
-
-
-/**
- * Grow the connection pool by creating a connection structure and clone the
- * original memcached handle.
- */
-static bool grow_pool(memcached_pool_st* pool)
-{
-  assert(pool);
-
-  memcached_st *obj;
-  if (not (obj= memcached_clone(NULL, pool->master)))
-  {
-    return false;
-  }
-
-  pool->server_pool[++pool->firstfree]= obj;
-  pool->current_size++;
-  obj->configure.version= pool->version();
-
-  return true;
-}
-
-bool memcached_pool_st::init(uint32_t initial)
-{
-  server_pool= new (std::nothrow) memcached_st *[size];
-  if (server_pool == NULL)
-  {
-    return false;
-  }
-
-  /*
-    Try to create the initial size of the pool. An allocation failure at
-    this time is not fatal..
-  */
-  for (unsigned int x= 0; x < initial; ++x)
-  {
-    if (grow_pool(this) == false)
-    {
-      break;
-    }
-  }
-
-  return true;
-}
-
-
-static inline memcached_pool_st *_pool_create(memcached_st* master, uint32_t initial, uint32_t max)
-{
-  if (initial == 0 or max == 0 or (initial > max))
-  {
-    return NULL;
-  }
-
-  memcached_pool_st *object= new (std::nothrow) memcached_pool_st(master, max);
-  if (object == NULL)
-  {
-    return NULL;
-  }
-
-  /*
-    Try to create the initial size of the pool. An allocation failure at
-    this time is not fatal..
-  */
-  if (not object->init(initial))
-  {
-    delete object;
-    return NULL;
-  }
-
-  return object;
-}
-
-memcached_pool_st *memcached_pool_create(memcached_st* master, uint32_t initial, uint32_t max)
-{
-  return _pool_create(master, initial, max);
-}
-
-memcached_pool_st * memcached_pool(const char *option_string, size_t option_string_length)
-{
-  memcached_st *memc= memcached(option_string, option_string_length);
-
-  if (memc == NULL)
-  {
-    return NULL;
-  }
-
-  memcached_pool_st *self= memcached_pool_create(memc, memc->configure.initial_pool_size, memc->configure.max_pool_size);
-  if (self == NULL)
-  {
-    memcached_free(memc);
-    return NULL;
-  }
-
-  self->_owns_master= true;
-
-  return self;
-}
-
-memcached_st*  memcached_pool_destroy(memcached_pool_st* pool)
-{
-  if (pool == NULL)
-  {
-    return NULL;
-  }
-
-  // Legacy that we return the original structure
-  memcached_st *ret= NULL;
-  if (pool->_owns_master)
-  { }
-  else
-  {
-    ret= pool->master;
-  }
-
-  delete pool;
-
-  return ret;
-}
-
-memcached_st* memcached_pool_st::fetch(memcached_return_t& rc)
-{
-  static struct timespec relative_time= { 0, 0 };
-  return fetch(relative_time, rc);
-}
-
-memcached_st* memcached_pool_st::fetch(const struct timespec& relative_time, memcached_return_t& rc)
-{
-  rc= MEMCACHED_SUCCESS;
-
-  int error;
-  if ((error= pthread_mutex_lock(&mutex)) != 0)
-  {
-    rc= MEMCACHED_IN_PROGRESS;
-    return NULL;
-  }
-
-  memcached_st *ret= NULL;
-  do
-  {
-    if (firstfree > -1)
-    {
-      ret= server_pool[firstfree--];
-    }
-    else if (current_size == size)
-    {
-      if (relative_time.tv_sec == 0 and relative_time.tv_nsec == 0)
-      {
-        error= pthread_mutex_unlock(&mutex);
-        rc= MEMCACHED_NOTFOUND;
-
-        return NULL;
-      }
-
-      struct timespec time_to_wait= {0, 0};
-      time_to_wait.tv_sec= time(NULL) +relative_time.tv_sec;
-      time_to_wait.tv_nsec= relative_time.tv_nsec;
-
-      int thread_ret;
-      if ((thread_ret= pthread_cond_timedwait(&cond, &mutex, &time_to_wait)) != 0)
-      {
-        int unlock_error;
-        if ((unlock_error= pthread_mutex_unlock(&mutex)) != 0)
-        {
-          assert_vmsg(error != 0, "pthread_mutex_unlock() %s", strerror(error));
-        }
-
-        if (thread_ret == ETIMEDOUT)
-        {
-          rc= MEMCACHED_TIMEOUT;
-        }
-        else
-        {
-          errno= thread_ret;
-          rc= MEMCACHED_ERRNO;
-        }
-
-        return NULL;
-      }
-    }
-    else if (grow_pool(this) == false)
-    {
-      int unlock_error;
-      if ((unlock_error= pthread_mutex_unlock(&mutex)) != 0)
-      {
-        assert_vmsg(error != 0, "pthread_mutex_unlock() %s", strerror(error));
-      }
-
-      return NULL;
-    }
-  } while (ret == NULL);
-
-  if ((error= pthread_mutex_unlock(&mutex)) != 0)
-  {
-    assert_vmsg(error != 0, "pthread_mutex_unlock() %s", strerror(error));
-  }
-
-  return ret;
-}
-
-bool memcached_pool_st::release(memcached_st *released, memcached_return_t& rc)
-{
-  rc= MEMCACHED_SUCCESS;
-  if (released == NULL)
-  {
-    rc= MEMCACHED_INVALID_ARGUMENTS;
-    return false;
-  }
-
-  int error;
-  if ((error= pthread_mutex_lock(&mutex)))
-  {
-    rc= MEMCACHED_IN_PROGRESS;
-    return false;
-  }
-
-  /* 
-    Someone updated the behavior on the object, so we clone a new memcached_st with the new settings. If we fail to clone, we keep the old one around.
-  */
-  if (compare_version(released) == false)
-  {
-    memcached_st *memc;
-    if ((memc= memcached_clone(NULL, master)))
-    {
-      memcached_free(released);
-      released= memc;
-    }
-  }
-
-  server_pool[++firstfree]= released;
-
-  if (firstfree == 0 and current_size == size)
-  {
-    /* we might have people waiting for a connection.. wake them up :-) */
-    if ((error= pthread_cond_broadcast(&cond)) != 0)
-    {
-      assert_vmsg(error != 0, "pthread_cond_broadcast() %s", strerror(error));
-    }
-  }
-
-  if ((error= pthread_mutex_unlock(&mutex)) != 0)
-  {
-  }
-
-  return true;
-}
-
-memcached_st* memcached_pool_fetch(memcached_pool_st* pool, struct timespec* relative_time, memcached_return_t* rc)
-{
-  if (pool == NULL)
-  {
-    return NULL;
-  }
-
-  memcached_return_t unused;
-  if (rc == NULL)
-  {
-    rc= &unused;
-  }
-
-  if (relative_time == NULL)
-  {
-    return pool->fetch(*rc);
-  }
-
-  return pool->fetch(*relative_time, *rc);
-}
-
-memcached_st* memcached_pool_pop(memcached_pool_st* pool,
-                                 bool block,
-                                 memcached_return_t *rc)
-{
-  if (pool == NULL)
-  {
-    return NULL;
-  }
-
-  memcached_return_t unused;
-  if (rc == NULL)
-  {
-    rc= &unused;
-  }
-
-  memcached_st *memc;
-  if (block)
-  {
-    memc= pool->fetch(pool->timeout(), *rc);
-  }
-  else
-  {
-    memc= pool->fetch(*rc);
-  }
-
-  return memc;
-}
-
-memcached_return_t memcached_pool_release(memcached_pool_st* pool, memcached_st *released)
-{
-  if (pool == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  memcached_return_t rc;
-
-  (void) pool->release(released, rc);
-
-  return rc;
-}
-
-memcached_return_t memcached_pool_push(memcached_pool_st* pool, memcached_st *released)
-{
-  return memcached_pool_release(pool, released);
-}
-
-
-memcached_return_t memcached_pool_behavior_set(memcached_pool_st *pool,
-                                               memcached_behavior_t flag,
-                                               uint64_t data)
-{
-  if (pool == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  int error;
-  if ((error= pthread_mutex_lock(&pool->mutex)))
-  {
-    return MEMCACHED_IN_PROGRESS;
-  }
-
-  /* update the master */
-  memcached_return_t rc= memcached_behavior_set(pool->master, flag, data);
-  if (memcached_failed(rc))
-  {
-    if ((error= pthread_mutex_unlock(&pool->mutex)) != 0)
-    {
-      assert_vmsg(error != 0, "pthread_mutex_unlock() %s", strerror(error));
-    }
-    return rc;
-  }
-
-  pool->increment_version();
-  /* update the clones */
-  for (int xx= 0; xx <= pool->firstfree; ++xx)
-  {
-    if (memcached_success(memcached_behavior_set(pool->server_pool[xx], flag, data)))
-    {
-      pool->server_pool[xx]->configure.version= pool->version();
-    }
-    else
-    {
-      memcached_st *memc;
-      if ((memc= memcached_clone(NULL, pool->master)))
-      {
-        memcached_free(pool->server_pool[xx]);
-        pool->server_pool[xx]= memc;
-        /* I'm not sure what to do in this case.. this would happen
-          if we fail to push the server list inside the client..
-          I should add a testcase for this, but I believe the following
-          would work, except that you would add a hole in the pool list..
-          in theory you could end up with an empty pool....
-        */
-      }
-    }
-  }
-
-  if ((error= pthread_mutex_unlock(&pool->mutex)) != 0)
-  {
-    assert_vmsg(error != 0, "pthread_mutex_unlock() %s", strerror(error));
-  }
-
-  return rc;
-}
-
-memcached_return_t memcached_pool_behavior_get(memcached_pool_st *pool,
-                                               memcached_behavior_t flag,
-                                               uint64_t *value)
-{
-  if (pool == NULL)
-  {
-    return MEMCACHED_INVALID_ARGUMENTS;
-  }
-
-  int error;
-  if ((error= pthread_mutex_lock(&pool->mutex)))
-  {
-    return MEMCACHED_IN_PROGRESS;
-  }
-
-  *value= memcached_behavior_get(pool->master, flag);
-
-  if ((error= pthread_mutex_unlock(&pool->mutex)) != 0)
-  {
-    assert_vmsg(error != 0, "pthread_mutex_unlock() %s", strerror(error));
-  }
-
-  return MEMCACHED_SUCCESS;
-}
diff --git a/libmemcachedutil/version.cc b/libmemcachedutil/version.cc
deleted file mode 100644 (file)
index 75a8f60..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Libmemcached library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  Copyright (C) 2010 Brian Aker All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <libmemcachedutil/common.h>
-#include <cassert>
-
-struct local_context
-{
-  uint8_t major_version;
-  uint8_t minor_version;
-  uint8_t micro_version;
-
-  bool truth;
-};
-
-static memcached_return_t check_server_version(const memcached_st *,
-                                               const memcached_instance_st * instance,
-                                               void *context)
-{
-  /* Do Nothing */
-  struct local_context *check= (struct local_context *)context;
-
-  if (memcached_server_major_version(instance) != UINT8_MAX) {
-    uint32_t sv, cv;
-
-    sv = memcached_server_micro_version(instance)
-        |memcached_server_minor_version(instance) << 8
-        |memcached_server_major_version(instance) << 16
-        ;
-    cv = check->micro_version
-        |check->minor_version << 8
-        |check->major_version << 16;
-
-    if (sv >= cv) {
-      return MEMCACHED_SUCCESS;
-    }
-  }
-
-  check->truth= false;
-
-  return MEMCACHED_FAILURE;
-}
-
-bool libmemcached_util_version_check(memcached_st *memc,
-                                     uint8_t major_version,
-                                     uint8_t minor_version,
-                                     uint8_t micro_version)
-{
-  if (memcached_failed(memcached_version(memc)))
-  {
-    return false;
-  }
-
-  struct local_context check= { major_version, minor_version, micro_version, true };
-
-  memcached_server_fn callbacks[1];
-  callbacks[0]= check_server_version;
-  memcached_server_cursor(memc, callbacks, (void *)&check,  1);
-
-  return check.truth;
-}
diff --git a/libtest/CMakeLists.txt b/libtest/CMakeLists.txt
deleted file mode 100644 (file)
index 492465f..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-
-file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/tmp_chroot)
-file(WRITE ${CMAKE_BINARY_DIR}/libtool
-"#!/bin/bash
-shift
-exec $@
-")
-if(UNIX)
-    if(EXISTS ${CMAKE_BINARY_DIR}/libtool)
-        execute_process(COMMAND chmod +x ${CMAKE_BINARY_DIR}/libtool)
-    endif()
-endif()
-
-add_library(libtest STATIC
-        alarm.cc
-        binaries.cc
-        client.cc
-        cmdline.cc
-        collection.cc
-        comparison.cc
-        core.cc
-        cpu.cc
-        dns.cc
-        dream.cc
-        drizzled.cc
-        exception.cc
-        exception/fatal.cc
-        formatter.cc
-        framework.cc
-        gearmand.cc
-        has.cc
-        http.cc
-        is_local.cc
-        killpid.cc
-        libtool.cc
-        main.cc
-        memcached.cc
-        port.cc
-        result.cc
-        runner.cc
-        server.cc
-        server_container.cc
-        signal.cc
-        socket.cc
-        strerror.cc
-        timer.cc
-        tmpfile.cc
-        vchar.cc
-        )
-set_target_properties(libtest PROPERTIES LIBRARY_OUTPUT_NAME test)
-target_compile_definitions(libtest PRIVATE
-        BUILDING_LIBTEST=1
-        LIBTEST_TEMP=\"${CMAKE_BINARY_DIR}/tmp_chroot\"
-
-        DRIZZLED_BINARY=\"drizzled\"
-        GEARMAND_BINARY=\"gearmand\"
-        MEMCACHED_BINARY=\"${MEMCACHED_BINARY}\"
-        HAVE_MEMCACHED_BINARY=1
-        )
-target_link_libraries(libtest PRIVATE Threads::Threads ${CMAKE_DL_LIBS})
-target_include_directories(libtest PRIVATE ..)
-
-add_executable(wait wait.cc dream.cc)
-target_include_directories(wait PRIVATE ..)
-
-add_executable(core_count core_count.cc cpu.cc)
-target_include_directories(core_count PRIVATE ..)
-
-add_executable(backtrace backtrace_test.cc ../libmemcached/backtrace.cc)
-target_link_libraries(backtrace PRIVATE ${CMAKE_DL_LIBS})
-target_include_directories(backtrace PRIVATE ..)
-
-configure_file(yatlcon.h.in yatlcon.h @ONLY)
-configure_file(version.h.in version.h @ONLY)
diff --git a/libtest/alarm.cc b/libtest/alarm.cc
deleted file mode 100644 (file)
index 6193fbb..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include <libtest/common.h>
-
-#include <sys/time.h>
-#include <cstdlib>
-
-namespace libtest {
-
-static const struct timeval default_it_value= { 600, 0 };
-static const struct timeval default_it_interval= { 0, 0 };
-static const struct itimerval defualt_timer= { default_it_interval, default_it_value };
-
-static const struct itimerval cancel_timer= { default_it_interval, default_it_interval };
-
-
-void set_alarm()
-{
-  if (setitimer(ITIMER_VIRTUAL, &defualt_timer, NULL) == -1)
-  {
-    Error << "setitimer() failed";
-  }
-}
-
-void set_alarm(long tv_sec, long tv_usec)
-{
-  // For the moment use any value to YATL_ALARM to cancel alarming.
-  if (getenv("YATL_ALARM"))
-  {
-    errno= 0;
-    tv_sec= strtol(getenv("YATL_ALARM"), (char **) NULL, 10);
-
-    if (errno != 0)
-    {
-      FATAL("Bad value for YATL_ALARM");
-    }
-    else if (tv_sec == 0)
-    {
-      cancel_alarm();
-    }
-  }
-
-#ifdef __APPLE__
-  struct timeval it_value= { time_t(tv_sec), suseconds_t(tv_usec) };
-#else
-  struct timeval it_value= { tv_sec, tv_usec };
-#endif
-
-  struct itimerval timer= { default_it_interval, it_value };
-
-  if (setitimer(ITIMER_VIRTUAL, &timer, NULL) == -1)
-  {
-    Error << "setitimer() failed";
-  }
-}
-
-void cancel_alarm()
-{
-  if (setitimer(ITIMER_VIRTUAL, &cancel_timer, NULL) == -1)
-  {
-    Error << "setitimer() failed";
-  }
-}
-
-} // namespace libtest
-
diff --git a/libtest/alarm.h b/libtest/alarm.h
deleted file mode 100644 (file)
index f675c58..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-void set_alarm(long tv_sec, long tv_usec);
-void set_alarm();
-void cancel_alarm();
-
-} // namespace libtest
-
diff --git a/libtest/backtrace_test.cc b/libtest/backtrace_test.cc
deleted file mode 100644 (file)
index d4af451..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <cerrno>
-#include <csignal>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <iostream>
-
-#include "libmemcached/backtrace.hpp"
-
-class Test {
-public:
-  Test()
-  {
-  }
-
-  void call_backtrace()
-  {
-    std::cerr << __func__ << std::endl;
-    custom_backtrace();
-  }
-};
-
-void SIGSEGV_handler(int sig_num, siginfo_t* info, void* ucontext)
-{
-  std::cerr << __func__ << std::endl;
-  (void)sig_num;
-  (void)info;
-  (void)ucontext;
-
-  custom_backtrace();
-}
-
-int raise_SIGSEGV()
-{
-  std::cerr << std::endl << "Calling backtrace()" << std::endl;
-  custom_backtrace();
-  std::cerr << std::endl << "Calling raise()" << std::endl;
-  return raise(SIGSEGV);
-}
-
-int layer4()
-{
-  return raise_SIGSEGV();
-}
-
-int layer3()
-{
-  return layer4();
-}
-
-int layer2()
-{
-  return layer3();
-}
-
-int layer1()
-{
-  return layer2();
-}
-
-int main(int, char **)
-{
-  Test t;
-
-  t.call_backtrace();
-
-  struct sigaction sigact;
-
-  sigact.sa_sigaction= SIGSEGV_handler;
-  sigact.sa_flags= SA_RESTART | SA_SIGINFO;
-
-  if (sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL) != 0)
-  {
-    std::cerr << "error setting signal handler for " << strsignal(SIGSEGV) << "(" <<  SIGSEGV << ")" << std::endl;
-
-    exit(EXIT_FAILURE);
-  }
-
-  int ret= layer1();
-  if (ret)
-  {
-    std::cerr << "raise() " << strerror(errno) << std::endl;
-    exit(EXIT_FAILURE);
-  }
-
-  exit(EXIT_SUCCESS);
-}
diff --git a/libtest/binaries.cc b/libtest/binaries.cc
deleted file mode 100644 (file)
index 9adfb89..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-namespace libtest {
-
-}
diff --git a/libtest/binaries.h b/libtest/binaries.h
deleted file mode 100644 (file)
index 7829f3f..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-} // namespace libtest
diff --git a/libtest/blobslap_worker.cc b/libtest/blobslap_worker.cc
deleted file mode 100644 (file)
index 5100a38..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-#include <libtest/blobslap_worker.h>
-
-#include <cassert>
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <iostream>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
-
-namespace libtest {
-
-class BlobslapWorker : public Server
-{
-private:
-public:
-  BlobslapWorker(in_port_t port_arg) :
-    Server("localhost", port_arg, "benchmark/blobslap_worker", true)
-  { 
-    set_pid_file();
-  }
-
-  pid_t get_pid(bool error_is_ok)
-  {
-    if (pid_file().empty())
-    {
-      Error << "pid_file was empty";
-      return -1;
-    }
-
-    Wait wait(pid_file(), 0);
-
-    if (error_is_ok and not wait.successful())
-    {
-      Error << "Pidfile was not found:" << pid_file();
-      return -1;
-    }
-
-    std::stringstream error_message;
-    pid_t ret= get_pid_from_file(pid_file(), error_message);
-
-    if (error_is_ok and is_pid_valid(ret) == false)
-    {
-      Error << error_message.str();
-    }
-
-    return ret;
-  }
-
-  bool ping()
-  {
-    if (pid_file().empty())
-    {
-      Error << "No pid file available";
-      return false;
-    }
-
-    Wait wait(pid_file(), 0);
-    if (not wait.successful())
-    {
-      Error << "Pidfile was not found:" << pid_file();
-      return false;
-    }
-
-    std::stringstream error_message;
-    pid_t local_pid= get_pid_from_file(pid_file(), error_message);
-    if (is_pid_valid(local_pid) == false)
-    {
-      Error << error_message.str();
-      return false;
-    }
-
-    // Use kill to determine is the process exist
-    if (::kill(local_pid, 0) == 0)
-    {
-      return true;
-    }
-
-    return false;
-  }
-
-  const char *name()
-  {
-    return "blobslap_worker";
-  };
-
-  bool has_port_option() const
-  {
-    return true;
-  }
-
-  bool has_log_file_option() const
-  {
-    return true;
-  }
-
-  bool is_libtool()
-  {
-    return true;
-  }
-
-  bool build();
-};
-
-
-#include <sstream>
-
-bool BlobslapWorker::build()
-{
-  return true;
-}
-
-Server *build_blobslap_worker(in_port_t try_port)
-{
-  return new BlobslapWorker(try_port);
-}
-
-} // namespace libtest
diff --git a/libtest/blobslap_worker.h b/libtest/blobslap_worker.h
deleted file mode 100644 (file)
index 907ae6e..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-Server *build_blobslap_worker(in_port_t try_port);
-
-}
diff --git a/libtest/callbacks.h b/libtest/callbacks.h
deleted file mode 100644 (file)
index 1e617b4..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void* (test_callback_create_fn)(libtest::server_startup_st&, test_return_t&);
-typedef bool test_callback_destroy_fn(void *);
-typedef enum test_return_t (test_callback_fn)(void *);
-typedef enum test_return_t (test_callback_runner_fn)(test_callback_fn*, void *);
-typedef enum test_return_t (test_callback_error_fn)(const test_return_t, void *);
-
-#ifdef __cplusplus
-}
-#endif
-
diff --git a/libtest/client.cc b/libtest/client.cc
deleted file mode 100644 (file)
index c536e9d..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#include <string>
-
-#ifdef HAVE_POLL_H
-# include <poll.h>
-#endif
-
-#ifndef HAVE_MSG_NOSIGNAL
-# define MSG_NOSIGNAL 0
-#endif
-
-namespace libtest {
-
-SimpleClient::SimpleClient(const std::string& hostname_, in_port_t port_) :
-  _is_connected(false),
-  _hostname(hostname_),
-  _port(port_),
-  sock_fd(INVALID_SOCKET),
-  requested_message(1)
-  {
-  }
-
-bool SimpleClient::ready(int event_)
-{
-  struct pollfd fds[1];
-  fds[0].fd= sock_fd;
-  fds[0].events= event_;
-  fds[0].revents= 0;
-
-  int timeout= 5000;
-  if (_is_connected == false)
-  {
-    timeout= timeout * 30;
-  }
-
-  int ready_fds= poll(fds, 1, timeout);
-
-  if (ready_fds == -1)
-  {
-    _error= strerror(errno);
-    return false;
-  }
-  else if (ready_fds == 1)
-  {
-    if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL))
-    {
-      int err;
-      socklen_t len= sizeof (err);
-      // We replace errno with err if getsockopt() passes, but err has been
-      // set.
-      if (getsockopt(fds[0].fd, SOL_SOCKET, SO_ERROR, &err, &len) == 0)
-      {
-        // We check the value to see what happened wth the socket.
-        if (err == 0)
-        {
-          _error= "getsockopt() returned no error but poll() indicated one existed";
-          return false;
-        }
-        errno= err;
-      }
-      _error= strerror(errno);
-
-      return false;
-    }
-
-    _is_connected= true;
-    if (fds[0].revents & event_)
-    {
-      return true;
-    }
-  }
-
-  fatal_assert(ready_fds == 0);
-  _error= "TIMEOUT";
-
-  return false;
-}
-
-struct addrinfo* SimpleClient::lookup()
-{
-  struct addrinfo *ai= NULL;
-  struct addrinfo hints;
-  memset(&hints, 0, sizeof(struct addrinfo));
-  hints.ai_socktype= SOCK_STREAM;
-  hints.ai_protocol= IPPROTO_TCP;
-
-  libtest::vchar_t service;
-  service.resize(NI_MAXSERV);
-  (void)snprintf(&service[0], service.size(), "%d", _port);
-
-  int getaddrinfo_error;
-  if ((getaddrinfo_error= getaddrinfo(_hostname.c_str(), &service[0], &hints, &ai)) != 0)
-  {
-    if (getaddrinfo_error != EAI_SYSTEM)
-    {
-      _error= gai_strerror(getaddrinfo_error);
-      return NULL;
-    }
-    else
-    {
-      _error= strerror(getaddrinfo_error);
-      return NULL;
-    }
-  }
-
-  return ai;
-}
-
-SimpleClient::~SimpleClient()
-{
-  close_socket();
-}
-
-void SimpleClient::close_socket()
-{
-  if (sock_fd != INVALID_SOCKET)
-  {
-    close(sock_fd);
-    sock_fd= INVALID_SOCKET;
-  }
-}
-
-bool SimpleClient::instance_connect()
-{
-  _is_connected= false;
-  struct addrinfo *ai;
-  if ((ai= lookup()))
-  {
-    {
-      struct addrinfo* address_info_next= ai;
-
-      while (address_info_next and sock_fd == INVALID_SOCKET)
-      {
-        if ((sock_fd= socket(address_info_next->ai_family, address_info_next->ai_socktype, address_info_next->ai_protocol)) != SOCKET_ERROR)
-        {
-          if (connect(sock_fd, address_info_next->ai_addr, address_info_next->ai_addrlen) == SOCKET_ERROR)
-          {
-            switch (errno)
-            {
-            case EINTR:
-              close_socket();
-              continue;
-
-            case EINPROGRESS: // nonblocking mode - first return
-            case EALREADY: // nonblocking mode - subsequent returns
-              continue; // Jump to while() and continue on
-
-
-            case ECONNREFUSED:
-            default:
-              break;
-            }
-
-            close_socket();
-            _error= strerror(errno);
-          }
-        }
-        else
-        {
-          FATAL(strerror(errno));
-        }
-        address_info_next= address_info_next->ai_next;
-      }
-
-      freeaddrinfo(ai);
-    }
-
-    if (sock_fd == INVALID_SOCKET)
-    {
-      fatal_assert(_error.size());
-    }
-
-    return bool(sock_fd != INVALID_SOCKET);
-  }
-
-  return false;
-}
-
-bool SimpleClient::is_valid()
-{
-  _error.clear();
-  if (sock_fd == INVALID_SOCKET)
-  {
-    return instance_connect();
-  }
-
-  return true;
-}
-
-bool SimpleClient::message(const char* ptr, const size_t len)
-{
-  if (is_valid())
-  {
-    if (ready(POLLOUT))
-    {
-      off_t offset= 0;
-      do
-      {
-        ssize_t nw= send(sock_fd, ptr + offset, len - offset, MSG_NOSIGNAL);
-        if (nw == -1)
-        {
-          if (errno != EINTR)
-          {
-            _error= strerror(errno);
-            return false;
-          }
-        }
-        else
-        {
-          offset += nw;
-        }
-      } while (offset < ssize_t(len));
-
-      return true;
-    }
-  }
-
-  fatal_assert(_error.size());
-
-  return false;
-}
-
-bool SimpleClient::send_message(const std::string& arg)
-{
-  if (message(arg.c_str(), arg.size()) == true)
-  {
-    return message("\r\n", 2);
-  }
-
-  return false;
-}
-
-bool SimpleClient::send_data(const libtest::vchar_t& message_, libtest::vchar_t& response_)
-{
-  requested_message++;
-  if (message(&message_[0], message_.size()))
-  {
-    return response(response_);
-  }
-
-  return false;
-}
-
-bool SimpleClient::send_message(const std::string& message_, std::string& response_)
-{
-  requested_message++;
-  if (send_message(message_))
-  {
-    return response(response_);
-  }
-
-  return false;
-}
-
-bool SimpleClient::response(libtest::vchar_t& response_)
-{
-  response_.clear();
-
-  if (is_valid())
-  {
-    if (ready(POLLIN))
-    {
-      bool more= true;
-      char buffer[2];
-      buffer[1]= 0;
-      do
-      {
-        ssize_t nr= recv(sock_fd, buffer, 1, MSG_NOSIGNAL);
-        if (nr == -1)
-        {
-          if (errno != EINTR)
-          {
-            _error= strerror(errno);
-            return false;
-          }
-        }
-        else if (nr == 0)
-        {
-          close_socket();
-          more= false;
-        }
-        else
-        {
-          response_.reserve(response_.size() + nr +1);
-          fatal_assert(nr == 1);
-          if (buffer[0] == '\n')
-          {
-            more= false;
-          }
-          response_.insert(response_.end(), buffer, buffer +nr);
-        }
-      } while (more);
-
-      return response_.size();
-    }
-  }
-
-  fatal_assert(_error.size());
-  return false;
-}
-
-bool SimpleClient::response(std::string& response_)
-{
-  response_.clear();
-
-  if (is_valid())
-  {
-    if (ready(POLLIN))
-    {
-      bool more= true;
-      char buffer[2];
-      buffer[1]= 0;
-      do
-      {
-        ssize_t nr= recv(sock_fd, buffer, 1, MSG_NOSIGNAL);
-        if (nr == -1)
-        {
-          if (errno != EINTR)
-          {
-            _error= strerror(errno);
-            return false;
-          }
-        }
-        else if (nr == 0)
-        {
-          close_socket();
-          more= false;
-        }
-        else
-        {
-          fatal_assert(nr == 1);
-          if (buffer[0] == '\n')
-          {
-            more= false;
-          }
-          response_.append(buffer);
-        }
-      } while (more);
-
-      return response_.size();
-    }
-  }
-
-  fatal_assert(_error.size());
-  return false;
-}
-
-} // namespace libtest
diff --git a/libtest/client.hpp b/libtest/client.hpp
deleted file mode 100644 (file)
index 979a532..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-class SimpleClient {
-public:
-  SimpleClient(const std::string& hostname_, in_port_t port_);
-  ~SimpleClient();
-
-  bool send_data(const libtest::vchar_t&, libtest::vchar_t&);
-  bool send_message(const std::string&);
-  bool send_message(const std::string&, std::string&);
-  bool response(std::string&);
-  bool response(libtest::vchar_t&);
-
-  bool is_valid();
-
-  const std::string& error() const
-  {
-    return _error;
-  }
-
-  bool is_error() const
-  {
-    return _error.size() ? true : false;
-  }
-
-private: // Methods
-  void close_socket();
-  bool instance_connect();
-  struct addrinfo* lookup();
-  bool message(const char* ptr, const size_t len);
-  bool ready(int event_);
-
-private:
-  bool _is_connected;
-  std::string _hostname;
-  in_port_t _port;
-  int sock_fd;
-  std::string _error;
-  int requested_message;
-};
-
-} // namespace libtest
diff --git a/libtest/cmdline.cc b/libtest/cmdline.cc
deleted file mode 100644 (file)
index 375b00a..0000000
+++ /dev/null
@@ -1,868 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include "libtest/common.h"
-
-using namespace libtest;
-
-#include <cstdlib>
-#include <cstring>
-#include <cerrno>
-#include <fcntl.h>
-#include <fstream>
-#include <memory>
-#ifdef HAVE_POLL_H
-# include <poll.h>
-#endif
-#ifdef HAVE_SPAWN_H
-# include <spawn.h>
-#endif
-#include <sstream>
-#include <string>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <algorithm>
-#include <stdexcept>
-
-#ifndef __USE_GNU
-static char **environ= NULL;
-#endif
-
-#ifndef FD_CLOEXEC
-# define FD_CLOEXEC 0
-#endif
-
-namespace {
-
-  std::string print_argv(libtest::vchar_ptr_t& built_argv)
-  {
-    std::stringstream arg_buffer;
-
-    for (vchar_ptr_t::iterator iter= built_argv.begin();
-         iter != built_argv.end();
-         ++iter)
-    {
-      if (*iter)
-      {
-        arg_buffer << *iter << " ";
-      }
-    }
-
-    return arg_buffer.str();
-  }
-
-#if 0
-  std::string print_argv(char** argv)
-  {
-    std::stringstream arg_buffer;
-
-    for (char** ptr= argv; *ptr; ++ptr)
-    {
-      arg_buffer << *ptr << " ";
-    }
-
-    return arg_buffer.str();
-  }
-#endif
-
-  static Application::error_t int_to_error_t(int arg)
-  {
-    switch (arg)
-    {
-    case 127:
-      return Application::INVALID_POSIX_SPAWN;
-
-    case 0:
-      return Application::SUCCESS;
-
-    case 1:
-      return Application::FAILURE;
-
-    default:
-      return Application::UNKNOWN;
-    }
-  }
-}
-
-namespace libtest {
-
-Application::Application(const std::string& arg, const bool _use_libtool_arg) :
-  _use_libtool(_use_libtool_arg),
-  _use_valgrind(false),
-  _use_gdb(false),
-  _use_ptrcheck(false),
-  _will_fail(false),
-  _argc(0),
-  _exectuble(arg),
-  stdin_fd(STDIN_FILENO),
-  stdout_fd(STDOUT_FILENO),
-  stderr_fd(STDERR_FILENO),
-  _pid(-1),
-  _status(0),
-  _app_exit_state(UNINITIALIZED)
-  { 
-    if (_use_libtool)
-    {
-      if (libtool() == NULL)
-      {
-        FATAL("libtool requested, but no libtool was found");
-      }
-    }
-
-    // Find just the name of the application with no path
-    {
-      size_t found= arg.find_last_of("/\\");
-      if (found)
-      {
-        _exectuble_name= arg.substr(found +1);
-      }
-      else
-      {
-        _exectuble_name= arg;
-      }
-    }
-
-    if (_use_libtool and getenv("PWD"))
-    {
-      _exectuble_with_path+= getenv("PWD");
-      _exectuble_with_path+= "/";
-    }
-    _exectuble_with_path+= _exectuble;
-  }
-
-Application::~Application()
-{
-  murder();
-  delete_argv();
-}
-
-Application::error_t Application::run(const char *args[])
-{
-  stdin_fd.reset();
-  stdout_fd.reset();
-  stderr_fd.reset();
-  _stdout_buffer.clear();
-  _stderr_buffer.clear();
-
-  posix_spawn_file_actions_t file_actions;
-  posix_spawn_file_actions_init(&file_actions);
-
-  stdin_fd.dup_for_spawn(file_actions);
-  stdout_fd.dup_for_spawn(file_actions);
-  stderr_fd.dup_for_spawn(file_actions);
-
-  posix_spawnattr_t spawnattr;
-  posix_spawnattr_init(&spawnattr);
-
-  short flags= 0;
-
-  // Child should not block signals
-  flags |= POSIX_SPAWN_SETSIGMASK;
-
-  sigset_t mask;
-  sigemptyset(&mask);
-
-  fatal_assert(posix_spawnattr_setsigmask(&spawnattr, &mask) == 0);
-
-#if defined(POSIX_SPAWN_USEVFORK) || defined(__linux__)
-  // Use USEVFORK on linux
-  flags |= POSIX_SPAWN_USEVFORK;
-#endif
-
-  flags |= POSIX_SPAWN_SETPGROUP;
-  fatal_assert(posix_spawnattr_setpgroup(&spawnattr, 0) == 0);
-
-  fatal_assert(posix_spawnattr_setflags(&spawnattr, flags) == 0);
-  
-  create_argv(args);
-
-  int spawn_ret;
-  if (_use_gdb)
-  {
-    std::string gdb_run_file= create_tmpfile(_exectuble_name);
-    std::fstream file_stream;
-    file_stream.open(gdb_run_file.c_str(), std::fstream::out | std::fstream::trunc);
-
-    _gdb_filename= create_tmpfile(_exectuble_name);
-    file_stream 
-      << "set logging redirect on" << std::endl
-      << "set logging file " << _gdb_filename << std::endl
-      << "set logging overwrite on" << std::endl
-      << "set logging on" << std::endl
-      << "set environment LIBTEST_IN_GDB=1" << std::endl
-      << "run " << arguments() << std::endl
-      << "thread apply all bt" << std::endl
-      << "quit" << std::endl;
-
-    fatal_assert(file_stream.good());
-    file_stream.close();
-
-    if (_use_libtool)
-    {
-      // libtool --mode=execute gdb -f -x binary
-      char *argv[]= {
-        const_cast<char *>(libtool()),
-        const_cast<char *>("--mode=execute"),
-        const_cast<char *>("gdb"),
-        const_cast<char *>("-batch"),
-        const_cast<char *>("-f"),
-        const_cast<char *>("-x"),
-        const_cast<char *>(gdb_run_file.c_str()), 
-        const_cast<char *>(_exectuble_with_path.c_str()), 
-        0};
-
-      spawn_ret= posix_spawnp(&_pid, libtool(), &file_actions, &spawnattr, argv, environ);
-    }
-    else
-    {
-      // gdb binary
-      char *argv[]= {
-        const_cast<char *>("gdb"),
-        const_cast<char *>("-batch"),
-        const_cast<char *>("-f"),
-        const_cast<char *>("-x"),
-        const_cast<char *>(gdb_run_file.c_str()), 
-        const_cast<char *>(_exectuble_with_path.c_str()), 
-        0};
-      spawn_ret= posix_spawnp(&_pid, "gdb", &file_actions, &spawnattr, argv, environ);
-    }
-  }
-  else
-  {
-    spawn_ret= posix_spawn(&_pid, built_argv[0], &file_actions, &spawnattr, &built_argv[0], environ);
-  }
-
-  posix_spawn_file_actions_destroy(&file_actions);
-  posix_spawnattr_destroy(&spawnattr);
-
-  stdin_fd.close(Application::Pipe::READ);
-  stdout_fd.close(Application::Pipe::WRITE);
-  stderr_fd.close(Application::Pipe::WRITE);
-
-  if (spawn_ret != 0)
-  {
-    if (_will_fail == false)
-    {
-      std::string sb;
-      char buf[1024];
-
-      std::for_each(built_argv.begin(), built_argv.end()-1, [&sb](const char *a) {
-        if (sb.size()) {
-          sb.append(" ");
-        }
-        sb.append(a);
-      });
-      Error << strerror(spawn_ret) << "(" << spawn_ret << "): " << sb << " cwd:" << getcwd(buf, sizeof(buf)-1);
-    }
-    _pid= -1;
-    return Application::INVALID_POSIX_SPAWN;
-  }
-
-  assert(_pid != -1);
-  if (_pid == -1)
-  {
-    return Application::INVALID_POSIX_SPAWN;
-  }
-
-#if 0
-  app_thread_st* _app_thread= new app_thread_st(_pid, _status, built_argv[0], _app_exit_state);
-  int error;
-  if ((error= pthread_create(&_thread, NULL, &app_thread, _app_thread)) != 0)
-  {
-    Error << "pthread_create() died during pthread_create(" << strerror(error) << ")";
-    return Application::FAILURE;
-  }
-#endif
-
-  return Application::SUCCESS;
-}
-
-bool Application::check() const
-{
-  if (_pid > 1 and kill(_pid, 0) == 0)
-  {
-    return true;
-  }
-
-  return false;
-}
-
-void Application::murder()
-{
-  if (check())
-  {
-    int count= 5;
-    while ((count--) > 0 and check())
-    {
-      if (kill(_pid, SIGTERM) == 0)
-      {
-        join();
-      }
-      else
-      {
-        Error << "kill(pid, SIGTERM) failed after kill with error of " << strerror(errno);
-        continue;
-      }
-
-      break;
-    }
-
-    // If for whatever reason it lives, kill it hard
-    if (check())
-    {
-      Error << "using SIGKILL, things will likely go poorly from this point";
-      (void)kill(_pid, SIGKILL);
-    }
-  }
-  slurp();
-}
-
-// false means that no data was returned
-bool Application::slurp()
-{
-  struct pollfd fds[2];
-  fds[0].fd= stdout_fd.fd();
-  fds[0].events= POLLRDNORM;
-  fds[0].revents= 0;
-  fds[1].fd= stderr_fd.fd();
-  fds[1].events= POLLRDNORM;
-  fds[1].revents= 0;
-
-  int active_fd;
-  if ((active_fd= poll(fds, 2, 0)) == -1)
-  {
-    int error;
-    switch ((error= errno))
-    {
-#ifdef __linux
-    case ERESTART:
-#endif
-    case EINTR:
-      break;
-
-    case EFAULT:
-    case ENOMEM:
-      FATAL(strerror(error));
-      break;
-
-    case EINVAL:
-      FATAL("RLIMIT_NOFILE exceeded, or if OSX the timeout value was invalid");
-      break;
-
-    default:
-      FATAL(strerror(error));
-      break;
-    }
-
-    return false;
-  }
-
-  if (active_fd == 0)
-  {
-    return false;
-  }
-
-  bool data_was_read= false;
-  if (fds[0].revents & POLLRDNORM)
-  {
-    if (stdout_fd.read(_stdout_buffer) == true)
-    {
-      data_was_read= true;
-    }
-  }
-
-  if (fds[1].revents & POLLRDNORM)
-  {
-    if (stderr_fd.read(_stderr_buffer) == true)
-    {
-      data_was_read= true;
-    }
-  }
-
-  return data_was_read;
-}
-
-std::pair<std::string, std::string> Application::output()
-{
-  slurp();
-  return {
-      std::string {
-          stdout_result().data(),
-          stdout_result().size()
-      },
-      std::string {
-          stderr_result().data(),
-          stderr_result().size()
-      }
-  };
-
-}
-
-Application::error_t Application::join()
-{
-  pid_t waited_pid= waitpid(_pid, &_status, WUNTRACED);
-  slurp();
-  if (waited_pid == _pid and WIFEXITED(_status) == false)
-  {
-    /*
-      What we are looking for here is how the exit status happened.
-      - 127 means that posix_spawn() itself had an error.
-      - If WEXITSTATUS is positive we need to see if it is a signal that we sent to kill the process. If not something bad happened in the process itself. 
-      - Finally something has happened that we don't currently understand.
-    */
-    if (WEXITSTATUS(_status) == 127)
-    {
-      _app_exit_state= Application::INVALID_POSIX_SPAWN;
-      std::string error_string("posix_spawn() failed pid:");
-      error_string+= _pid;
-      error_string+= " name:";
-      error_string+= print_argv(built_argv);
-      if (stderr_result_length())
-      {
-        error_string+= " stderr: ";
-        error_string+= stderr_c_str();
-      }
-      throw std::logic_error(error_string);
-    }
-    else if (WIFSIGNALED(_status))
-    {
-      if (WTERMSIG(_status) != SIGTERM and WTERMSIG(_status) != SIGHUP)
-      {
-        slurp();
-        _app_exit_state= Application::INVALID_POSIX_SPAWN;
-        std::string error_string(print_argv(built_argv));
-        error_string+= " was killed by signal ";
-        error_string+= strsignal(WTERMSIG(_status));
-
-        if (stdout_result_length())
-        {
-          error_string+= " stdout: ";
-          error_string+= stdout_c_str();
-        }
-
-        if (stderr_result_length())
-        {
-          error_string+= " stderr: ";
-          error_string+= stderr_c_str();
-        }
-
-        throw std::runtime_error(error_string);
-      }
-
-      // If we terminted it on purpose then it counts as a success.
-#if defined(DEBUG)
-      if (DEBUG)
-      {
-        Out << "waitpid() application terminated at request"
-          << " pid:" << _pid 
-          << " name:" << built_argv[0];
-      }
-#endif
-    }
-    else
-    {
-      _app_exit_state= Application::UNKNOWN;
-      Error << "Unknown logic state at exit:" << WEXITSTATUS(_status) 
-        << " pid:" << _pid
-        << " name:" << built_argv[0];
-    }
-  }
-  else if (waited_pid == _pid and WIFEXITED(_status))
-  {
-    _app_exit_state= int_to_error_t(WEXITSTATUS(_status));
-  }
-  else if (waited_pid == -1)
-  {
-    std::string error_string;
-    if (stdout_result_length())
-    {
-      error_string+= " stdout: ";
-      error_string+= stdout_c_str();
-    }
-
-    if (stderr_result_length())
-    {
-      error_string+= " stderr: ";
-      error_string+= stderr_c_str();
-    }
-    Error << "waitpid() returned errno:" << strerror(errno) << " " << error_string;
-    _app_exit_state= Application::UNKNOWN;
-  }
-  else
-  {
-    _app_exit_state= Application::UNKNOWN;
-    throw std::logic_error("waitpid() returned an unknown value");
-  }
-
-  return _app_exit_state;
-}
-
-void Application::add_long_option(const std::string& name, const std::string& option_value)
-{
-  std::string arg(name);
-  arg+= option_value;
-  _options.push_back(std::make_pair(arg, std::string()));
-}
-
-void Application::add_option(const std::string& arg)
-{
-  _options.push_back(std::make_pair(arg, std::string()));
-}
-
-void Application::add_option(const std::string& name, const std::string& value)
-{
-  _options.push_back(std::make_pair(name, value));
-}
-
-Application::Pipe::Pipe(int arg) :
-  _std_fd(arg)
-{
-  _pipe_fd[READ]= -1;
-  _pipe_fd[WRITE]= -1;
-  _open[READ]= false;
-  _open[WRITE]= false;
-}
-
-int Application::Pipe::Pipe::fd()
-{
-  if (_std_fd == STDOUT_FILENO)
-  {
-    return _pipe_fd[READ];
-  }
-  else if (_std_fd == STDERR_FILENO)
-  {
-    return _pipe_fd[READ];
-  }
-
-  return _pipe_fd[WRITE]; // STDIN_FILENO
-}
-
-
-bool Application::Pipe::read(libtest::vchar_t& arg)
-{
-  fatal_assert(_std_fd == STDOUT_FILENO or _std_fd == STDERR_FILENO);
-
-  bool data_was_read= false;
-
-  libtest::vchar_t buffer;
-  buffer.resize(1024);
-  ssize_t read_length;
-  while ((read_length= ::read(_pipe_fd[READ], &buffer[0], buffer.size())))
-  {
-    if (read_length == -1)
-    {
-      switch(errno)
-      {
-      case EAGAIN:
-        break;
-
-      default:
-        Error << strerror(errno);
-        break;
-      }
-
-      break;
-    }
-
-    data_was_read= true;
-    arg.reserve(read_length +1);
-    for (size_t x= 0; x < size_t(read_length); ++x)
-    {
-      arg.push_back(buffer[x]);
-    }
-    // @todo Suck up all errput code here
-  }
-
-  return data_was_read;
-}
-
-void Application::Pipe::nonblock()
-{
-  int flags;
-  do 
-  {
-    flags= fcntl(_pipe_fd[READ], F_GETFL, 0);
-  } while (flags == -1 and (errno == EINTR or errno == EAGAIN));
-
-  if (flags == -1)
-  {
-    Error << "fcntl(F_GETFL) " << strerror(errno);
-    throw strerror(errno);
-  }
-
-  int rval;
-  do
-  {
-    rval= fcntl(_pipe_fd[READ], F_SETFL, flags | O_NONBLOCK);
-  } while (rval == -1 and (errno == EINTR or errno == EAGAIN));
-
-  if (rval == -1)
-  {
-    Error << "fcntl(F_SETFL) " << strerror(errno);
-    throw strerror(errno);
-  }
-}
-
-void Application::Pipe::reset()
-{
-  close(READ);
-  close(WRITE);
-
-#ifdef HAVE_PIPE2
-  if (pipe2(_pipe_fd, O_NONBLOCK|O_CLOEXEC) == -1)
-#endif
-  {
-    if (pipe(_pipe_fd) == -1)
-    {
-      FATAL(strerror(errno));
-    }
-
-    // Since either pipe2() was not found/called we set the pipe directly
-    nonblock();
-    cloexec();
-  }
-  _open[0]= true;
-  _open[1]= true;
-}
-
-void Application::Pipe::cloexec()
-{
-  //if (SOCK_CLOEXEC == 0)
-  {
-    if (FD_CLOEXEC) 
-    {
-      int flags;
-      do 
-      {
-        flags= fcntl(_pipe_fd[WRITE], F_GETFD, 0);
-      } while (flags == -1 and (errno == EINTR or errno == EAGAIN));
-
-      if (flags == -1)
-      {
-        Error << "fcntl(F_GETFD) " << strerror(errno);
-        throw strerror(errno);
-      }
-
-      int rval;
-      do
-      { 
-        rval= fcntl(_pipe_fd[WRITE], F_SETFD, flags | FD_CLOEXEC);
-      } while (rval == -1 && (errno == EINTR or errno == EAGAIN));
-
-      if (rval == -1)
-      {
-        Error << "fcntl(F_SETFD) " << strerror(errno);
-        throw strerror(errno);
-      }
-    }
-  }
-}
-
-Application::Pipe::~Pipe()
-{
-  if (_pipe_fd[0] != -1)
-  {
-    ::close(_pipe_fd[0]);
-  }
-
-  if (_pipe_fd[1] != -1)
-  {
-    ::close(_pipe_fd[1]);
-  }
-}
-
-void Application::Pipe::dup_for_spawn(posix_spawn_file_actions_t& file_actions)
-{
-  int type= STDIN_FILENO == _std_fd ? 0 : 1;
-
-  int ret;
-  if ((ret= posix_spawn_file_actions_adddup2(&file_actions, _pipe_fd[type], _std_fd )) < 0)
-  {
-    FATAL("posix_spawn_file_actions_adddup2(%s)", strerror(ret));
-  }
-
-  if ((ret= posix_spawn_file_actions_addclose(&file_actions, _pipe_fd[type])) < 0)
-  {
-    FATAL("posix_spawn_file_actions_addclose(%s)", strerror(ret));
-  }
-}
-
-void Application::Pipe::close(const close_t& arg)
-{
-  int type= int(arg);
-
-  if (_open[type])
-  {
-    if (::close(_pipe_fd[type]) == -1)
-    {
-      Error << "close(" << strerror(errno) << ")";
-    }
-    _open[type]= false;
-    _pipe_fd[type]= -1;
-  }
-}
-
-void Application::create_argv(const char *args[])
-{
-  delete_argv();
-  if (_use_libtool)
-  {
-    assert(libtool());
-    vchar::append(built_argv, libtool());
-    vchar::append(built_argv, "--mode=execute");
-  }
-
-  if (_use_valgrind)
-  {
-    /*
-      valgrind --error-exitcode=1 --leak-check=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE
-    */
-    vchar::append(built_argv, "valgrind");
-    vchar::append(built_argv, "--error-exitcode=1");
-    vchar::append(built_argv, "--leak-check=yes");
-#if 0
-    vchar::append(built_argv, "--show-reachable=yes"));
-#endif
-    vchar::append(built_argv, "--track-fds=yes");
-#if 0
-    built_argv[x++]= strdup("--track-origin=yes");
-#endif
-    vchar::append(built_argv, "--malloc-fill=A5");
-    vchar::append(built_argv, "--free-fill=DE");
-
-    std::string log_file= create_tmpfile("valgrind");
-    libtest::vchar_t buffer;
-    buffer.resize(1024);
-    int length= snprintf(&buffer[0], buffer.size(), "--log-file=%s", log_file.c_str());
-    fatal_assert(length > 0 and size_t(length) < buffer.size());
-    vchar::append(built_argv, &buffer[0]);
-  }
-  else if (_use_ptrcheck)
-  {
-    /*
-      valgrind --error-exitcode=1 --tool=exp-ptrcheck --log-file= 
-    */
-    vchar::append(built_argv, "valgrind");
-    vchar::append(built_argv, "--error-exitcode=1");
-    vchar::append(built_argv, "--tool=exp-ptrcheck");
-    std::string log_file= create_tmpfile("ptrcheck");
-    libtest::vchar_t buffer;
-    buffer.resize(1024);
-    int length= snprintf(&buffer[0], buffer.size(), "--log-file=%s", log_file.c_str());
-    fatal_assert(length > 0 and size_t(length) < buffer.size());
-    vchar::append(built_argv, &buffer[0]);
-  }
-  else if (_use_gdb)
-  {
-    vchar::append(built_argv, "gdb");
-  }
-
-  vchar::append(built_argv, _exectuble_with_path.c_str());
-
-  for (Options::const_iterator iter= _options.begin(); iter != _options.end(); ++iter)
-  {
-    vchar::append(built_argv, (*iter).first.c_str());
-    if ((*iter).second.empty() == false)
-    {
-      vchar::append(built_argv, (*iter).second.c_str());
-    }
-  }
-
-  if (args)
-  {
-    for (const char **ptr= args; *ptr; ++ptr)
-    {
-      vchar::append(built_argv, *ptr);
-    }
-  }
-  built_argv.push_back(nullptr);
-}
-
-std::string Application::print()
-{
-  return print_argv(built_argv);
-}
-
-std::string Application::arguments()
-{
-  std::stringstream arg_buffer;
-
-  // Skip printing out the libtool reference
-  for (size_t x= _use_libtool ? 2 : 0; x < _argc; ++x)
-  {
-    if (built_argv[x])
-    {
-      arg_buffer << built_argv[x] << " ";
-    }
-  }
-
-  return arg_buffer.str();
-}
-
-void Application::delete_argv()
-{
-  std::for_each(built_argv.begin(), built_argv.end(), FreeFromVector());
-
-  built_argv.clear();
-  _argc= 0;
-}
-
-
-int exec_cmdline(const std::string& command, const char *args[], bool use_libtool)
-{
-  Application app(command, use_libtool);
-
-  Application::error_t ret= app.run(args);
-
-  if (Application::SUCCESS == ret) {
-    ret = app.join();
-  }
-
-  if (ret != Application::SUCCESS)
-  {
-    auto out = app.output();
-    Error << command << " stdout: " << out.first;
-    Error << command << " stderr: " << out.second;
-  }
-
-  return int(ret);
-}
-
-} // namespace exec_cmdline
diff --git a/libtest/cmdline.h b/libtest/cmdline.h
deleted file mode 100644 (file)
index 244c646..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <spawn.h>
-
-// http://www.gnu.org/software/automake/manual/automake.html#Using-the-TAP-test-protocol
-#ifndef EXIT_SKIP
-# define EXIT_SKIP 77
-#endif
-
-#ifndef EXIT_FATAL
-# define EXIT_FATAL 99
-#endif
-
-#ifndef EX_NOEXEC
-# define EX_NOEXEC 126
-#endif
-
-#ifndef EX_NOTFOUND
-# define EX_NOTFOUND 127
-#endif
-
-namespace libtest {
-
-class Application {
-private:
-  typedef std::vector< std::pair<std::string, std::string> > Options;
-
-public:
-
-  enum error_t {
-    SUCCESS= EXIT_SUCCESS,
-    FAILURE= EXIT_FAILURE,
-    UNINITIALIZED,
-    SIGTERM_KILLED,
-    UNKNOWN,
-    UNKNOWN_SIGNAL,
-    INVALID_POSIX_SPAWN= 127
-  };
-
-  static const char* toString(error_t arg)
-  {
-    switch (arg)
-    {
-    case Application::SUCCESS:
-      return "EXIT_SUCCESS";
-
-    case Application::UNINITIALIZED:
-      return "UNINITIALIZED";
-
-    case Application::SIGTERM_KILLED:
-      return "Exit happened via SIGTERM";
-
-    case Application::FAILURE:
-      return "EXIT_FAILURE";
-
-    case Application::UNKNOWN_SIGNAL:
-      return "Exit happened via a signal which was not SIGTERM";
-
-    case Application::INVALID_POSIX_SPAWN:
-      return "127: Invalid call to posix_spawn()";
-
-    case Application::UNKNOWN:
-    default:
-      break;
-    }
-
-    return "EXIT_UNKNOWN";
-  }
-
-  class Pipe {
-  public:
-    Pipe(int);
-    ~Pipe();
-
-    int fd();
-
-    enum close_t {
-      READ= 0,
-      WRITE= 1
-    };
-
-    void reset();
-    void close(const close_t& arg);
-    void dup_for_spawn(posix_spawn_file_actions_t& file_actions);
-
-    void nonblock();
-    void cloexec();
-    bool read(libtest::vchar_t&);
-
-  private:
-    const int _std_fd;
-    int _pipe_fd[2];
-    bool _open[2];
-  };
-
-public:
-  Application(const std::string& arg, const bool _use_libtool_arg= false);
-
-  virtual ~Application();
-
-  void add_option(const std::string&);
-  void add_option(const std::string&, const std::string&);
-  void add_long_option(const std::string& option_name, const std::string& option_value);
-  error_t run(const char *args[]= NULL);
-  Application::error_t join();
-
-  libtest::vchar_t stdout_result() const
-  {
-    return _stdout_buffer;
-  }
-
-  size_t stdout_result_length() const
-  {
-    return _stdout_buffer.size();
-  }
-
-  const char* stdout_c_str() const
-  {
-    return &_stdout_buffer[0];
-  }
-
-  libtest::vchar_t stderr_result() const
-  {
-    return _stderr_buffer;
-  }
-
-  const char* stderr_c_str() const
-  {
-    return &_stderr_buffer[0];
-  }
-
-  size_t stderr_result_length() const
-  {
-    return _stderr_buffer.size();
-  }
-
-  std::string print();
-
-  void use_valgrind(bool arg)
-  {
-    _use_valgrind= arg;
-  }
-
-  bool check() const;
-
-  bool slurp();
-  std::pair<std::string, std::string> output();
-  void murder();
-
-  void clear()
-  {
-    slurp();
-    _stdout_buffer.clear();
-    _stderr_buffer.clear();
-  }
-
-  void use_gdb(bool arg)
-  {
-    _use_gdb= arg;
-  }
-
-  void use_ptrcheck(bool arg)
-  {
-    _use_ptrcheck= arg;
-  }
-
-  std::string arguments();
-
-  std::string gdb_filename()
-  {
-    return  _gdb_filename;
-  }
-
-  pid_t pid() const
-  {
-    return _pid;
-  }
-
-  void will_fail()
-  {
-    _will_fail= true;
-  }
-
-private:
-  void create_argv(const char *args[]);
-  void delete_argv();
-  void add_to_build_argv(const char*);
-
-private:
-  const bool _use_libtool;
-  bool _use_valgrind;
-  bool _use_gdb;
-  bool _use_ptrcheck;
-  bool _will_fail;
-  size_t _argc;
-  std::string _exectuble_name;
-  std::string _exectuble;
-  std::string _exectuble_with_path;
-  std::string _gdb_filename;
-  Options _options;
-  Pipe stdin_fd;
-  Pipe stdout_fd;
-  Pipe stderr_fd;
-  libtest::vchar_ptr_t built_argv;
-  pid_t _pid;
-  libtest::vchar_t _stdout_buffer;
-  libtest::vchar_t _stderr_buffer;
-  int _status;
-  pthread_t _thread;
-  error_t _app_exit_state;
-};
-
-static inline std::ostream& operator<<(std::ostream& output, const enum Application::error_t &arg)
-{
-  return output << Application::toString(arg);
-}
-
-int exec_cmdline(const std::string& executable, const char *args[], bool use_libtool= false);
-
-}
diff --git a/libtest/collection.cc b/libtest/collection.cc
deleted file mode 100644 (file)
index ff9c886..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include <libtest/common.h>
-
-// @todo possibly have this code fork off so if it fails nothing goes bad
-static test_return_t runner_code(libtest::Framework* frame,
-                                 test_st* run, 
-                                 libtest::Timer& _timer)
-{ // Runner Code
-
-  assert(frame->runner());
-  assert(run->test_fn);
-
-  test_return_t return_code;
-  try 
-  {
-    _timer.reset();
-    assert(frame);
-    assert(frame->runner());
-    assert(run->test_fn);
-    return_code= frame->runner()->main(run->test_fn, frame->creators_ptr());
-  }
-  // Special case where check for the testing of the exception
-  // system.
-  catch (const libtest::fatal& e)
-  {
-    if (libtest::fatal::is_disabled())
-    {
-      libtest::fatal::increment_disabled_counter();
-      return_code= TEST_SUCCESS;
-    }
-    else
-    {
-      throw;
-    }
-  }
-
-  _timer.sample();
-
-  return return_code;
-}
-
-namespace libtest {
-
-Collection::Collection(Framework* frame_arg,
-                       collection_st* arg) :
-  _name(arg->name),
-  _pre(arg->pre),
-  _post(arg->post),
-  _tests(arg->tests),
-  _frame(frame_arg),
-  _success(0),
-  _skipped(0),
-  _failed(0),
-  _total(0),
-  _formatter(frame_arg->name(), _name)
-{
-  fatal_assert(arg);
-}
-
-test_return_t Collection::exec()
-{
-  if (test_success(_frame->runner()->setup(_pre, _frame->creators_ptr())))
-  {
-    for (test_st *run= _tests; run->name; run++)
-    {
-      formatter()->push_testcase(run->name);
-      if (_frame->match(run->name))
-      {
-        formatter()->skipped();
-        continue;
-      }
-      _total++;
-
-      test_return_t return_code;
-      try 
-      {
-        if (run->requires_flush)
-        {
-          if (test_failed(_frame->runner()->flush(_frame->creators_ptr())))
-          {
-            Error << "frame->runner()->flush(creators_ptr)";
-            _skipped++;
-            formatter()->skipped();
-            continue;
-          }
-        }
-
-        set_alarm();
-
-        try 
-        {
-          return_code= runner_code(_frame, run, _timer);
-        }
-        catch (...)
-        {
-          cancel_alarm();
-
-          throw;
-        }
-        libtest::cancel_alarm();
-      }
-      catch (const libtest::fatal& e)
-      {
-        _failed++;
-        formatter()->failed();
-        stream::make_cerr err(e.file(), e.line(), e.func());
-        err << e.what();
-        for (auto server : _frame->servers().servers)
-        {
-          auto output = server->output();
-          if (output.first.size())
-          {
-            err << "Server(" << server->port() << ") stdout:\n" << output.first << "\n";
-          }
-          if (output.second.size())
-          {
-            err << "Server(" << server->port() << ") stderr:\n" << output.second << "\n";
-          }
-        }
-        throw;
-      }
-
-      switch (return_code)
-      {
-      case TEST_SUCCESS:
-        _success++;
-        formatter()->success(_timer);
-        break;
-
-      case TEST_FAILURE:
-        _failed++;
-        formatter()->failed();
-        for (auto server : _frame->servers().servers)
-        {
-          auto output = server->output();
-          if (output.first.size())
-          {
-            Out << "Server(" << server->port() << ") stdout:\n" << output.first << "\n";
-          }
-          if (output.second.size())
-          {
-            Out << "Server(" << server->port() << ") stderr:\n" << output.second << "\n";
-          }
-        }
-        break;
-
-      case TEST_SKIPPED:
-        _skipped++;
-        formatter()->skipped();
-        break;
-
-      default:
-        FATAL("invalid return code");
-      }
-#if 0
-      @TODO add code here to allow for a collection to define a method to reset to allow tests to continue.
-#endif
-    }
-
-    (void) _frame->runner()->teardown(_post, _frame->creators_ptr());
-  }
-
-  if (_failed == 0 and _skipped == 0 and _success)
-  {
-    return TEST_SUCCESS;
-  }
-
-  if (_failed)
-  {
-    return TEST_FAILURE;
-  }
-
-  fatal_assert(_skipped or _success == 0);
-
-  return TEST_SKIPPED;
-}
-
-} // namespace libtest
-
diff --git a/libtest/collection.h b/libtest/collection.h
deleted file mode 100644 (file)
index a9f9cba..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <libtest/formatter.hpp>
-
-#include <libtest/timer.hpp>
-
-namespace { class Framework; }
-
-
-/**
-  A structure which describes a collection of test cases.
-*/
-struct collection_st {
-  const char *name;
-  test_callback_fn *pre;
-  test_callback_fn *post;
-  struct test_st *tests;
-};
-
-namespace libtest {
-
-class Collection {
-public:
-  Collection(libtest::Framework*, collection_st*);
-
-  test_return_t exec();
-
-  const char* name()
-  {
-    return _name.c_str();
-  }
-
-  uint32_t success()
-  {
-    return _success;
-  }
-
-  uint32_t skipped()
-  {
-    return _skipped;
-  }
-
-  uint32_t failed()
-  {
-    return _failed;
-  }
-
-  uint32_t total()
-  {
-    return _total;
-  }
-
-  libtest::Formatter* formatter()
-  {
-    return &_formatter;
-  }
-
-private:
-  std::string _name;
-  test_callback_fn *_pre;
-  test_callback_fn *_post;
-  struct test_st *_tests;
-  libtest::Framework* _frame;
-  uint32_t _success;
-  uint32_t _skipped;
-  uint32_t _failed;
-  uint32_t _total;
-  libtest::Timer _timer;
-  libtest::Formatter _formatter;
-
-private:
-  Collection( const Collection& );
-  const Collection& operator=( const Collection& );
-};
-
-} // namespace libtest
diff --git a/libtest/common.h b/libtest/common.h
deleted file mode 100644 (file)
index 90d8b6a..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-/*
-  Common include file for libtest
-*/
-
-#pragma once
-
-#include <cassert>
-#include <cerrno>
-#include <cstdlib>
-#include <sstream>
-#include <string>
-
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#endif
-
-#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-
-#ifdef HAVE_SYS_RESOURCE_H 
-# include <sys/resource.h> 
-#endif
-#ifdef HAVE_FNMATCH_H
-# include <fnmatch.h>
-#endif
-
-#ifdef HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif
-
-#if defined(WIN32)
-# include "win32/wrappers.h"
-# define get_socket_errno() WSAGetLastError()
-#else
-# ifdef HAVE_UNISTD_H
-#  include <unistd.h>
-# endif
-# define INVALID_SOCKET -1
-# define SOCKET_ERROR -1
-# define closesocket(a) close(a)
-# define get_socket_errno() errno
-#endif
-
-#include <libtest/test.hpp>
-
-#include <libtest/is_pid.hpp>
-
-#include <libtest/gearmand.h>
-#include <libtest/blobslap_worker.h>
-#include <libtest/memcached.h>
-#include <libtest/drizzled.h>
-
-#include <libtest/libtool.hpp>
-#include <libtest/killpid.h>
-#include <libtest/signal.h>
-#include <libtest/dns.hpp>
-#include <libtest/formatter.hpp>
-
-struct FreeFromVector
-{
-  template <class T>
-    void operator() ( T* ptr) const
-    {
-      if (ptr)
-      {
-        free(ptr);
-        ptr= NULL;
-      }
-    }
-};
-
-struct DeleteFromVector
-{
-  template <class T>
-    void operator() ( T* ptr) const
-    {
-      delete ptr;
-      ptr= NULL;
-    }
-};
diff --git a/libtest/comparison.cc b/libtest/comparison.cc
deleted file mode 100644 (file)
index c0c2193..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-namespace libtest {
-
-bool jenkins_is_caller(void)
-{
-  if (bool(getenv("JENKINS_HOME")))
-  {
-    return true;
-  }
-
-  return false;
-}
-
-bool gdb_is_caller(void)
-{
-  if (bool(getenv("LOG_COMPILER")) and strstr(getenv("LOG_COMPILER"), "gdb"))
-  {
-    return true;
-  }
-
-  if (bool(getenv("LIBTEST_IN_GDB")))
-  {
-    return true;
-  }
-
-  return false;
-}
-
-bool helgrind_is_caller(void)
-{
-  if (bool(getenv("LOG_COMPILER")) and strstr(getenv("LOG_COMPILER"), "helgrind"))
-  {
-    return true;
-  }
-
-  return false;
-}
-
-bool _in_valgrind(const char*, int, const char*)
-{
-  if (valgrind_is_caller())
-  {
-    return true;
-  }
-
-  return false;
-}
-
-} // namespace libtest
diff --git a/libtest/comparison.hpp b/libtest/comparison.hpp
deleted file mode 100644 (file)
index 9a7d81c..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <typeinfo>
-
-#if defined(HAVE_LIBMEMCACHED) && HAVE_LIBMEMCACHED
-#include <libmemcached-1.0/memcached.h>
-#include <libmemcachedutil-1.0/ostream.hpp>
-#include <libtest/memcached.hpp>
-#endif
-
-#if defined(HAVE_LIBGEARMAN) && HAVE_LIBGEARMAN
-#include <libgearman-1.0/ostream.hpp>
-#endif
-
-namespace libtest {
-
-LIBTEST_API
-bool jenkins_is_caller(void);
-
-LIBTEST_API
-bool gdb_is_caller(void);
-
-LIBTEST_API
-bool _in_valgrind(const char *file, int line, const char *func);
-
-LIBTEST_API
-bool helgrind_is_caller(void);
-
-template <class T_comparable>
-bool _compare_truth(const char *file, int line, const char *func, T_comparable __expected, const char *assertation_label)
-{
-  if (__expected == false)
-  {
-    libtest::stream::make_cerr(file, line, func) << "Assertation  \"" << assertation_label << "\"";
-    return false;
-  }
-
-  return true;
-}
-
-template <class T1_comparable, class T2_comparable>
-bool _compare(const char *file, int line, const char *func, const T1_comparable& __expected, const T2_comparable& __actual, bool use_io)
-{
-  if (__expected != __actual)
-  {
-    if (use_io)
-    {
-      libtest::stream::make_cerr(file, line, func) << "Expected \"" << __expected << "\" got \"" << __actual << "\"";
-    }
-
-    return false;
-  }
-
-  return true;
-}
-
-template <class T1_comparable, class T2_comparable>
-bool _compare_strcmp(const char *file, int line, const char *func, const T1_comparable *__expected, const T2_comparable *__actual)
-{
-  if (__expected == NULL)
-  {
-    FATAL("Expected value was NULL, programmer error");
-  }
-
-  if (__actual == NULL)
-  {
-    libtest::stream::make_cerr(file, line, func) << "Expected " << __expected << " but got NULL";
-    return false;
-  }
-
-  if (strncmp(__expected, __actual, strlen(__expected)))
-  {
-    libtest::stream::make_cerr(file, line, func) << "Expected " << __expected << " passed \"" << __actual << "\"";
-    return false;
-  }
-
-  return true;
-}
-
-template <class T_comparable>
-bool _compare_zero(const char *file, int line, const char *func, T_comparable __actual)
-{
-  if (T_comparable(0) != __actual)
-  {
-    libtest::stream::make_cerr(file, line, func) << "Expected 0 got \"" << __actual << "\"";
-    return false;
-  }
-
-  return true;
-}
-
-template <class T1_comparable, class T2_comparable>
-bool _ne_compare(const char *file, int line, const char *func, T1_comparable __expected, T2_comparable __actual, bool io_error= true)
-{
-  if (__expected == __actual)
-  {
-    if (io_error)
-    {
-      libtest::stream::make_cerr(file, line, func) << "Expected \"" << __expected << "\" got \"" << __actual << "\"";
-    }
-
-    return false;
-  }
-
-  return true;
-}
-
-template <class T_comparable, class T_expression_string>
-bool _assert_truth(const char *file, int line, const char *func, T_comparable __truth, T_expression_string __expression, const char* __explain= NULL)
-{
-  if (__truth)
-  {
-    return true;
-  }
-
-  if (__explain)
-  {
-    libtest::stream::make_cerr(file, line, func) << "Assertion \"" << __expression << "\" warning:" << __explain;
-  }
-
-  return false;
-}
-
-} // namespace libtest
diff --git a/libtest/core.cc b/libtest/core.cc
deleted file mode 100644 (file)
index 2542f43..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-
-namespace libtest {
-
-void create_core(void)
-{
-#if defined(__APPLE__) && __APPLE__
-  if (__APPLE__)
-  {
-    return;
-  }
-#endif
-  if (getenv("YATL_COREDUMP"))
-  {
-    pid_t pid= fork();
-
-    if (pid == 0)
-    {
-      abort();
-    }
-    else
-    {
-      while (waitpid(pid, NULL, 0) != pid) {};
-    }
-  }
-}
-
-} // namespace libtest
diff --git a/libtest/core.h b/libtest/core.h
deleted file mode 100644 (file)
index 654fcaf..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-LIBTEST_API
-void create_core(void);
-
-} // namespace libtest
diff --git a/libtest/core_count.cc b/libtest/core_count.cc
deleted file mode 100644 (file)
index 36ebc22..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include <cstdlib>
-#include <fcntl.h>
-#include <getopt.h>
-#include <iostream>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <libtest/cpu.hpp>
-
-static void version_command(const char *command_name, int major_version, int minor_version)
-{
-  std::cout << command_name << " " << major_version << "." << minor_version << std::endl;
-}
-
-static void help_command(const char *command_name,
-                         int major_version, int minor_version,
-                         const struct option *long_options)
-{
-  std::cout << command_name << " " << major_version << "." << minor_version << std::endl;
-  std::cout << "Prints the number of cores found on the local host." << std::endl << std::endl;
-
-  for (uint32_t x= 0; long_options[x].name; x++)
-  {
-    std::cout << "\t --" << long_options[x].name << char(long_options[x].has_arg ? '=' : ' ') << std::endl;
-  }
-
-  std::cout << std::endl;
-}
-
-enum {
-  OPT_HELP,
-  OPT_VERSION
-};
-
-static void options_parse(int argc, char *argv[])
-{
-  static struct option long_options[]=
-  {
-    { "version", no_argument, NULL, OPT_VERSION},
-    { "help", no_argument, NULL, OPT_HELP},
-    {0, 0, 0, 0},
-  };
-
-  bool opt_version= false;
-  bool opt_help= false;
-  int option_index= 0;
-
-  while (1)
-  {
-    int option_rv= getopt_long(argc, argv, "", long_options, &option_index);
-    if (option_rv == -1) 
-    {
-      break;
-    }
-
-    switch (option_rv)
-    {
-    case OPT_HELP: /* --help or -h */
-      opt_help= true;
-      break;
-
-    case OPT_VERSION: /* --version or -v */
-      opt_version= true;
-      break;
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(EXIT_FAILURE);
-
-    default:
-      help_command(argv[0], 1, 0, long_options);
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  if (opt_version)
-  {
-    version_command(argv[0], 1, 0);
-    exit(EXIT_SUCCESS);
-  }
-
-  if (opt_help)
-  {
-    help_command(argv[0], 1, 0, long_options);
-    exit(EXIT_SUCCESS);
-  }
-}
-
-int main(int argc, char *argv[])
-{
-  options_parse(argc, argv);
-
-  std::cout << libtest::number_of_cpus() << std::endl;
-
-  return EXIT_SUCCESS;
-}
diff --git a/libtest/cpu.cc b/libtest/cpu.cc
deleted file mode 100644 (file)
index c62d6c2..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-#include <unistd.h>
-
-#pragma GCC diagnostic ignored "-Wundef"
-
-#if defined(HAVE_LINUX_SYSCTL_H) && HAVE_LINUX_SYSCTL_H
-#include <linux/sysctl.h>
-#elif defined(HAVE_SYS_SYSCTL_H) && HAVE_SYS_SYSCTL_H
-#include <sys/sysctl.h>
-#endif
-
-namespace libtest {
-
-size_t number_of_cpus()
-{
-  size_t number_of_cpu= 1;
-#if defined(__linux) && __linux
-  number_of_cpu= sysconf(_SC_NPROCESSORS_ONLN);
-#elif defined(HAVE_SYS_SYSCTL_H) && defined(CTL_HW) && defined(HW_NCPU) && defined(HW_AVAILCPU) && defined(HW_NCPU)
-  int mib[4];
-  size_t len= sizeof(number_of_cpu); 
-
-  /* set the mib for hw.ncpu */
-  mib[0] = CTL_HW;
-  mib[1] = HW_AVAILCPU;  // alternatively, try HW_NCPU;
-
-  /* get the number of CPUs from the system */
-  sysctl(mib, 2, &number_of_cpu, &len, NULL, 0);
-
-  if (number_of_cpu < 1) 
-  {
-    mib[1]= HW_NCPU;
-    sysctl(mib, 2, &number_of_cpu, &len, NULL, 0 );
-
-    if (number_of_cpu < 1 )
-    {
-      number_of_cpu = 1;
-    }
-  }
-#else
- // Guessing number of CPU
-#endif
-
-  return number_of_cpu;
-}
-
-} // namespace libtest
diff --git a/libtest/cpu.hpp b/libtest/cpu.hpp
deleted file mode 100644 (file)
index 4127709..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-size_t number_of_cpus();
-
-} // namespace libtest
diff --git a/libtest/dns.cc b/libtest/dns.cc
deleted file mode 100644 (file)
index 75a5bbf..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-namespace libtest {
-
-bool lookup(const char* host)
-{
-  bool success= false;
-  assert(host and host[0]);
-  if (host and host[0])
-  {
-    struct addrinfo *addrinfo= NULL;
-    struct addrinfo hints;
-    memset(&hints, 0, sizeof(hints));
-    hints.ai_socktype= SOCK_STREAM;
-    hints.ai_protocol= IPPROTO_TCP;
-
-    int limit= 5;
-    while (--limit and success == false)
-    {
-      if (addrinfo)
-      {
-        freeaddrinfo(addrinfo);
-        addrinfo= NULL;
-      }
-
-      int ret;
-      if ((ret= getaddrinfo(host, "echo", &hints, &addrinfo)) == 0)
-      {
-        success= true;
-        break;
-      }
-
-      switch (ret)
-      {
-      case EAI_AGAIN:
-        continue;
-
-      case EAI_NONAME:
-      default:
-        break;
-      }
-
-      break;
-    }
-
-    if (addrinfo)
-    {
-      freeaddrinfo(addrinfo);
-    }
-  }
-
-  return success;
-}
-
-
-bool check_dns()
-{
-  if (valgrind_is_caller())
-  {
-    return false;
-  }
-
-  if (lookup("exist.gearman.info") == false)
-  {
-    return false;
-  }
-
-  if (lookup("does_not_exist.gearman.info")) // This should fail, if it passes,...
-  {
-    fatal_assert("Your service provider sucks and is providing bogus DNS. You might be in an airport.");
-  }
-
-  return true;
-}
-
-} // namespace libtest
-
diff --git a/libtest/dns.hpp b/libtest/dns.hpp
deleted file mode 100644 (file)
index 438a922..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-bool check_dns();
-bool lookup(const char*);
-
-} // namespace libtest
diff --git a/libtest/dream.cc b/libtest/dream.cc
deleted file mode 100644 (file)
index 42f9222..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-namespace libtest {
-
-void dream(time_t tv_sec, long tv_nsec)
-{
-#if defined(WIN32)
-  if (tv_sec == 0 and tv_nsec)
-  {
-    tv_sec++;
-  }
-  sleep(tv_sec);
-#else
-  struct timespec requested;
-  requested.tv_sec= tv_sec;
-  requested.tv_nsec= tv_nsec;
-  nanosleep(&requested, NULL);
-#endif
-}
-
-}
diff --git a/libtest/dream.h b/libtest/dream.h
deleted file mode 100644 (file)
index 41cabaf..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-void dream(time_t tv_sec, long tv_nsec= 0);
-
-}
-
diff --git a/libtest/drizzled.cc b/libtest/drizzled.cc
deleted file mode 100644 (file)
index 3a93b66..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-#include <libtest/drizzled.h>
-
-#include "util/instance.hpp"
-#include "util/operation.hpp"
-
-using namespace datadifferential;
-using namespace libtest;
-
-#include <cassert>
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <iostream>
-#include <signal.h>
-#include <sstream>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
-
-#if defined(HAVE_LIBDRIZZLE) && HAVE_LIBDRIZZLE
-# include <libdrizzle-5.1/drizzle_client.h>
-#endif
-
-using namespace libtest;
-
-namespace libtest {
-bool ping_drizzled(const in_port_t _port)
-{
-  (void)(_port);
-#if defined(HAVE_LIBDRIZZLE) && HAVE_LIBDRIZZLE
-  if (HAVE_LIBDRIZZLE)
-  {
-    drizzle_st *drizzle= drizzle_create(getenv("MYSQL_SERVER"),
-                                        getenv("MYSQL_PORT") ? atoi("MYSQL_PORT") : DRIZZLE_DEFAULT_TCP_PORT,
-                                        getenv("MYSQL_USER"),
-                                        getenv("MYSQL_PASSWORD"),
-                                        getenv("MYSQL_SCHEMA"), 0);
-
-    if (drizzle == NULL)
-    {
-      return false;
-    }
-
-    bool success= false;
-
-    drizzle_return_t rc;
-    if ((rc= drizzle_connect(drizzle)) == DRIZZLE_RETURN_OK)
-    {
-      drizzle_result_st *result= drizzle_ping(drizzle, &rc);
-      success= bool(result);
-      drizzle_result_free(result);
-    }
-
-    if (success == true)
-    { }
-    else if (rc != DRIZZLE_RETURN_OK)
-    {
-      Error << drizzle_error(drizzle) << " localhost:" << _port;
-    }
-
-    drizzle_quit(drizzle);
-
-    return success;
-  }
-#endif
-
-  return false;
-}
-} // namespace libtest
-
-class Drizzle : public libtest::Server
-{
-private:
-public:
-  Drizzle(const std::string& host_arg, in_port_t port_arg) :
-    libtest::Server(host_arg, port_arg, DRIZZLED_BINARY, false)
-  {
-    set_pid_file();
-  }
-
-  bool ping()
-  {
-    size_t limit= 5;
-    while (_app.check() and --limit)
-    {
-      if (ping_drizzled(_port))
-      {
-        return true;
-      }
-      libtest::dream(1, 0);
-    }
-
-    return false;
-  }
-
-  const char *name()
-  {
-    return "drizzled";
-  };
-
-  void log_file_option(Application&, const std::string&)
-  {
-  }
-
-  bool has_log_file_option() const
-  {
-    return true;
-  }
-
-  bool broken_pid_file()
-  {
-    return true;
-  }
-
-  bool is_libtool()
-  {
-    return false;
-  }
-
-  bool has_syslog() const
-  {
-    return true;
-  }
-
-  bool has_port_option() const
-  {
-    return true;
-  }
-
-  void port_option(Application& app, in_port_t arg)
-  {
-    if (arg > 0)
-    {
-      libtest::vchar_t buffer;
-      buffer.resize(1024);
-      snprintf(&buffer[1024], buffer.size(), "--drizzle-protocol.port=%d", int(arg));
-      app.add_option(&buffer[1024]);
-    }
-  }
-
-  bool build();
-};
-
-bool Drizzle::build()
-{
-  if (getuid() == 0 or geteuid() == 0)
-  {
-    add_option("--user=root");
-  }
-
-  add_option("--verbose=INSPECT");
-#if 0
-  add_option("--datadir=var/drizzle");
-#endif
-
-  return true;
-}
-
-namespace libtest {
-
-libtest::Server *build_drizzled(const char *hostname, in_port_t try_port)
-{
-  return new Drizzle(hostname, try_port);
-}
-
-}
diff --git a/libtest/drizzled.h b/libtest/drizzled.h
deleted file mode 100644 (file)
index c3e3055..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <arpa/inet.h>
-
-namespace libtest { struct Server; }
-
-namespace libtest {
-
-libtest::Server *build_drizzled(const char *hostname, in_port_t try_port);
-
-bool ping_drizzled(const in_port_t);
-
-}
-
diff --git a/libtest/error.h b/libtest/error.h
deleted file mode 100644 (file)
index f567d2a..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-enum test_return_t {
-  TEST_SUCCESS,
-  TEST_FAILURE,
-  TEST_SKIPPED
-};
-
-
-static inline bool test_success(test_return_t rc)
-{
-  return (rc == TEST_SUCCESS);
-}
-
-static inline bool test_failed(test_return_t rc)
-{
-  return (rc != TEST_SUCCESS);
-}
diff --git a/libtest/exception.cc b/libtest/exception.cc
deleted file mode 100644 (file)
index 0b18f77..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-#include <cstdarg>
-
-namespace libtest {
-
-exception::exception(const char *file_arg, int line_arg, const char *func_arg):
-  std::exception(),
-  _line(line_arg),
-  _file(file_arg),
-  _func(func_arg),
-  _error_message(NULL),
-  _error_message_size(0)
-{
-}
-
-#ifndef __INTEL_COMPILER
-# pragma GCC diagnostic ignored "-Wformat-nonliteral"
-#endif
-void exception::init(va_list args_)
-{
-  const char *format= va_arg(args_, const char *);
-  int error_message_length= vasprintf(&_error_message, format, args_);
-  assert(error_message_length != -1);
-  if (error_message_length > 0)
-  {
-    _error_message_size= error_message_length +1;
-  }
-}
-
-exception::~exception() throw()
-{
-  if (_error_message)
-  {
-    free(_error_message);
-  }
-}
-
-void exception::what(size_t length_, const char* message_)
-{
-  if (length_ > 0 and message_)
-  {
-    char *ptr= (char*) realloc(_error_message, length_ +1);
-    if (ptr)
-    {
-      _error_message= ptr;
-      memcpy(_error_message, message_, length_);
-      _error_message[length_]= 0;
-    }
-  }
-}
-
-exception::exception(const exception& other) :
-  std::exception(),
-  _line(other._line),
-  _file(other._file),
-  _func(other._func),
-  _error_message_size(0)
-{
-  if (other.length() > 0)
-  {
-    _error_message= (char*) malloc(other.length() +1);
-    if (_error_message)
-    {
-      memcpy(_error_message, other._error_message, other.length());
-      _error_message_size= other.length();
-    }
-  }
-}
-
-} // namespace libtest
-
diff --git a/libtest/exception.hpp b/libtest/exception.hpp
deleted file mode 100644 (file)
index 3d20e8b..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-class exception : public std::exception
-{
-public:
-  exception(const char *file, int line, const char *func);
-
-  exception( const exception& );
-
-  virtual ~exception() throw();
-
-  virtual const char* what() const throw()
-  {
-    if (_error_message)
-    {
-      return _error_message;
-    }
-
-    return "";
-  }
-
-  void what(size_t, const char*);
-
-  size_t length() const
-  {
-    return _error_message_size;
-  }
-
-  int line() const
-  {
-    return _line;
-  }
-
-  const char* file() const
-  {
-    return _file;
-  }
-
-  const char* func() const
-  {
-    return _func;
-  }
-
-protected:
-  void init(va_list);
-
-private:
-  int _line;
-  const char*  _file;
-  const char* _func;
-  char* _error_message;
-  size_t _error_message_size;
-};
-
-} // namespace libtest
-
diff --git a/libtest/exception/disconnected.hpp b/libtest/exception/disconnected.hpp
deleted file mode 100644 (file)
index 6e9f4c4..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include "libtest/exception.hpp"
-
-namespace libtest {
-
-class disconnected : public libtest::exception
-{
-public:
-  disconnected(const char *file, int line, const char *func, const std::string&, const unsigned port, ...);
-
-  disconnected(const disconnected&);
-
-  // The following are just for unittesting the exception class
-  static bool is_disabled();
-  static void disable();
-  static void enable();
-  static uint32_t disabled_counter();
-  static void increment_disabled_counter();
-
-private:
-  in_port_t _port;
-  char _instance[BUFSIZ];
-};
-
-} // namespace libtest
diff --git a/libtest/exception/fatal.cc b/libtest/exception/fatal.cc
deleted file mode 100644 (file)
index 5a3bab5..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-#include "libtest/exception.hpp"
-#include <cstdarg>
-
-namespace libtest {
-
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
-
-fatal::fatal(const char *file_arg, int line_arg, const char *func_arg, ...) :
-  libtest::exception(file_arg, line_arg, func_arg)
-{
-  va_list args;
-  va_start(args, func_arg);
-  init(args);
-  va_end(args);
-}
-
-fatal::fatal( const fatal& other ) :
-  libtest::exception(other)
-{
-}
-
-static bool _disabled= false;
-static uint32_t _counter= 0;
-
-bool fatal::is_disabled() throw()
-{
-  return _disabled;
-}
-
-void fatal::disable() throw()
-{
-  _counter= 0;
-  _disabled= true;
-}
-
-void fatal::enable() throw()
-{
-  _counter= 0;
-  _disabled= false;
-}
-
-uint32_t fatal::disabled_counter() throw()
-{
-  return _counter;
-}
-
-void fatal::increment_disabled_counter() throw()
-{
-  _counter++;
-}
-
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
-disconnected::disconnected(const char *file_arg, int line_arg, const char *func_arg,
-                           const std::string& instance, const unsigned port, ...) :
-  libtest::exception(file_arg, line_arg, func_arg),
-  _port(port)
-{
-  va_list args;
-  va_start(args, port);
-  const char *format= va_arg(args, const char *);
-  char last_error[BUFSIZ];
-  (void)vsnprintf(last_error, sizeof(last_error), format, args);
-  va_end(args);
-
-  char buffer_error[BUFSIZ];
-  int error_length= snprintf(buffer_error, sizeof(buffer_error), "%s:%u %s", instance.c_str(), uint32_t(port), last_error);
-
-  if (error_length > 0)
-  {
-    what(size_t(error_length), buffer_error);
-  }
-}
-
-disconnected::disconnected(const disconnected& other):
-  libtest::exception(other),
-  _port(other._port)
-{
-  strncpy(_instance, other._instance, BUFSIZ);
-}
-
-} // namespace libtest
diff --git a/libtest/exception/fatal.hpp b/libtest/exception/fatal.hpp
deleted file mode 100644 (file)
index 5ee1aac..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-class fatal : public libtest::exception
-{
-public:
-  fatal(const char *file, int line, const char *func, ...);
-
-  fatal(const fatal&);
-
-  // The following are just for unittesting the exception class
-  static bool is_disabled() throw();
-  static void disable() throw();
-  static void enable() throw();
-  static uint32_t disabled_counter() throw();
-  static void increment_disabled_counter() throw();
-
-  test_return_t return_code() const
-  {
-    return TEST_SKIPPED;
-  }
-
-private:
-};
-
-} // namespace libtest
-
-#define FATAL(...) \
-do \
-{ \
-  throw libtest::fatal(LIBYATL_DEFAULT_PARAM, __VA_ARGS__); \
-} while (0)
-
-#define FATAL_IF(__expression, ...) \
-do \
-{ \
-  if ((__expression)) { \
-    throw libtest::fatal(LIBYATL_DEFAULT_PARAM, (#__expression)); \
-  } \
-} while (0)
-
-#define FATAL_IF_(__expression, ...) \
-do \
-{ \
-  if ((__expression)) { \
-    throw libtest::fatal(LIBYATL_DEFAULT_PARAM, __VA_ARGS__); \
-  } \
-} while (0)
-
-#define fatal_assert(__assert) if((__assert)) {} else { throw libtest::fatal(LIBYATL_DEFAULT_PARAM, #__assert); }
diff --git a/libtest/failed.cc b/libtest/failed.cc
deleted file mode 100644 (file)
index df5d083..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-#include <libtest/failed.h>
-
-#include <iostream>
-#include <string>
-#include <vector>
-
-namespace libtest {
-
-struct failed_st {
-  failed_st(const std::string& collection_arg, const std::string& test_arg) :
-    collection(collection_arg),
-    test(test_arg)
-  { }
-
-  std::string collection;
-  std::string test;
-};
-
-typedef std::vector<failed_st> Failures;
-
-class Failed
-{
-private:
-  Failures failures;
-
-public:
-  void push(const char *collection, const char *test)
-  {
-    failures.push_back(failed_st(collection, test));
-  }
-
-  void print_failed_test(void)
-  {
-    for (Failures::iterator iter= failures.begin(); iter != failures.end(); ++iter)
-    {
-      Error << "\t" << (*iter).collection << " " << (*iter).test;
-    }
-  }
-};
-
-} // namespace libtest
diff --git a/libtest/formatter.cc b/libtest/formatter.cc
deleted file mode 100644 (file)
index 443256b..0000000
+++ /dev/null
@@ -1,275 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include <libtest/common.h>
-
-#include <algorithm>
-#include <fstream>
-#include <iostream>
-#include <ostream>
-
-namespace libtest {
-
-std::string& escape4XML(std::string const& arg, std::string& escaped_string)
-{
-  escaped_string.clear();
-
-  escaped_string+= '"';
-  for (std::string::const_iterator x= arg.begin(), end= arg.end(); x != end; ++x)
-  {
-    unsigned char c= *x;
-    if (c == '&')
-    {
-      escaped_string+= "&amp;";
-    }
-    else if (c == '>')
-    {
-      escaped_string+= "&gt;";
-    }
-    else if (c == '<')
-    {
-      escaped_string+= "&lt;";
-    }
-    else if (c == '\'')
-    {
-      escaped_string+= "&apos;";  break;
-    }
-    else if (c == '"')
-    {
-      escaped_string+= "&quot;";
-    }
-    else if (c == ' ')
-    {
-      escaped_string+= ' ';
-    }
-    else if (isalnum(c))
-    {
-      escaped_string+= c;
-    }
-    else 
-    {
-      char const* const hexdig= "0123456789ABCDEF";
-      escaped_string+= "&#x";
-      escaped_string+= hexdig[c >> 4];
-      escaped_string+= hexdig[c & 0xF];
-      escaped_string+= ';';
-    }
-  }
-  escaped_string+= '"';
-
-  return escaped_string;
-}
-
-class TestCase {
-public:
-  TestCase(const std::string& arg):
-    _name(arg),
-    _result(TEST_FAILURE)
-  {
-  }
-
-  const std::string& name() const
-  {
-    return _name;
-  }
-
-  test_return_t result() const
-  {
-    return _result;
-  }
-
-  void result(test_return_t arg)
-  {
-    _result= arg;
-  }
-
-  void result(test_return_t arg, const libtest::Timer& timer_)
-  {
-    _result= arg;
-    _timer= timer_;
-  }
-
-  const libtest::Timer& timer() const
-  {
-    return _timer;
-  }
-
-  void timer(libtest::Timer& arg)
-  {
-    _timer= arg;
-  }
-
-private:
-  std::string _name;
-  test_return_t _result;
-  libtest::Timer _timer;
-};
-
-Formatter::Formatter(const std::string& frame_name, const std::string& arg)
-{
-  _suite_name= frame_name;
-  _suite_name+= ".";
-  _suite_name+= arg;
-}
-
-Formatter::~Formatter()
-{
-  std::for_each(_testcases.begin(), _testcases.end(), DeleteFromVector());
-  _testcases.clear();
-}
-
-TestCase* Formatter::current()
-{
-  return _testcases.back();
-}
-
-void Formatter::skipped()
-{
-  assert(current());
-  current()->result(TEST_SKIPPED);
-
-  Out
-    << "[ " << test_strerror(current()->result()) << " ]"
-    << "\t\t"
-    << name() << "." << current()->name()
-    ;
-
-  reset();
-}
-
-void Formatter::failed()
-{
-  assert(current());
-  current()->result(TEST_FAILURE);
-
-  Out
-    << "[ " << test_strerror(current()->result()) << " ]"
-    << "\t\t"
-    << name() << "." << current()->name()
-    ;
-
-  reset();
-}
-
-void Formatter::success(const libtest::Timer& timer_)
-{
-  assert(current());
-  current()->result(TEST_SUCCESS, timer_);
-
-  Out
-    << "[ " << test_strerror(current()->result()) << " ]"
-    << "\t"
-    << current()->timer()
-    << "\t"
-    << name() << "." << current()->name()
-    ;
-
-  reset();
-}
-
-void Formatter::xml(libtest::Framework& framework_, std::ofstream& output)
-{
-  std::string escaped_string;
-
-  output << "<testsuites name=" 
-    << escape4XML(framework_.name(), escaped_string) << ">" << std::endl;
-
-  for (Suites::iterator framework_iter= framework_.suites().begin();
-       framework_iter != framework_.suites().end();
-       ++framework_iter)
-  {
-    output << "\t<testsuite name=" 
-      << escape4XML((*framework_iter)->name(), escaped_string)
-#if 0
-      << "  classname=\"\" package=\"\"" 
-#endif
-      << ">" << std::endl;
-
-    for (TestCases::iterator case_iter= (*framework_iter)->formatter()->testcases().begin();
-         case_iter != (*framework_iter)->formatter()->testcases().end();
-         ++case_iter)
-    {
-      output << "\t\t<testcase name=" 
-        << escape4XML((*case_iter)->name(), escaped_string)
-        << " time=\"" 
-        << (*case_iter)->timer().elapsed_milliseconds() 
-        << "\""; 
-
-      switch ((*case_iter)->result())
-      {
-        case TEST_SKIPPED:
-        output << ">" << std::endl;
-        output << "\t\t <skipped/>" << std::endl;
-        output << "\t\t</testcase>" << std::endl;
-        break;
-
-        case TEST_FAILURE:
-        output << ">" << std::endl;
-        output << "\t\t <failure message=\"\" type=\"\"/>"<< std::endl;
-        output << "\t\t</testcase>" << std::endl;
-        break;
-
-        case TEST_SUCCESS:
-        output << "/>" << std::endl;
-        break;
-      }
-    }
-    output << "\t</testsuite>" << std::endl;
-  }
-  output << "</testsuites>" << std::endl;
-}
-
-void Formatter::push_testcase(const std::string& arg)
-{
-  assert(_suite_name.empty() == false);
-  TestCase* _current_testcase= new TestCase(arg);
-  _testcases.push_back(_current_testcase);
-
-  assert(current());
-
-  Echo
-    << "\t\t\t"
-    << name() << "." << current()->name()
-    << "... \r"
-    ;
-}
-
-void Formatter::reset()
-{
-}
-} // namespace libtest
diff --git a/libtest/formatter.hpp b/libtest/formatter.hpp
deleted file mode 100644 (file)
index 10818d4..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <string>
-
-namespace libtest { class Framework; }
-
-
-namespace libtest {
-
-class TestCase;
-typedef std::vector<libtest::TestCase*> TestCases;
-
-class Formatter {
-public:
-  Formatter(const std::string& frame_name, const std::string& arg);
-
-  ~Formatter();
-
-  void skipped();
-
-  void failed();
-
-  void success(const libtest::Timer&);
-
-  void push_testcase(const std::string&);
-
-  const std::string& name() const
-  {
-    return _suite_name;
-  }
-
-  TestCases& testcases()
-  {
-    return _testcases;
-  }
-
-  static void xml(libtest::Framework&, std::ofstream&);
-
-private:
-  void reset();
-
-  TestCase* current();
-
-private:
-  std::string _suite_name;
-  TestCases _testcases;
-};
-
-} // namespace libtest
diff --git a/libtest/framework.cc b/libtest/framework.cc
deleted file mode 100644 (file)
index 2c9ba74..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include <libtest/common.h>
-#include <libtest/collection.h>
-#include <libtest/signal.h>
-
-#include <algorithm>
-#include <fnmatch.h>
-#include <iostream>
-
-namespace libtest {
-
-Framework::Framework(libtest::SignalThread& signal_,
-                     const std::string& name_,
-                     const std::string& only_run_arg,
-                     const std::string& wildcard_arg) :
-  _total(0),
-  _success(0),
-  _skipped(0),
-  _failed(0),
-  _create(NULL),
-  _destroy(NULL),
-  _on_error(NULL),
-  _runner(NULL),
-  _socket(false),
-  _creators_ptr(NULL),
-  _signal(signal_),
-  _only_run(only_run_arg),
-  _wildcard(wildcard_arg),
-  _name(name_)
-{
-  get_world(this);
-}
-
-void Framework::collections(collection_st collections_[])
-{
-  for (collection_st *next= collections_; next and next->name; next++)
-  {
-    _collection.push_back(new Collection(this, next));
-  }
-}
-
-Framework::~Framework()
-{
-  if (_destroy and _destroy(_creators_ptr))
-  {
-    Error << "Failure in _destroy(), some resources may not have been cleaned up.";
-  }
-
-  _servers.shutdown();
-
-  delete _runner;
-
-  std::for_each(_collection.begin(), _collection.end(), DeleteFromVector());
-  _collection.clear();
-}
-
-bool Framework::match(const char* arg)
-{
-  if (_wildcard.empty() == false and fnmatch(_wildcard.c_str(), arg, 0))
-  {
-    return true;
-  }
-
-  return false;
-}
-
-void Framework::exec()
-{
-  for (std::vector<Collection*>::iterator iter= _collection.begin();
-       iter != _collection.end() and (_signal.is_shutdown() == false);
-       ++iter)
-  {
-    if (*iter)
-    {
-      if (_only_run.empty() == false and
-          fnmatch(_only_run.c_str(), (*iter)->name(), 0))
-      {
-        continue;
-      }
-
-      _total++;
-
-      try {
-        switch ((*iter)->exec())
-        {
-          case TEST_FAILURE:
-            _failed++;
-            break;
-
-          case TEST_SKIPPED:
-            _skipped++;
-            break;
-
-            // exec() can return SUCCESS, but that doesn't mean that some tests did
-            // not fail or get skipped.
-          case TEST_SUCCESS:
-            _success++;
-            break;
-        }
-      }
-      catch (const libtest::fatal& e)
-      {
-        _failed++;
-        stream::cerr(e.file(), e.line(), e.func()) << e.what();
-      }
-      catch (const libtest::disconnected& e)
-      {
-        _failed++;
-        Error << "Unhandled disconnection occurred:" << e.what();
-        throw;
-      }
-      catch (...)
-      {
-        _failed++;
-        throw;
-      }
-    }
-  }
-
-  void xml(const std::string& testsuites_name, std::ostream& output);
-}
-
-uint32_t Framework::sum_total()
-{
-  uint32_t count= 0;
-  for (std::vector<Collection*>::iterator iter= _collection.begin();
-       iter != _collection.end();
-       ++iter)
-  {
-    count+= (*iter)->total();
-  }
-
-  return count;
-}
-
-uint32_t Framework::sum_success()
-{
-  uint32_t count= 0;
-  for (std::vector<Collection*>::iterator iter= _collection.begin();
-       iter != _collection.end();
-       ++iter)
-  {
-    count+= (*iter)->success();
-  }
-
-  return count;
-}
-
-uint32_t Framework::sum_skipped()
-{
-  uint32_t count= 0;
-  for (std::vector<Collection*>::iterator iter= _collection.begin();
-       iter != _collection.end();
-       ++iter)
-  {
-    count+= (*iter)->skipped();
-  }
-
-  return count;
-}
-
-uint32_t Framework::sum_failed()
-{
-  uint32_t count= 0;
-  for (std::vector<Collection*>::iterator iter= _collection.begin();
-       iter != _collection.end();
-       ++iter)
-  {
-    count+= (*iter)->failed();
-  }
-
-  return count;
-}
-
-libtest::Runner *Framework::runner()
-{
-  if (_runner == NULL)
-  {
-    _runner= new Runner;
-  }
-  _runner->set_servers(_servers);
-
-  return _runner;
-}
-
-test_return_t Framework::create()
-{
-  test_return_t rc= TEST_SUCCESS;
-  if (_create)
-  {
-    _creators_ptr= _create(_servers, rc);
-  }
-
-  return rc;
-}
-
-} // namespace libtest
diff --git a/libtest/framework.h b/libtest/framework.h
deleted file mode 100644 (file)
index 361779d..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <libtest/signal.h>
-
-/**
-  Framework is the structure which is passed to the test implementation to be filled.
-  This must be implemented in order for the test framework to load the tests. We call
-  get_world() in order to fill this structure.
-*/
-
-#include <vector>
-
-namespace { class Collection; }
-typedef std::vector<libtest::Collection*> Suites;
-
-namespace libtest {
-
-class Framework {
-public:
-
-public:
-  test_return_t create();
-
-  const std::string& name() const
-  {
-    return _name;
-  }
-
-  void create(test_callback_create_fn* arg)
-  {
-    _create= arg;
-  }
-
-  void destroy(test_callback_destroy_fn* arg)
-  {
-    _destroy= arg;
-  }
-
-  void collections(collection_st arg[]);
-
-  void set_on_error(test_callback_error_fn *arg)
-  {
-    _on_error= arg;
-  }
-
-  test_return_t on_error(const enum test_return_t, void *);
-
-  void set_socket()
-  {
-    _servers.set_socket();
-  }
-
-  void set_sasl(const std::string& username_arg, const std::string& password_arg)
-  {
-    _servers.set_sasl(username_arg, password_arg);
-  }
-
-  libtest::server_startup_st& servers()
-  {
-    return _servers;
-  }
-
-  void set_runner(libtest::Runner *arg)
-  {
-    _runner= arg;
-  }
-
-  libtest::Runner *runner();
-
-  void exec();
-
-  libtest::Collection& collection();
-
-  virtual ~Framework();
-
-  Framework(libtest::SignalThread&,
-            const std::string&,
-            const std::string&,
-            const std::string&);
-
-  bool match(const char* arg);
-
-  void *creators_ptr()
-  {
-    return _creators_ptr;
-  }
-
-  libtest::SignalThread& signal()
-  {
-    return _signal;
-  }
-
-  uint32_t sum_total();
-  uint32_t sum_success();
-  uint32_t sum_skipped();
-  uint32_t sum_failed();
-
-  size_t size() 
-  {
-    return _collection.size();
-  }
-
-  uint32_t total() const
-  {
-    return _total;
-  }
-
-  uint32_t success() const
-  {
-    return _success;
-  }
-
-  uint32_t skipped() const
-  {
-    return _skipped;
-  }
-
-  uint32_t failed() const
-  {
-    return _failed;
-  }
-
-  Suites& suites()
-  {
-    return _collection;
-  }
-
-private:
-  uint32_t _total;
-  uint32_t _success;
-  uint32_t _skipped;
-  uint32_t _failed;
-  
-  /* These methods are called outside of any collection call. */
-  test_callback_create_fn *_create;
-  test_callback_destroy_fn *_destroy;
-
-  /**
-    If an error occurs during the test, this is called.
-  */
-  test_callback_error_fn *_on_error;
-
-  /**
-    Runner represents the callers for the tests. If not implemented we will use
-    a set of default implementations.
-  */
-  libtest::Runner *_runner;
-
-  libtest::server_startup_st _servers;
-  bool _socket;
-  void *_creators_ptr;
-  unsigned long int _servers_to_run;
-  Suites _collection;
-  libtest::SignalThread& _signal;
-  std::string _only_run;
-  std::string _wildcard;
-  std::string _name;
-
-private:
-  Framework( const Framework& );
-  const Framework& operator=( const Framework& );
-};
-
-} // namespace libtest
diff --git a/libtest/gearmand.cc b/libtest/gearmand.cc
deleted file mode 100644 (file)
index 852cf19..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-#include <libtest/gearmand.h>
-
-using namespace libtest;
-
-#include <cassert>
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <iostream>
-#include <signal.h>
-#include <sstream>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
-
-using namespace libtest;
-
-class Gearmand : public libtest::Server
-{
-private:
-public:
-  Gearmand(const std::string& host_arg, in_port_t port_arg, bool libtool_, const char* binary);
-
-  bool ping()
-  {
-    reset_error();
-
-    if (out_of_ban_killed())
-    {
-      return false;
-    }
-
-    SimpleClient client(_hostname, _port);
-
-    std::string response;
-    bool ret= client.send_message("version", response);
-
-    if (client.is_error())
-    {
-      error(client.error());
-    }
-
-    return ret;
-  }
-
-  const char *name()
-  {
-    return "gearmand";
-  };
-
-  void log_file_option(Application& app, const std::string& arg)
-  {
-    if (arg.empty() == false)
-    {
-      std::string buffer("--log-file=");
-      buffer+= arg;
-      app.add_option("--verbose=DEBUG");
-      app.add_option(buffer);
-    }
-  }
-
-  bool has_log_file_option() const
-  {
-    return true;
-  }
-
-  bool is_libtool()
-  {
-    return true;
-  }
-
-  bool has_syslog() const
-  {
-    return false; //  --syslog.errmsg-enable
-  }
-
-  bool has_port_option() const
-  {
-    return true;
-  }
-
-  bool build();
-};
-
-Gearmand::Gearmand(const std::string& host_arg, in_port_t port_arg, bool libtool_, const char* binary_arg) :
-  libtest::Server(host_arg, port_arg, binary_arg, libtool_)
-{
-  set_pid_file();
-}
-
-bool Gearmand::build()
-{
-  if (getuid() == 0 or geteuid() == 0)
-  {
-    add_option("-u", "root");
-  }
-
-  add_option("--listen=localhost");
-
-  return true;
-}
-
-namespace libtest {
-
-libtest::Server *build_gearmand(const char *hostname, in_port_t try_port, const char* binary)
-{
-  if (binary == NULL)
-  {
-#if defined(HAVE_GEARMAND_BINARY)
-# if defined(GEARMAND_BINARY)
-    if (HAVE_GEARMAND_BINARY)
-    {
-      binary= GEARMAND_BINARY;
-    }
-# endif
-#endif
-  }
-
-  if (binary == NULL)
-  {
-    return NULL;
-  }
-
-  bool is_libtool_script= true;
-
-  if (binary[0] == '/')
-  {
-    is_libtool_script= false;
-  }
-
-  return new Gearmand(hostname, try_port, is_libtool_script, binary);
-}
-
-}
diff --git a/libtest/gearmand.h b/libtest/gearmand.h
deleted file mode 100644 (file)
index 41317d7..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest { struct Server; }
-
-namespace libtest {
-
-libtest::Server *build_gearmand(const char *hostname, in_port_t try_port, const char* binary= NULL);
-
-}
diff --git a/libtest/get.h b/libtest/get.h
deleted file mode 100644 (file)
index e21ac0a..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-  /* How we make all of this work :) */
-  LIBTEST_API
-    void get_world(libtest::Framework *world);
-
-#ifdef __cplusplus
-}
-#endif
-
-
diff --git a/libtest/has.cc b/libtest/has.cc
deleted file mode 100644 (file)
index 74b4aa2..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-#include <cstdio>
-#include <cstdlib>
-#include <unistd.h>
-
-namespace libtest {
-
-bool has_libmemcached_sasl(void)
-{
-#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
-  return LIBMEMCACHED_WITH_SASL_SUPPORT;
-#else
-  return false;
-#endif
-}
-
-bool has_libmemcached(void)
-{
-#if defined(HAVE_LIBMEMCACHED) && HAVE_LIBMEMCACHED
-  if (HAVE_LIBMEMCACHED)
-  {
-    return true;
-  }
-#endif
-
-  return false;
-}
-
-bool has_libdrizzle(void)
-{
-#if defined(HAVE_LIBDRIZZLE) && HAVE_LIBDRIZZLE
-  if (HAVE_LIBDRIZZLE)
-  {
-    return true;
-  }
-#endif
-
-  return false;
-}
-
-bool has_postgres_support(void)
-{
-  char *getenv_ptr;
-  if (bool((getenv_ptr= getenv("POSTGRES_IS_RUNNING_AND_SETUP"))))
-  {
-    (void)(getenv_ptr);
-#if defined(HAVE_LIBPQ) && HAVE_LIBPQ
-    if (HAVE_LIBPQ)
-    {
-      return true;
-    }
-#endif
-  }
-
-  return false;
-}
-
-
-bool has_gearmand()
-{
-#if defined(GEARMAND_BINARY) && defined(HAVE_GEARMAND_BINARY) && HAVE_GEARMAND_BINARY
-  if (HAVE_GEARMAND_BINARY)
-  {
-    std::stringstream arg_buffer;
-
-    char *getenv_ptr;
-    if (bool((getenv_ptr= getenv("PWD"))) and 
-        ((strcmp(GEARMAND_BINARY, "./gearmand/gearmand") == 0) or (strcmp(GEARMAND_BINARY, "gearmand/gearmand") == 0)))
-    {
-      arg_buffer << getenv_ptr;
-      arg_buffer << "/";
-    }
-    arg_buffer << GEARMAND_BINARY;
-
-    if (access(arg_buffer.str().c_str(), X_OK) == 0)
-    {
-      return true;
-    }
-  }
-#endif
-
-  return false;
-}
-
-bool has_drizzled()
-{
-#if defined(DRIZZLED_BINARY) && defined(HAVE_DRIZZLED_BINARY) && HAVE_DRIZZLED_BINARY
-  if (HAVE_DRIZZLED_BINARY)
-  {
-    if (access(DRIZZLED_BINARY, X_OK) == 0)
-    {
-      return true;
-    }
-  }
-#endif
-
-  return false;
-}
-
-bool has_mysqld()
-{
-#if defined(MYSQLD_BINARY) && defined(HAVE_MYSQLD_BUILD) && HAVE_MYSQLD_BUILD
-  if (HAVE_MYSQLD_BUILD)
-  {
-    if (access(MYSQLD_BINARY, X_OK) == 0)
-    {
-      return true;
-    }
-  }
-#endif
-
-  return false;
-}
-
-static char memcached_binary_path[FILENAME_MAX];
-
-static void initialize_memcached_binary_path()
-{
-  memcached_binary_path[0]= 0;
-
-#if defined(MEMCACHED_BINARY) && defined(HAVE_MEMCACHED_BINARY) && HAVE_MEMCACHED_BINARY
-  if (HAVE_MEMCACHED_BINARY)
-  {
-    std::stringstream arg_buffer;
-
-    char *getenv_ptr;
-    if (bool((getenv_ptr= getenv("PWD"))) and strcmp(MEMCACHED_BINARY, "memcached/memcached") == 0)
-    {
-      arg_buffer << getenv_ptr;
-      arg_buffer << "/";
-    }
-    arg_buffer << MEMCACHED_BINARY;
-
-    if (access(arg_buffer.str().c_str(), X_OK) == 0)
-    {
-      strncpy(memcached_binary_path, arg_buffer.str().c_str(), FILENAME_MAX-1);
-    }
-  }
-#endif
-}
-
-static pthread_once_t memcached_binary_once= PTHREAD_ONCE_INIT;
-static void initialize_memcached_binary(void)
-{
-  int ret;
-  if ((ret= pthread_once(&memcached_binary_once, initialize_memcached_binary_path)) != 0)
-  {
-    FATAL(strerror(ret));
-  }
-}
-
-bool has_memcached()
-{
-  initialize_memcached_binary();
-
-  if (memcached_binary_path[0] and (strlen(memcached_binary_path) > 0))
-  {
-    return true;
-  }
-
-  return false;
-}
-
-const char* memcached_binary()
-{
-  initialize_memcached_binary();
-
-  if (memcached_binary_path[0])
-  {
-    return memcached_binary_path;
-  }
-
-  return NULL;
-}
-
-const char *gearmand_binary() 
-{
-#if defined(GEARMAND_BINARY)
-  return GEARMAND_BINARY;
-#else
-  return NULL;
-#endif
-}
-
-const char *drizzled_binary() 
-{
-#if defined(DRIZZLED_BINARY)
-  return DRIZZLED_BINARY;
-#else
-  return NULL;
-#endif
-}
-
-} // namespace libtest
diff --git a/libtest/has.hpp b/libtest/has.hpp
deleted file mode 100644 (file)
index 59ee88f..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-LIBTEST_API
-bool has_libmemcached_sasl(void);
-
-LIBTEST_API
-bool has_libmemcached();
-
-LIBTEST_API
-bool has_libdrizzle();
-
-LIBTEST_API
-bool has_postgres_support();
-
-LIBTEST_API
-bool has_memcached();
-
-LIBTEST_API
-bool has_memcached_sasl();
-
-LIBTEST_API
-bool has_gearmand();
-
-LIBTEST_API
-bool has_drizzled();
-
-LIBTEST_API
-bool has_mysqld();
-
-LIBTEST_API
-const char* memcached_binary();
-
-LIBTEST_API
-const char *gearmand_binary(); 
-
-LIBTEST_API
-const char *drizzled_binary();
-} // namespace libtest
diff --git a/libtest/http.cc b/libtest/http.cc
deleted file mode 100644 (file)
index 465ce61..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include <libtest/common.h>
-
-#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
-#include <curl/curl.h>
-#else
-class CURL;
-#endif
-
-
-static void cleanup_curl(void)
-{
-#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
-  curl_global_cleanup();
-#endif
-}
-
-static void initialize_curl_startup()
-{
-#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
-  if (curl_global_init(CURL_GLOBAL_ALL))
-  {
-    FATAL("curl_global_init(CURL_GLOBAL_ALL) failed");
-  }
-#endif
-
-  if (atexit(cleanup_curl))
-  {
-    FATAL("atexit() failed");
-  }
-}
-
-static pthread_once_t start_key_once= PTHREAD_ONCE_INIT;
-static void initialize_curl(void)
-{
-  int ret;
-  if ((ret= pthread_once(&start_key_once, initialize_curl_startup)) != 0)
-  {
-    FATAL(strerror(ret));
-  }
-}
-
-namespace libtest {
-namespace http {
-
-#define YATL_USERAGENT "YATL/1.0"
-
-static size_t http_get_result_callback(void *ptr, size_t size, size_t nmemb, void *data)
-{
-  vchar_t *_body= (vchar_t*)data;
-
-  _body->resize(size * nmemb);
-  memcpy(&(*_body)[0], ptr, _body->size());
-
-  return _body->size();
-}
-
-static void init(CURL *curl, const std::string& url)
-{
-  (void)http_get_result_callback;
-  (void)curl;
-  (void)url;
-#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
-  if (HAVE_LIBCURL)
-  {
-    assert(curl);
-    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
-    curl_easy_setopt(curl, CURLOPT_USERAGENT, YATL_USERAGENT);
-  }
-#endif
-}
-
-HTTP::HTTP(const std::string& url_arg) :
-  _url(url_arg),
-  _response(0)
-{
-  initialize_curl();
-}
-
-bool GET::execute()
-{
-  (void)init;
-
-#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
-  if (HAVE_LIBCURL)
-  {
-    CURL *curl= curl_easy_init();
-
-    init(curl, url());
-
-    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_result_callback);
-    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&_body);
-
-    CURLcode retref= curl_easy_perform(curl);
-    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, _response);
-
-    curl_easy_cleanup(curl);
-
-    return bool(retref == CURLE_OK);
-  }
-#endif
-
-  return false;
-}
-
-bool POST::execute()
-{
-#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
-  if (HAVE_LIBCURL)
-  {
-    CURL *curl= curl_easy_init();;
-
-    init(curl, url());
-
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, _body.size());
-    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void *)&_body[0]);
-
-    CURLcode retref= curl_easy_perform(curl);
-    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, _response);
-
-    curl_easy_cleanup(curl);
-
-    return bool(retref == CURLE_OK);
-  }
-#endif
-
-  return false;
-}
-
-bool TRACE::execute()
-{
-#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
-  if (HAVE_LIBCURL)
-  {
-    CURL *curl= curl_easy_init();;
-
-    init(curl, url());
-
-    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "TRACE");
-    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_result_callback);
-    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&_body[0]);
-
-    CURLcode retref= curl_easy_perform(curl);
-    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, _response);
-
-    curl_easy_cleanup(curl);
-
-    return retref == CURLE_OK;
-  }
-#endif
-
-  return false;
-}
-
-bool HEAD::execute()
-{
-#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
-  if (HAVE_LIBCURL)
-  {
-    CURL *curl= curl_easy_init();
-
-    init(curl, url());
-
-    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "HEAD");
-    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_result_callback);
-
-    CURLcode retref= curl_easy_perform(curl);
-    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, _response);
-
-    curl_easy_cleanup(curl);
-
-    return retref == CURLE_OK;
-  }
-#endif
-
-  return false;
-}
-
-} // namespace http
-} // namespace libtest
diff --git a/libtest/http.hpp b/libtest/http.hpp
deleted file mode 100644 (file)
index 6827821..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <libtest/vchar.hpp>
-
-namespace libtest {
-namespace http {
-
-class HTTP {
-public:
-
-  HTTP(const std::string& url_arg);
-
-  virtual bool execute()= 0;
-
-  virtual ~HTTP()
-  { }
-
-  const std::string& url() const
-  {
-    return _url;
-  }
-
-  long response()
-  {
-    return _response;
-  }
-
-private:
-  std::string _url;
-
-protected:
-  long _response;
-};
-
-class GET: public HTTP {
-public:
-
-  GET(const std::string& url_arg) :
-    HTTP(url_arg)
-  {
-  }
-
-  bool execute();
-
-private:
-  libtest::vchar_t _body;
-};
-
-class POST: public HTTP {
-public:
-
-  POST(const std::string& url_arg,
-       const vchar_t& post_arg) :
-    HTTP(url_arg),
-    _post(post_arg)
-  {
-  }
-
-  bool execute();
-
-private:
-  libtest::vchar_t _post;
-  libtest::vchar_t _body;
-};
-
-class TRACE: public HTTP {
-public:
-
-  TRACE(const std::string& url_arg,
-        const vchar_t& body_arg) :
-    HTTP(url_arg),
-    _body(body_arg)
-  {
-  }
-
-  bool execute();
-
-private:
-  libtest::vchar_t _body;
-};
-
-class HEAD: public HTTP {
-public:
-
-  HEAD(const std::string& url_arg) :
-    HTTP(url_arg)
-  {
-  }
-
-  bool execute();
-
-private:
-};
-
-} // namespace http
-} // namespace libtest
diff --git a/libtest/is_local.cc b/libtest/is_local.cc
deleted file mode 100644 (file)
index ef4059c..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-
-namespace libtest {
-
-bool test_is_local()
-{
-  return (getenv("LIBTEST_LOCAL"));
-}
-
-static bool _is_massive= false;
-void is_massive(bool arg)
-{
-  _is_massive= arg;
-}
-
-bool is_massive()
-{
-  return _is_massive;
-}
-
-} // namespace libtest
-
diff --git a/libtest/is_local.hpp b/libtest/is_local.hpp
deleted file mode 100644 (file)
index 0835553..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-LIBTEST_API
-bool test_is_local();
-
-LIBTEST_API
-void is_massive(bool);
-
-LIBTEST_API
-bool is_massive();
-
-} // namespace libtest
diff --git a/libtest/is_pid.hpp b/libtest/is_pid.hpp
deleted file mode 100644 (file)
index 3c514a9..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-static inline bool is_pid_valid(const pid_t pid)
-{
-  return (pid > 1) ? true : false;
-}
-
diff --git a/libtest/killpid.cc b/libtest/killpid.cc
deleted file mode 100644 (file)
index 2cefff2..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-#include <cstdlib>
-#include <cstring>
-#include <iostream>
-#include <sstream>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-
-#include <libtest/killpid.h>
-#include <libtest/stream.h>
-
-using namespace libtest;
-
-bool kill_pid(pid_t pid_arg)
-{
-  assert(pid_arg > 0);
-  if (pid_arg < 1)
-  {
-    Error << "Invalid pid:" << pid_arg;
-    return false;
-  }
-
-  if ((::kill(pid_arg, SIGTERM) == -1))
-  {
-    switch (errno)
-    {
-    case EPERM:
-      Error << "Does someone else have a process running locally for " << int(pid_arg) << "?";
-      return false;
-
-    case ESRCH:
-      Error << "Process " << int(pid_arg) << " not found.";
-      return false;
-
-    default:
-    case EINVAL:
-      Error << "kill() " << strerror(errno);
-      return false;
-    }
-  }
-
-  {
-    uint32_t this_wait= 0;
-    uint32_t timeout= 20; // This number should be high enough for valgrind startup (which is slow)
-    uint32_t waited;
-    uint32_t retry;
-
-    for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
-    {
-      int status= 0;
-      if (waitpid(pid_arg, &status, WNOHANG) == 0)
-      {
-        break;
-      }
-      else if (errno == ECHILD)
-      {
-        // Server has already gone away
-        break;
-      }
-      else if (waited >= timeout)
-      {
-        // Timeout failed
-        kill(pid_arg, SIGKILL);
-        break;
-      }
-
-      this_wait= retry * retry / 3 + 1;
-      libtest::dream(this_wait, 0);
-    }
-  }
-
-  return true;
-}
-
-bool check_pid(const std::string &filename)
-{
-  if (filename.empty())
-  {
-    return false;
-  }
-
-  FILE *fp;
-  if ((fp= fopen(filename.c_str(), "r")))
-  {
-    libtest::vchar_t pid_buffer;
-    pid_buffer.resize(1024);
-
-    char *ptr= fgets(&pid_buffer[0], int(pid_buffer.size()), fp);
-    fclose(fp);
-
-    if (ptr)
-    {
-      pid_t pid= (pid_t)atoi(&pid_buffer[0]);
-      if (pid > 0)
-      {
-        return (::kill(pid, 0) == 0);
-      }
-    }
-  }
-  
-  return false;
-}
-
-
-bool kill_file(const std::string &filename)
-{
-  if (filename.empty())
-  {
-    return true;
-  }
-
-  FILE *fp;
-  if ((fp= fopen(filename.c_str(), "r")))
-  {
-    libtest::vchar_t pid_buffer;
-    pid_buffer.resize(1024);
-
-    char *ptr= fgets(&pid_buffer[0], int(pid_buffer.size()), fp);
-    fclose(fp);
-
-    if (ptr)
-    {
-      pid_t pid= (pid_t)atoi(&pid_buffer[0]);
-      if (pid != 0)
-      {
-        bool ret= kill_pid(pid);
-        unlink(filename.c_str()); // If this happens we may be dealing with a dead server that left its pid file.
-
-        return ret;
-      }
-    }
-  }
-  
-  return false;
-}
-
-#define STRINGIFY(x) #x
-#define TOSTRING(x) STRINGIFY(x)
-#define LIBTEST_AT __FILE__ ":" TOSTRING(__LINE__)
-
-pid_t get_pid_from_file(const std::string &filename, std::stringstream& error_message)
-{
-  pid_t ret= -1;
-
-  if (filename.empty())
-  {
-    error_message << LIBTEST_AT << " empty pid file";
-    return ret;
-  }
-
-  FILE *fp;
-  if ((fp= fopen(filename.c_str(), "r")))
-  {
-    libtest::vchar_t pid_buffer;
-    pid_buffer.resize(1024);
-
-    char *ptr= fgets(&pid_buffer[0], int(pid_buffer.size()), fp);
-    if (ptr)
-    {
-      ret= (pid_t)atoi(&pid_buffer[0]);
-      if (ret < 1)
-      {
-        error_message << LIBTEST_AT << " Invalid pid was read from file " << filename;
-      }
-    }
-    else
-    {
-      error_message << LIBTEST_AT << " File " << filename << " was empty ";
-    }
-
-    fclose(fp);
-
-    return ret;
-  }
-  else
-  {
-    libtest::vchar_t buffer;
-    buffer.resize(1024);
-    char *current_directory= getcwd(&buffer[0], buffer.size());
-    error_message << "Error while opening " << current_directory << "/" << filename << " " << strerror(errno);
-  }
-  
-  return ret;
-}
diff --git a/libtest/killpid.h b/libtest/killpid.h
deleted file mode 100644 (file)
index 6bf5dee..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-bool kill_pid(pid_t pid_arg);
-
-bool kill_file(const std::string &filename);
-
-bool check_pid(const std::string &filename);
-
-pid_t get_pid_from_file(const std::string &filename, std::stringstream& error_message);
-
-static inline bool check_pid(pid_t pid_arg)
-{
-  return (pid_arg > 1);
-}
diff --git a/libtest/libtool.cc b/libtest/libtool.cc
deleted file mode 100644 (file)
index 9d4b0f5..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-#include <string>
-
-char _libtool[1024]= { 0 };
-
-namespace libtest {
-
-const char *libtool(void)
-{
-  if (_libtool[0] == 0)
-  {
-    std::string libtool_buffer;
-    if (getenv("PWD"))
-    {
-      libtool_buffer+= getenv("PWD");
-      libtool_buffer+= "/";
-    }
-    else
-    {
-      libtool_buffer+= "./";
-    }
-
-    libtool_buffer+= "libtool";
-    if (access(libtool_buffer.c_str(), R_OK | W_OK | X_OK))
-    {
-      Error << "Could not find libtool via access(" << libtool_buffer << ") :" << strerror(errno);
-      return NULL;
-    }
-
-    snprintf(_libtool, sizeof(_libtool), "%s", libtool_buffer.c_str());
-  }
-
-  return _libtool;
-}
-
-} // namespace libtest
diff --git a/libtest/libtool.hpp b/libtest/libtool.hpp
deleted file mode 100644 (file)
index 925b55d..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-const char *libtool(void);
-
-}
diff --git a/libtest/lite.h b/libtest/lite.h
deleted file mode 100644 (file)
index 36f873e..0000000
+++ /dev/null
@@ -1,413 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifdef __cplusplus
-# include <cstdarg>
-# include <cstddef>
-# include <cstdio>
-# include <cstdlib>
-# include <cstring>
-#else
-# include <stdarg.h>
-# include <stdbool.h>
-# include <stddef.h>
-# include <stdio.h>
-# include <stdlib.h>
-# include <string.h>
-#endif
-
-#if defined(WIN32)
-# include <malloc.h>
-#else
-# include <alloca.h>
-#endif
-
-#ifndef __PRETTY_FUNCTION__
-# define __PRETTY_FUNCTION__ __func__
-#endif
-
-#ifndef EXIT_SKIP
-# define EXIT_SKIP 77
-#endif
-
-#ifndef YATL_FULL
-# define YATL_FULL 0
-#endif
-
-#ifndef FAIL
-# define FAIL(__message_format, ...)
-#endif
-
-#ifndef SKIP
-# define SKIP(__message_format, ...)
-#endif
-
-#include <libtest/valgrind.h>
-
-static inline size_t yatl_strlen(const char *s)
-{
-  if (s)
-  {
-    return strlen(s);
-  }
-
-  return (size_t)(0);
-}
-
-static inline int yatl_strcmp(const char *s1, const char *s2, size_t *s1_length, size_t *s2_length)
-{
-  *s1_length= yatl_strlen(s1);
-  *s2_length= yatl_strlen(s2);
-
-  if (*s1_length == 0 &&  *s1_length == *s2_length)
-  {
-    return 0;
-  }
-
-  if (*s1_length == 0 && *s2_length)
-  {
-    return 1;
-  }
-
-  if (*s1_length &&  *s2_length == 0)
-  {
-    return 1;
-  }
-
-  return strcmp(s1, s2);
-}
-
-#define SKIP_IF(__expression) \
-do \
-{ \
-  if ((__expression)) { \
-    if (YATL_FULL) { \
-      SKIP(#__expression); \
-    } \
-    fprintf(stdout, "\n%s:%d: %s SKIP '!(%s)'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression); \
-    exit(EXIT_SKIP); \
-  } \
-} while (0)
-
-#define SKIP_IF_(__expression, ...) \
-do \
-{ \
-  if ((__expression)) { \
-    size_t ask= snprintf(0, 0, __VA_ARGS__); \
-    ask++; \
-    char *buffer= (char*)alloca(sizeof(char) * ask); \
-    snprintf(buffer, ask, __VA_ARGS__); \
-    if (YATL_FULL) { \
-      SKIP(#__expression, buffer); \
-    } \
-    fprintf(stdout, "\n%s:%d: %s SKIP '%s' [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression, buffer); \
-    exit(EXIT_SKIP); \
-  } \
-} while (0)
-
-#define SKIP_UNLESS(__expression) \
-do \
-{ \
-  if (! (__expression)) { \
-    if (YATL_FULL) { \
-      SKIP(#__expression); \
-    } \
-    fprintf(stdout, "\n%s:%d: %s SKIP '(%s)'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression); \
-    exit(EXIT_SKIP); \
-  } \
-} while (0)
-
-#define SKIP_UNLESS_(__expression, ...) \
-do \
-{ \
-  if (! (__expression)) { \
-    size_t ask= snprintf(0, 0, __VA_ARGS__); \
-    ask++; \
-    char *buffer= (char*)alloca(sizeof(char) * ask); \
-    snprintf(buffer, ask, __VA_ARGS__); \
-    if (YATL_FULL) { \
-      SKIP(#__expression, buffer); \
-    } \
-    fprintf(stdout, "\n%s:%d: %s SKIP '%s' [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression, buffer); \
-    exit(EXIT_SKIP); \
-  } \
-} while (0)
-
-#define ASSERT_TRUE(__expression) \
-do \
-{ \
-  if (! (__expression)) { \
-    if (YATL_FULL) { \
-      FAIL("Assertion '%s'", #__expression); \
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '%s'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression);\
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_FALSE(__expression) \
-do \
-{ \
-  if ((__expression)) { \
-    if (YATL_FULL) { \
-     FAIL("Assertion '!%s'", #__expression); \
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '!%s'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression);\
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_NULL_(__expression, ...) \
-do \
-{ \
-  if ((__expression) != NULL) { \
-    size_t ask= snprintf(0, 0, __VA_ARGS__); \
-    ask++; \
-    char *buffer= (char*)alloca(sizeof(char) * ask); \
-    snprintf(buffer, ask, __VA_ARGS__); \
-    if (YATL_FULL) { \
-      FAIL("Assertion '%s' != NULL [ %s ]", #__expression, buffer);\
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '%s' != NULL [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression, buffer);\
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_NOT_NULL(__expression) \
-do \
-{ \
-  if ((__expression) == NULL) { \
-    if (YATL_FULL) { \
-      FAIL("Assertion '%s' == NULL", #__expression,);\
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '%s' == NULL\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression,);\
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_NOT_NULL_(__expression, ...) \
-do \
-{ \
-  if ((__expression) == NULL) { \
-    size_t ask= snprintf(0, 0, __VA_ARGS__); \
-    ask++; \
-    char *buffer= (char*)alloca(sizeof(char) * ask); \
-    snprintf(buffer, ask, __VA_ARGS__); \
-    if (YATL_FULL) { \
-      FAIL("Assertion '%s' == NULL [ %s ]", #__expression, buffer);\
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '%s' == NULL [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression, buffer);\
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_TRUE_(__expression, ...) \
-do \
-{ \
-  if (! (__expression)) { \
-    size_t ask= snprintf(0, 0, __VA_ARGS__); \
-    ask++; \
-    char *buffer= (char*)alloca(sizeof(char) * ask); \
-    snprintf(buffer, ask, __VA_ARGS__); \
-    if (YATL_FULL) { \
-      FAIL("Assertion '%s' [ %s ]", #__expression, buffer); \
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '%s' [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression, buffer); \
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_EQ(__expected, __actual) \
-do \
-{ \
-  if ((__expected) != (__actual)) { \
-    if (YATL_FULL) { \
-      FAIL("Assertion '%s' != '%s'", #__expected, #__actual); \
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '%s' != '%s'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expected, #__actual); \
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_EQ_(__expected, __actual, ...) \
-do \
-{ \
-  if ((__expected) != (__actual)) { \
-    size_t ask= snprintf(0, 0, __VA_ARGS__); \
-    ask++; \
-    char *buffer= (char*)alloca(sizeof(char) * ask); \
-    snprintf(buffer, ask, __VA_ARGS__); \
-    if (YATL_FULL) { \
-      FAIL("Assertion '%s' != '%s' [ %s ]", #__expected, #__actual, buffer); \
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '%s' != '%s' [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expected, #__actual, buffer); \
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_STREQ(__expected_str, __actual_str) \
-do \
-{ \
-  size_t __expected_length; \
-  size_t __actual_length; \
-  int ret= yatl_strcmp(__expected_str, __actual_str, &__expected_length, &__actual_length); \
-  if (ret) { \
-    if (YATL_FULL) { \
-      FAIL("Assertion '%.*s' != '%.*s'\n", \
-           (int)(__expected_length), (__expected_str), \
-           (int)__actual_length, (__actual_str)) ; \
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '%.*s' != '%.*s'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, \
-            (int)(__expected_length), (__expected_str), \
-            (int)__actual_length, (__actual_str)) ; \
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_STREQ_(__expected_str, __actual_str, ...) \
-do \
-{ \
-  size_t __expected_length; \
-  size_t __actual_length; \
-  int ret= yatl_strcmp(__expected_str, __actual_str, &__expected_length, &__actual_length); \
-  if (ret) { \
-    size_t ask= snprintf(0, 0, __VA_ARGS__); \
-    ask++; \
-    char *buffer= (char*)alloca(sizeof(char) * ask); \
-    ask= snprintf(buffer, ask, __VA_ARGS__); \
-    if (YATL_FULL) { \
-      FAIL("Assertion '%.*s' != '%.*s' [ %.*s ]", \
-           (int)(__expected_length), (__expected_str), \
-           (int)(__actual_length), (__actual_str), \
-           (int)(ask), buffer); \
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '%.*s' != '%.*s' [ %.*s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, \
-            (int)(__expected_length), (__expected_str), \
-            (int)(__actual_length), (__actual_str), \
-            (int)(ask), buffer); \
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_STRNE(__expected_str, __actual_str) \
-do \
-{ \
-  size_t __expected_length; \
-  size_t __actual_length; \
-  int ret= yatl_strcmp(__expected_str, __actual_str, &__expected_length, &__actual_length); \
-  if (ret == 0) { \
-    if (YATL_FULL) { \
-      FAIL("Assertion '%.*s' == '%.*s'", \
-           (int)(__expected_length), (__expected_str), \
-           (int)__actual_length, (__actual_str)) ; \
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '%.*s' == '%.*s'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, \
-            (int)(__expected_length), (__expected_str), \
-            (int)__actual_length, (__actual_str)) ; \
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_STRNE_(__expected_str, __actual_str, ...) \
-do \
-{ \
-  size_t __expected_length; \
-  size_t __actual_length; \
-  int ret= yatl_strcmp(__expected_str, __actual_str, &__expected_length, &__actual_length); \
-  if (ret == 0) { \
-    size_t ask= snprintf(0, 0, __VA_ARGS__); \
-    ask++; \
-    char *buffer= (char*)alloca(sizeof(char) * ask); \
-    ask= snprintf(buffer, ask, __VA_ARGS__); \
-    if (YATL_FULL) { \
-      FAIL("Assertion '%.*s' == '%.*s' [ %.*s ]", \
-           (int)(__expected_length), (__expected_str), \
-           (int)(__actual_length), (__actual_str), \
-           (int)(ask), buffer); \
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '%.*s' == '%.*s' [ %.*s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, \
-            (int)(__expected_length), (__expected_str), \
-            (int)(__actual_length), (__actual_str), \
-            (int)(ask), buffer); \
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_NEQ(__expected, __actual) \
-do \
-{ \
-  if ((__expected) == (__actual)) { \
-    if (YATL_FULL) { \
-      FAIL("Assertion '%s' == '%s'", #__expected, #__actual); \
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '%s' == '%s'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expected, #__actual); \
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_NEQ_(__expected, __actual, ...) \
-do \
-{ \
-  if ((__expected) == (__actual)) { \
-    size_t ask= snprintf(0, 0, __VA_ARGS__); \
-    ask++; \
-    char *buffer= (char*)alloca(sizeof(char) * ask); \
-    snprintf(buffer, ask, __VA_ARGS__); \
-    if (YATL_FULL) { \
-      FAIL("Assertion '%s' == '%s' [ %s ]", #__expected, #__actual, buffer); \
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '%s' == '%s' [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expected, #__actual, buffer); \
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
-
-#define ASSERT_FALSE_(__expression, ...) \
-do \
-{ \
-  if ((__expression)) { \
-    size_t ask= snprintf(0, 0, __VA_ARGS__); \
-    ask++; \
-    char *buffer= (char*)alloca(sizeof(char) * ask); \
-    snprintf(buffer, ask, __VA_ARGS__); \
-    if (YATL_FULL) { \
-      FAIL("Assertion '!%s' [ %s ]", #__expression, buffer); \
-    } \
-    fprintf(stderr, "\n%s:%d: %s Assertion '!%s' [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression, buffer); \
-    exit(EXIT_FAILURE); \
-  } \
-} while (0)
diff --git a/libtest/main.cc b/libtest/main.cc
deleted file mode 100644 (file)
index f20cb95..0000000
+++ /dev/null
@@ -1,396 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-#include <cassert>
-#include <cstdlib>
-#include <cstring>
-#include <ctime>
-#include <fnmatch.h>
-#include <iostream>
-#ifdef HAVE_STRINGS_H
-# include <strings.h>
-#endif
-#include <fstream>
-#include <memory>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <signal.h>
-
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
-
-#if __cplusplus >= 201103L
-# define UNIQUE_PTR std::unique_ptr
-#else
-# define UNIQUE_PTR std::auto_ptr
-#endif
-
-using namespace libtest;
-
-static void stats_print(libtest::Framework *frame)
-{
-  if (frame->failed() == 0 and frame->success() == 0)
-  {
-    return;
-  }
-
-  Outn();
-  Out << "Collections\t\t\t\t\t" << frame->total();
-  Out << "\tFailed\t\t\t\t\t" << frame->failed();
-  Out << "\tSkipped\t\t\t\t\t" << frame->skipped();
-  Out << "\tSucceeded\t\t\t\t" << frame->success();
-  Outn();
-  Out << "Tests\t\t\t\t\t" << frame->sum_total();
-  Out << "\tFailed\t\t\t\t" << frame->sum_failed();
-  Out << "\tSkipped\t\t\t\t" << frame->sum_skipped();
-  Out << "\tSucceeded\t\t\t" << frame->sum_success();
-}
-
-#include <getopt.h>
-#include <unistd.h>
-
-int main(int argc, char *argv[])
-{
-  bool opt_massive= false;
-  unsigned long int opt_repeat= 1; // Run all tests once
-  bool opt_quiet= false;
-  std::string collection_to_run;
-  std::string wildcard;
-  std::string binary_name;
-
-  const char *just_filename= rindex(argv[0], '/');
-  if (just_filename)
-  {
-    just_filename++;
-  }
-  else
-  {
-    just_filename= argv[0];
-  }
-
-  if (just_filename[0] == 'l' and just_filename[1] == 't' and  just_filename[2] == '-')
-  {
-    just_filename+= 3;
-  }
-  binary_name.append(just_filename);
-
-  /*
-    Valgrind does not currently work reliably, or sometimes at all, on OSX
-    - Fri Jun 15 11:24:07 EDT 2012
-  */
-#if defined(__APPLE__) && __APPLE__
-  if (valgrind_is_caller())
-  {
-    return EXIT_SKIP;
-  }
-#endif
-
-  // Options parsing
-  {
-    enum long_option_t {
-      OPT_LIBYATL_VERSION,
-      OPT_LIBYATL_MATCH_COLLECTION,
-      OPT_LIBYATL_MASSIVE,
-      OPT_LIBYATL_QUIET,
-      OPT_LIBYATL_MATCH_WILDCARD,
-      OPT_LIBYATL_REPEAT
-    };
-
-    static struct option long_options[]=
-    {
-      { "version", no_argument, NULL, OPT_LIBYATL_VERSION },
-      { "quiet", no_argument, NULL, OPT_LIBYATL_QUIET },
-      { "repeat", required_argument, NULL, OPT_LIBYATL_REPEAT },
-      { "collection", required_argument, NULL, OPT_LIBYATL_MATCH_COLLECTION },
-      { "wildcard", required_argument, NULL, OPT_LIBYATL_MATCH_WILDCARD },
-      { "massive", no_argument, NULL, OPT_LIBYATL_MASSIVE },
-      { 0, 0, 0, 0 }
-    };
-
-    int option_index= 0;
-    while (1)
-    {
-      int option_rv= getopt_long(argc, argv, "", long_options, &option_index);
-      if (option_rv == -1)
-      {
-        break;
-      }
-
-      switch (option_rv)
-      {
-      case OPT_LIBYATL_VERSION:
-        break;
-
-      case OPT_LIBYATL_QUIET:
-        opt_quiet= true;
-        break;
-
-      case OPT_LIBYATL_REPEAT:
-        errno= 0;
-        opt_repeat= strtoul(optarg, (char **) NULL, 10);
-        if (errno != 0)
-        {
-          Error << "unknown value passed to --repeat: `" << optarg << "`";
-          exit(EXIT_FAILURE);
-        }
-        break;
-
-      case OPT_LIBYATL_MATCH_COLLECTION:
-        collection_to_run= optarg;
-        break;
-
-      case OPT_LIBYATL_MATCH_WILDCARD:
-        wildcard= optarg;
-        break;
-
-      case OPT_LIBYATL_MASSIVE:
-        opt_massive= true;
-        break;
-
-      case '?':
-        /* getopt_long already printed an error message. */
-        Error << "unknown option to getopt_long()";
-        exit(EXIT_FAILURE);
-
-      default:
-        break;
-      }
-    }
-  }
-
-  srandom((unsigned int)time(NULL));
-
-  errno= 0;
-  if (bool(getenv("YATL_REPEAT")))
-  {
-    errno= 0;
-    opt_repeat= strtoul(getenv("YATL_REPEAT"), (char **) NULL, 10);
-    if (errno != 0)
-    {
-      Error << "ENV YATL_REPEAT passed an invalid value: `" << getenv("YATL_REPEAT") << "`";
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  if ((bool(getenv("YATL_QUIET")) and (strcmp(getenv("YATL_QUIET"), "0") == 0)) or opt_quiet)
-  {
-    opt_quiet= true;
-  }
-  else if (getenv("JENKINS_URL"))
-  {
-    if (bool(getenv("YATL_QUIET")) and (strcmp(getenv("YATL_QUIET"), "1") == 0))
-    { }
-    else
-    {
-      opt_quiet= true;
-    }
-  }
-
-  if ((bool(getenv("YATL_RUN_MASSIVE_TESTS"))) or opt_massive)
-  {
-    opt_massive= true;
-  }
-
-  if (opt_quiet)
-  {
-    close(STDOUT_FILENO);
-  }
-
-  if (opt_massive)
-  {
-    is_massive(opt_massive);
-  }
-
-  libtest::vchar_t tmp_directory;
-  tmp_directory.resize(1024);
-  if (getenv("LIBTEST_TMP"))
-  {
-    snprintf(&tmp_directory[0], tmp_directory.size(), "%s", getenv("LIBTEST_TMP"));
-  }
-  else
-  {
-    snprintf(&tmp_directory[0], tmp_directory.size(), "%s", LIBTEST_TEMP);
-  }
-
-  if (chdir(&tmp_directory[0]) == -1)
-  {
-    libtest::vchar_t getcwd_buffer;
-    getcwd_buffer.resize(1024);
-    char *dir= getcwd(&getcwd_buffer[0], getcwd_buffer.size());
-
-    Error << "Unable to chdir() from " << dir << " to " << &tmp_directory[0] << " errno:" << strerror(errno);
-    return EXIT_FAILURE;
-  }
-
-  if (getenv("YATL_COLLECTION_TO_RUN"))
-  {
-    if (strlen(getenv("YATL_COLLECTION_TO_RUN")))
-    {
-      collection_to_run= getenv("YATL_COLLECTION_TO_RUN");
-    }
-  }
-
-  if (collection_to_run.compare("none") == 0)
-  {
-    return EXIT_SUCCESS;
-  }
-
-  if (collection_to_run.empty() == false)
-  {
-    Out << "Only testing " <<  collection_to_run;
-  }
-
-  int exit_code;
-
-  try 
-  {
-    do
-    {
-      exit_code= EXIT_SUCCESS;
-      fatal_assert(sigignore(SIGPIPE) == 0);
-
-      libtest::SignalThread signal;
-      if (signal.setup() == false)
-      {
-        Error << "Failed to setup signals";
-        return EXIT_FAILURE;
-      }
-
-      UNIQUE_PTR<libtest::Framework> frame(new libtest::Framework(signal, binary_name, collection_to_run, wildcard));
-
-      // Run create(), bail on error.
-      {
-        switch (frame->create())
-        {
-        case TEST_SUCCESS:
-          break;
-
-        case TEST_SKIPPED:
-          SKIP("SKIP was returned from framework create()");
-          break;
-
-        case TEST_FAILURE:
-          std::cerr << "Could not call frame->create()" << std::endl;
-          return EXIT_FAILURE;
-        }
-      }
-
-      frame->exec();
-
-      if (signal.is_shutdown() == false)
-      {
-        signal.set_shutdown(SHUTDOWN_GRACEFUL);
-      }
-
-      shutdown_t status= signal.get_shutdown();
-      if (status == SHUTDOWN_FORCED)
-      {
-        Out << "Tests were aborted.";
-        exit_code= EXIT_FAILURE;
-      }
-      else if (frame->failed())
-      {
-        Out << "Some test failed.";
-        exit_code= EXIT_FAILURE;
-      }
-      else if (frame->skipped() and frame->failed() and frame->success())
-      {
-        Out << "Some tests were skipped.";
-      }
-      else if (frame->success() and (frame->failed() == 0))
-      {
-        Out;
-        Out << "All tests completed successfully.";
-      }
-
-      stats_print(frame.get());
-
-      std::ofstream xml_file;
-      std::string file_name;
-      file_name.append(&tmp_directory[0]);
-      file_name.append(frame->name());
-      file_name.append(".xml");
-      xml_file.open(file_name.c_str(), std::ios::trunc);
-      libtest::Formatter::xml(*frame, xml_file);
-
-      Outn(); // Generate a blank to break up the messages if make check/test has been run
-    } while (exit_code == EXIT_SUCCESS and --opt_repeat);
-  }
-  catch (const libtest::__skipped& e)
-  {
-    return EXIT_SKIP;
-  }
-  catch (const libtest::__failure& e)
-  {
-    libtest::stream::make_cout(e.file(), e.line(), e.func()) << e.what();
-    exit_code= EXIT_FAILURE;
-  }
-  catch (const libtest::fatal& e)
-  {
-    std::cerr << "FATAL:" << e.what() << std::endl;
-    exit_code= EXIT_FAILURE;
-  }
-  catch (const libtest::disconnected& e)
-  {
-    std::cerr << "Unhandled disconnection occurred:" << e.what() << std::endl;
-    exit_code= EXIT_FAILURE;
-  }
-  catch (const std::exception& e)
-  {
-    std::cerr << "std::exception:" << e.what() << std::endl;
-    exit_code= EXIT_FAILURE;
-  }
-  catch (char const* s)
-  {
-    std::cerr << "Exception:" << s << std::endl;
-    exit_code= EXIT_FAILURE;
-  }
-  catch (...)
-  {
-    std::cerr << "Unknown exception halted execution." << std::endl;
-    exit_code= EXIT_FAILURE;
-  }
-
-  return exit_code;
-}
diff --git a/libtest/memcached.cc b/libtest/memcached.cc
deleted file mode 100644 (file)
index caeb11c..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include "libtest/common.h"
-
-#include <cassert>
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <iostream>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <libtest/server.h>
-#include <libtest/wait.h>
-
-#include <libtest/memcached.h>
-
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
-
-namespace libtest {
-
-class Memcached : public libtest::Server
-{
-  std::string _username;
-  std::string _password;
-
-public:
-  Memcached(const std::string& host_arg,
-            const in_port_t port_arg,
-            const bool is_socket_arg,
-            const std::string& username_arg,
-            const std::string& password_arg) :
-    libtest::Server(host_arg, port_arg, 
-                    memcached_binary(), false, is_socket_arg),
-    _username(username_arg),
-    _password(password_arg)
-  { }
-
-  Memcached(const std::string& host_arg, const in_port_t port_arg, const bool is_socket_arg) :
-    libtest::Server(host_arg, port_arg,
-                    memcached_binary(), false, is_socket_arg)
-  {
-    set_pid_file();
-  }
-
-  virtual const char *sasl() const
-  {
-    return "-S";
-  }
-
-  bool is_sasl() const
-  {
-    return _username.size() && _password.size();
-  }
-
-  const std::string& password() const
-  {
-    return _password;
-  }
-
-  const std::string& username() const
-  {
-    return _username;
-  }
-
-  bool wait_for_pidfile() const
-  {
-    Wait wait(pid(), 4);
-
-    return wait.successful();
-  }
-
-  bool ping()
-  {
-    if (out_of_ban_killed())
-    {
-      return false;
-    }
-
-    if (is_socket() or is_sasl())
-    {
-      return _app.check();
-    }
-
-    SimpleClient client(_hostname, _port);
-
-    std::string response;
-    return client.send_message("version", response);
-  }
-
-  const char *name()
-  {
-    return "memcached";
-  };
-
-  const char *executable()
-  {
-    return memcached_binary();
-  }
-
-  bool is_libtool()
-  {
-    return false;
-  }
-
-  virtual void pid_file_option(Application& app, const std::string& arg)
-  {
-    if (arg.empty() == false)
-    {
-      app.add_option("-P", arg);
-    }
-  }
-
-  const char *socket_file_option() const
-  {
-    return "-s ";
-  }
-
-  virtual void port_option(Application& app, in_port_t arg)
-  {
-    char buffer[30];
-    snprintf(buffer, sizeof(buffer), "%d", int(arg));
-    app.add_option("-p", buffer);
-
-    if(!is_sasl())
-    {
-      app.add_option("-U", buffer);
-    }
-  }
-
-  bool has_port_option() const
-  {
-    return true;
-  }
-
-  bool has_socket_file_option() const
-  {
-    return has_socket();
-  }
-
-  void socket_file_option(Application& app, const std::string& socket_arg)
-  {
-    if (socket_arg.empty() == false)
-    {
-      app.add_option("-s", socket_arg);
-    }
-  }
-
-  bool broken_socket_cleanup()
-  {
-    return true;
-  }
-
-  // Memcached's pidfile is broken
-  bool broken_pid_file()
-  {
-    return true;
-  }
-
-  bool build();
-};
-
-
-#include <sstream>
-
-bool Memcached::build()
-{
-  if (getuid() == 0 or geteuid() == 0)
-  {
-    add_option("-u", "root");
-  }
-
-  add_option("-l", "localhost");
-#ifdef __APPLE__
-#else
-  add_option("-m", "128");
-  add_option("-M");
-#endif
-
-  if (is_sasl())
-  {
-    add_option(sasl());
-  }
-
-  //add_option("-vvv");
-
-  return true;
-}
-
-libtest::Server *build_memcached(const std::string& hostname, const in_port_t try_port)
-{
-  if (has_memcached())
-  {
-    return new Memcached(hostname, try_port, false);
-  }
-
-  return NULL;
-}
-
-libtest::Server *build_memcached_socket(const std::string& socket_file, const in_port_t try_port)
-{
-  if (has_memcached())
-  {
-    return new Memcached(socket_file, try_port, true);
-  }
-
-  return NULL;
-}
-
-libtest::Server *build_memcached_sasl(const std::string &hostname, const in_port_t try_port, const std::string &username, const std::string &password)
-{
-  if (has_memcached())
-  {
-    return new Memcached(hostname, try_port, false, username, password);
-  }
-
-  return NULL;
-}
-
-} // namespace libtest
diff --git a/libtest/memcached.h b/libtest/memcached.h
deleted file mode 100644 (file)
index 7dc9c4d..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-libtest::Server *build_memcached(const std::string& hostname, const in_port_t try_port);
-
-libtest::Server *build_memcached_socket(const std::string& socket_file, const in_port_t try_port);
-
-libtest::Server *build_memcached_sasl(const std::string &hostname, const in_port_t try_port, const std::string &username, const std::string &password);
-
-}
-
diff --git a/libtest/memcached.hpp b/libtest/memcached.hpp
deleted file mode 100644 (file)
index 5d010fa..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#if defined(HAVE_LIBMEMCACHED) && HAVE_LIBMEMCACHED
-inline bool operator== (const memcached_st& memc, const memcached_return_t rc)
-{
-  if (memcached_last_error(const_cast<memcached_st *>(&memc)) == rc)
-  {
-    return true;
-  }
-
-  return false;
-}
-
-inline bool operator!= (const memcached_st& memc, memcached_return_t rc)
-{
-  if (memcached_last_error(const_cast<memcached_st *>(&memc)) != rc)
-  {
-    return true;
-  }
-
-  return false;
-}
-
-inline bool operator== (memcached_st* const memc, memcached_return_t rc)
-{
-  if (memcached_last_error(memc) == rc)
-  {
-    return true;
-  }
-
-  return false;
-}
-
-inline bool operator!= (memcached_st* const memc, memcached_return_t rc)
-{
-  if (memcached_last_error(memc) != rc)
-  {
-    return true;
-  }
-
-  return false;
-}
-
-inline bool operator!= (memcached_return_t rc, const memcached_st& memc)
-{
-  if (memcached_last_error(const_cast<memcached_st *>(&memc)) != rc)
-  {
-    return true;
-  }
-
-  return false;
-}
-
-inline bool operator!= (memcached_return_t rc, memcached_st* const memc)
-{
-  if (memcached_last_error(memc) != rc)
-  {
-    return true;
-  }
-
-  return false;
-}
-#endif
-
diff --git a/libtest/poll_error.hpp b/libtest/poll_error.hpp
deleted file mode 100644 (file)
index b75066f..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
-  Structures for generic tests.
-*/
-
-#include <cstdio>
-#include <poll.h>
-
-void print_poll(pollfd& fds)
-{
-  if (fds.revents & POLLERR)
-  {
-    fprintf(stderr, "\tPOLLERR\n");
-  }
-
-  if (fds.revents & POLLHUP)
-  {
-    fprintf(stderr, "\tPOLLHUP\n");
-  }
-
-  if (fds.revents & POLLIN)
-  {
-    fprintf(stderr, "\tPOLLIN\n");
-  }
-
-  if (fds.revents & POLLIN)
-  {
-    fprintf(stderr, "\tPOLLIN\n");
-  }
-
-  if (fds.revents & POLLNVAL)
-  {
-    fprintf(stderr, "\tPOLLNVAL\n");
-  }
-
-  if (fds.revents & POLLOUT)
-  {
-    fprintf(stderr, "\tPOLLOUT\n");
-  }
-
-  if (fds.revents & POLLPRI)
-  {
-    fprintf(stderr, "\tPOLLPRI\n");
-  }
-
-  if (fds.revents & POLLRDBAND)
-  {
-    fprintf(stderr, "\tPOLLPRI\n");
-  }
-
-  if (fds.revents & POLLRDNORM)
-  {
-    fprintf(stderr, "\tPOLLRDNORM\n");
-  }
-
-  if (fds.revents & POLLWRBAND)
-  {
-    fprintf(stderr, "\tPOLLWRBAND\n");
-  }
-
-  if (fds.revents & POLLWRNORM)
-  {
-    fprintf(stderr, "\tPOLLWRNORM\n");
-  }
-}
diff --git a/libtest/port.cc b/libtest/port.cc
deleted file mode 100644 (file)
index d8e8c12..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-#include <cassert>
-#include <cstdlib>
-#include <cstring>
-#include <ctime>
-#include <fnmatch.h>
-#include <iostream>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h> 
-#include <sys/wait.h>
-#include <unistd.h>
-
-#include <utility>
-#include <vector>
-
-#include <signal.h>
-
-#include <libtest/signal.h>
-
-#ifndef SOCK_CLOEXEC 
-#  define SOCK_CLOEXEC 0
-#endif
-
-#ifndef SOCK_NONBLOCK 
-#  define SOCK_NONBLOCK 0
-#endif
-
-#ifndef FD_CLOEXEC
-#  define FD_CLOEXEC 0
-#endif
-
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
-
-using namespace libtest;
-
-struct socket_st {
-  typedef std::vector< std::pair< int, in_port_t> > socket_port_t;
-  socket_port_t _pair;
-  in_port_t last_port;
-
-  socket_st():
-    last_port(0)
-  { }
-
-  void release(in_port_t _arg)
-  {
-    for (socket_port_t::iterator iter= _pair.begin();
-         iter != _pair.end();
-         ++iter)
-    {
-      if ((*iter).second == _arg)
-      {
-        shutdown((*iter).first, SHUT_RDWR);
-        close((*iter).first);
-      }
-    }
-  }
-
-  ~socket_st()
-  {
-    for (socket_port_t::iterator iter= _pair.begin();
-         iter != _pair.end();
-         ++iter)
-    {
-      shutdown((*iter).first, SHUT_RDWR);
-      close((*iter).first);
-    }
-  }
-};
-
-static socket_st all_socket_fd;
-
-static in_port_t global_port= 0;
-
-namespace libtest {
-
-in_port_t default_port()
-{
-  if (global_port == 0)
-  {
-    global_port= get_free_port();
-  }
-
-  return global_port;
-}
-
-void release_port(in_port_t arg)
-{
-  all_socket_fd.release(arg);
-}
-
-in_port_t get_free_port()
-{
-  const in_port_t default_port= in_port_t(-1);
-
-  int retries= 1024;
-
-  in_port_t ret_port;
-  while (--retries)
-  {
-    ret_port= default_port;
-    int sd;
-    if ((sd= socket(AF_INET, SOCK_STREAM, 0)) != SOCKET_ERROR)
-    {
-      int optval= 1;
-      if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != SOCKET_ERROR)
-      { 
-        struct sockaddr_in sin;
-        sin.sin_port= 0;
-        sin.sin_addr.s_addr= 0;
-        sin.sin_addr.s_addr= INADDR_ANY;
-        sin.sin_family= AF_INET;
-
-        int bind_ret;
-        do
-        {
-          if ((bind_ret= bind(sd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in) )) != SOCKET_ERROR)
-          {
-            socklen_t addrlen= sizeof(sin);
-
-            if (getsockname(sd, (struct sockaddr *)&sin, &addrlen) != -1)
-            {
-              ret_port= sin.sin_port;
-            }
-          }
-          else
-          {
-            if (errno != EADDRINUSE)
-            {
-              Error << strerror(errno);
-            }
-          }
-
-          if (errno == EADDRINUSE)
-          {
-            libtest::dream(2, 0);
-          }
-        } while (bind_ret == -1 and errno == EADDRINUSE);
-
-        all_socket_fd._pair.push_back(std::make_pair(sd, ret_port));
-      }
-      else
-      {
-        Error << strerror(errno);
-      }
-    }
-    else
-    {
-      Error << strerror(errno);
-    }
-
-    if (ret_port == default_port)
-    {
-      Error << "no ret_port set:" << strerror(errno);
-    }
-    else if (ret_port > 1024 and ret_port != all_socket_fd.last_port)
-    {
-      break;
-    }
-  }
-
-  // We handle the case where if we max out retries, we still abort.
-  if (retries == 0)
-  {
-    FATAL("No port could be found, exhausted retry");
-  }
-
-  if (ret_port == 0)
-  {
-    FATAL("No port could be found");
-  }
-
-  if (ret_port == default_port)
-  {
-    FATAL("No port could be found");
-  }
-
-  if (ret_port <= 1024)
-  {
-    FATAL("No port could be found, though some where available below or at 1024");
-  }
-
-  all_socket_fd.last_port= ret_port;
-  release_port(ret_port);
-
-  return ret_port;
-}
-
-} // namespace libtest
diff --git a/libtest/port.h b/libtest/port.h
deleted file mode 100644 (file)
index 55cef53..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
-  Structures for generic tests.
-*/
-
-#pragma once
-
-#define LIBTEST_FAIL_PORT 23
-
-namespace libtest {
-
-LIBTEST_API
-in_port_t default_port();
-
-LIBTEST_API
-in_port_t get_free_port();
-
-LIBTEST_API
-void release_port(in_port_t arg);
-
-} // namespace libtest
diff --git a/libtest/result.cc b/libtest/result.cc
deleted file mode 100644 (file)
index 3e4523d..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-#include <cstdarg>
-
-namespace libtest {
-
-__test_result::__test_result(const char *file_arg, int line_arg, const char *func_arg):
-  libtest::exception(file_arg, line_arg, func_arg)
-  {
-  }
-
-__success::__success(const char *file_arg, int line_arg, const char *func_arg):
-  __test_result(file_arg, line_arg, func_arg)
-{
-}
-
-__skipped::__skipped(const char *file_arg, int line_arg, const char *func_arg, ...):
-  __test_result(file_arg, line_arg, func_arg)
-{
-  va_list args;
-  va_start(args, func_arg);
-  init(args);
-  va_end(args);
-}
-
-__skipped::__skipped(const __skipped& other) :
-  __test_result(other)
-{
-}
-
-__failure::__failure(const char *file_arg, int line_arg, const char *func_arg, ...) :
-  __test_result(file_arg, line_arg, func_arg)
-{
-  va_list args;
-  va_start(args, func_arg);
-  init(args);
-  va_end(args);
-}
-
-__failure::__failure(const __failure& other) :
-  __test_result(other)
-{
-}
-
-
-} // namespace libtest
diff --git a/libtest/result.hpp b/libtest/result.hpp
deleted file mode 100644 (file)
index 79acbb4..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <libtest/result/base.hpp>
-#include <libtest/result/fail.hpp>
-#include <libtest/result/skip.hpp>
-#include <libtest/result/success.hpp>
-
-#define _SUCCESS throw libtest::__success(LIBYATL_DEFAULT_PARAM)
-
-#define SKIP(...) \
-do \
-{ \
-  throw libtest::__skipped(LIBYATL_DEFAULT_PARAM, __VA_ARGS__); \
-} while (0)
-
-#define FAIL(...) \
-do \
-{ \
-  throw libtest::__failure(LIBYATL_DEFAULT_PARAM, __VA_ARGS__); \
-} while (0)
diff --git a/libtest/result/base.hpp b/libtest/result/base.hpp
deleted file mode 100644 (file)
index 5f093f8..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include "libtest/exception.hpp"
-#include "libtest/error.h"
-
-namespace libtest {
-
-class __test_result : public libtest::exception
-{
-public:
-  __test_result(const char *file, int line, const char *func);
-
-  virtual test_return_t return_code() const= 0;
-
-private:
-};
-
-} // namespace libtest
diff --git a/libtest/result/fail.hpp b/libtest/result/fail.hpp
deleted file mode 100644 (file)
index 3aec9c1..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-class __failure : public __test_result
-{
-public:
-  __failure(const char *file, int line, const char *func, ...);
-
-  __failure(const __failure&);
-
-  test_return_t return_code() const
-  {
-    return TEST_FAILURE;
-  }
-
-private:
-};
-
-} // namespace libtest
diff --git a/libtest/result/skip.hpp b/libtest/result/skip.hpp
deleted file mode 100644 (file)
index 7409d71..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-class __skipped : public __test_result
-{
-public:
-  __skipped(const char *file, int line, const char *func, ...);
-
-  __skipped(const __skipped&);
-
-  test_return_t return_code() const
-  {
-    return TEST_SKIPPED;
-  }
-};
-
-} // namespace libtest
diff --git a/libtest/result/success.hpp b/libtest/result/success.hpp
deleted file mode 100644 (file)
index a34e677..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-class __success : public __test_result
-{
-public:
-  __success(const char *file, int line, const char *func);
-
-  const char* what() const throw()
-  {
-    return "SUCCESS";
-  }
-
-  test_return_t return_code() const
-  {
-    return TEST_SUCCESS;
-  }
-
-private:
-};
-
-} // namespace libtest
diff --git a/libtest/run-ci.gdb b/libtest/run-ci.gdb
deleted file mode 100644 (file)
index 20724b0..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-set logging on
-set logging overwrite on
-set environment LIBTEST_IN_GDB=1
-set ASAN_OPTIONS=abort_on_error=1
-run
-thread apply all bt
-quit
diff --git a/libtest/run.gdb b/libtest/run.gdb
deleted file mode 100644 (file)
index c35ab76..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-set logging on
-set logging overwrite on
-set environment LIBTEST_IN_GDB=1
-#set ASAN_OPTIONS=abort_on_error=1
-handle SIGVTALRM stop
-run
-thread apply all bt
diff --git a/libtest/runner.cc b/libtest/runner.cc
deleted file mode 100644 (file)
index 2f94ad3..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-namespace libtest {
-
-Runner::Runner() :
-  _servers(NULL)
-{
-}
-
-test_return_t Runner::main(test_callback_fn* func, void *object)
-{
-  test_return_t ret;
-  try {
-    ret= run(func, object);
-  }
-  catch (const libtest::__skipped& e)
-  {
-    ret= TEST_SKIPPED;
-  }
-  catch (const libtest::__failure& e)
-  {
-    libtest::stream::make_cerr(e.file(), e.line(), e.func()) << e.what();
-    ret= TEST_FAILURE;
-  }
-  catch (const libtest::__success&)
-  {
-    ret= TEST_SUCCESS;
-  }
-  catch (const libtest::fatal&)
-  {
-    throw;
-  }
-  catch (const std::exception& e)
-  {
-    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << e.what();
-    throw;
-  }
-  catch (...)
-  {
-    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << "Unknown exception thrown";
-    throw;
-  }
-
-  return ret;
-}
-
-test_return_t Runner::setup(test_callback_fn* func, void *object)
-{
-  test_return_t ret;
-  try {
-    ret= pre(func, object);
-  }
-  catch (const libtest::__skipped& e)
-  {
-    ret= TEST_SKIPPED;
-  }
-  catch (const libtest::__failure& e)
-  {
-    libtest::stream::make_cout(e.file(), e.line(), e.func()) << e.what();
-    ret= TEST_FAILURE;
-  }
-  catch (const libtest::__success&)
-  {
-    ret= TEST_SUCCESS;
-  }
-  catch (const libtest::fatal& e)
-  {
-    throw;
-  }
-  catch (const std::exception& e)
-  {
-    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << e.what();
-    throw;
-  }
-  catch (...)
-  {
-    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << "Unknown exception thrown";
-    throw;
-  }
-
-  return ret;
-}
-
-test_return_t Runner::teardown(test_callback_fn* func, void *object)
-{
-  test_return_t ret;
-  try {
-    ret= post(func, object);
-  }
-  catch (const libtest::__skipped& e)
-  {
-    ret= TEST_SKIPPED;
-  }
-  catch (const libtest::__failure& e)
-  {
-    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << e.what();
-    ret= TEST_FAILURE;
-  }
-  catch (const libtest::__success&)
-  {
-    ret= TEST_SUCCESS;
-  }
-  catch (const libtest::fatal& e)
-  {
-    throw;
-  }
-  catch (const std::exception& e)
-  {
-    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << e.what();
-    throw;
-  }
-  catch (...)
-  {
-    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << "Unknown exception thrown";
-    throw;
-  }
-
-  return ret;
-}
-
-test_return_t Runner::flush(void*)
-{
-  return TEST_SUCCESS;
-}
-
-test_return_t Runner::run(test_callback_fn* func, void *object)
-{
-  if (func)
-  {
-    return func(object);
-  }
-
-  return TEST_SUCCESS;
-}
-
-test_return_t Runner::pre(test_callback_fn* func, void *object)
-{
-  if (func)
-  {
-    return func(object);
-  }
-
-  return TEST_SUCCESS;
-}
-
-test_return_t Runner::post(test_callback_fn* func, void *object)
-{
-  if (func)
-  {
-    return func(object);
-  }
-
-  return TEST_SUCCESS;
-}
-
-void Runner::set_servers(libtest::server_startup_st& arg)
-{
-  _servers= &arg;
-}
-
-bool Runner::check()
-{
-  return _servers ? _servers->check() : true;
-}
-
-} // namespace libtest
diff --git a/libtest/runner.h b/libtest/runner.h
deleted file mode 100644 (file)
index 627a0a8..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-namespace libtest {
-
-/**
-  Structure which houses the actual callers for the test cases contained in
-  the collections.
-*/
-class Runner {
-public:
-  test_return_t main(test_callback_fn* func, void *object);
-  test_return_t setup(test_callback_fn* func, void *object);
-  test_return_t teardown(test_callback_fn* func, void *object);
-
-  Runner();
-
-  void set_servers(libtest::server_startup_st& arg);
-
-  bool check();
-
-  virtual ~Runner() { }
-
-  virtual test_return_t flush(void*);
-  virtual test_return_t run(test_callback_fn* func, void *object);
-  virtual test_return_t pre(test_callback_fn* func, void *object);
-  virtual test_return_t post(test_callback_fn* func, void *object);
-
-private:
-  libtest::server_startup_st* _servers;
-
-private:
-  Runner( const Runner& );
-  const Runner& operator=( const Runner& );
-};
-
-} // namespace Runner
diff --git a/libtest/server.cc b/libtest/server.cc
deleted file mode 100644 (file)
index bfb265c..0000000
+++ /dev/null
@@ -1,532 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include <libtest/common.h>
-
-#include <cassert>
-#include <cerrno>
-#include <climits>
-#include <cstdlib>
-#include <iostream>
-#include <string>
-
-#include <algorithm> 
-#include <functional> 
-#include <locale>
-#include <unistd.h>
-
-// trim from end 
-static inline std::string &rtrim(std::string &s)
-{ 
-  s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end()); 
-  return s; 
-}
-
-#include <libtest/server.h>
-#include <libtest/stream.h>
-#include <libtest/killpid.h>
-
-namespace libtest {
-
-std::ostream& operator<<(std::ostream& output, const Server &arg)
-{
-  if (arg.is_socket())
-  {
-    output << arg.hostname();
-  }
-  else
-  {
-    output << arg.hostname() << ":" << arg.port();
-  }
-
-  if (arg.has_pid())
-  {
-    output << " Pid:" <<  arg.pid();
-  }
-
-  if (arg.has_socket())
-  {
-    output << " Socket:" <<  arg.socket();
-  }
-
-  if (arg.running().empty() == false)
-  {
-    output << " Exec:" <<  arg.running();
-  }
-
-  return output;  // for multiple << operators
-}
-
-#ifdef __GLIBC__
-namespace {
-
-class Buffer
-{
-public:
-  Buffer(char *b) : b_(b) {}
-   ~Buffer() { if (b_) free(b_); }
-  char* buf() { return b_; }
-private:
-  char *b_;
-};
-
-}
-#endif // __GLIBC__
-
-#define MAGIC_MEMORY 123570
-
-Server::Server(const std::string& host_arg, const in_port_t port_arg,
-               const std::string& executable, const bool _is_libtool,
-               bool is_socket_arg) :
-  _magic(MAGIC_MEMORY),
-  _is_socket(is_socket_arg),
-  _port(port_arg),
-  _hostname(host_arg),
-  _app(executable, _is_libtool),
-  out_of_ban_killed_(false),
-  _timeout(40)
-{
-}
-
-Server::~Server()
-{
-  kill();
-}
-
-bool Server::check()
-{
-  _app.clear();
-  return _app.check();
-}
-
-bool Server::validate()
-{
-  return _magic == MAGIC_MEMORY;
-}
-
-// If the server exists, kill it
-bool Server::cycle()
-{
-  uint32_t limit= 3;
-
-  // Try to ping, and kill the server #limit number of times
-  while (--limit and 
-         is_pid_valid(_app.pid()))
-  {
-    if (kill())
-    {
-      Log << "Killed existing server," << *this;
-      dream(0, 50000);
-      continue;
-    }
-  }
-
-  // For whatever reason we could not kill it, and we reached limit
-  if (limit == 0)
-  {
-    Error << "Reached limit, could not kill server";
-    return false;
-  }
-
-  return true;
-}
-
-bool Server::wait_for_pidfile() const
-{
-  Wait wait(pid_file(), 4);
-
-  return wait.successful();
-}
-
-bool Server::init(const char *argv[])
-{
-  if (argv)
-  {
-    for (const char **ptr= argv; *ptr ; ++ptr)
-    {
-      if (ptr)
-      {
-        add_option(*ptr);
-      }
-    }
-  }
-
-  return build();
-}
-
-bool Server::has_pid() const
-{
-  return (_app.pid() > 1);
-}
-
-
-bool Server::start()
-{
-  if (getenv("YATL_GDB_SERVER"))
-  {
-    _app.use_gdb(true);
-  }
-
-  if (port() == LIBTEST_FAIL_PORT)
-  {
-    throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
-                                hostname(), port(), "Called failure");
-  }
-
-  if (getenv("YATL_PTRCHECK_SERVER"))
-  {
-    _app.use_ptrcheck(true);
-  }
-  else if (getenv("YATL_VALGRIND_SERVER"))
-  {
-    _app.use_valgrind(true);
-  }
-
-  out_of_ban_killed(false);
-  if (args(_app) == false)
-  {
-    throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
-                                hostname(), port(), "Could not build command()");
-  }
-
-  libtest::release_port(_port);
-
-  Application::error_t ret;
-  if (Application::SUCCESS !=  (ret= _app.run()))
-  {
-    throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
-                                hostname(), port(), "Application::run() %s", libtest::Application::toString(ret));
-    return false;
-  }
-  _running= _app.print();
-
-  if (valgrind_is_caller())
-  {
-    dream(5, 50000);
-  }
-
-  size_t repeat= 5;
-  _app.slurp();
-  while (--repeat)
-  {
-    if (pid_file().empty() == false)
-    {
-      Wait wait(pid_file(), 8);
-
-      if (wait.successful() == false)
-      {
-        if (_app.check())
-        {
-          _app.slurp();
-          continue;
-        }
-
-#ifdef __GLIBC__
-        Buffer buf( get_current_dir_name());
-        char *getcwd_buf= buf.buf();
-#else
-        libtest::vchar_t buf;
-        buf.resize(PATH_MAX);
-        char *getcwd_buf= getcwd(&buf[0], buf.size());
-#endif // __GLIBC__
-        throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
-                                    hostname(), port(),
-                                    "Unable to open pidfile in %s for: %s stderr:%s",
-                                    getcwd_buf ? getcwd_buf : "",
-                                    _running.c_str(),
-                                    _app.stderr_c_str());
-      }
-    }
-  }
-
-  bool pinged= false;
-  uint32_t this_wait= 0;
-  {
-    uint32_t waited;
-    uint32_t retry;
-
-    for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
-    {
-      if (_app.check() == false)
-      {
-        break;
-      }
-
-      if ((pinged= ping()) == true)
-      {
-        break;
-      }
-      else if (waited >= _timeout)
-      {
-        break;
-      }
-
-      this_wait= retry * retry / 3 + 1;
-      libtest::dream(this_wait, 0);
-    }
-  }
-
-  if (pinged == false)
-  {
-#if 0
-    Error << "Failed to ping(" << _app.pid() << ") wait: " << this_wait << " " << hostname() << ":" << port() << " run:" << _running << " " << error();
-#endif
-
-    // If we happen to have a pid file, lets try to kill it
-    if ((pid_file().empty() == false) and (access(pid_file().c_str(), R_OK) == 0))
-    {
-      _app.slurp();
-      if (kill_file(pid_file()) == false)
-      {
-        throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
-                                    hostname(), port(),
-                                    "Failed to kill off server, waited: %u after startup occurred, when pinging failed: %.*s stderr:%.*s",
-                                    this_wait,
-                                    int(_running.size()), _running.c_str(),
-                                    int(_app.stderr_result_length()), _app.stderr_c_str());
-      }
-      else
-      {
-        throw libtest::disconnected(LIBYATL_DEFAULT_PARAM, 
-                                    hostname(), port(),
-                                    "Failed native ping(), pid: %d was alive: %s waited: %u server started, having pid_file. exec: %.*s stderr:%.*s",
-                                    int(_app.pid()),
-                                    _app.check() ? "true" : "false",
-                                    this_wait,
-                                    int(_running.size()), _running.c_str(),
-                                    int(_app.stderr_result_length()), _app.stderr_c_str());
-      }
-    }
-    else
-    {
-      throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
-                                  hostname(), port(),
-                                  "Failed native ping(), pid: %d is alive: %s waited: %u server started. exec: %.*s stderr:%.*s",
-                                  int(_app.pid()),
-                                  _app.check() ? "true" : "false",
-                                  this_wait,
-                                  int(_running.size()), _running.c_str(),
-                                  int(_app.stderr_result_length()), _app.stderr_c_str());
-    }
-    _running.clear();
-
-    return false;
-  }
-
-  return has_pid();
-}
-
-void Server::reset_pid()
-{
-  _running.clear();
-  _pid_file.clear();
-}
-
-pid_t Server::pid() const
-{
-  return _app.pid();
-}
-
-void Server::add_option(const std::string& arg)
-{
-  _options.push_back(std::make_pair(arg, std::string()));
-}
-
-void Server::add_option(const std::string& name_, const std::string& value_)
-{
-  _options.push_back(std::make_pair(name_, value_));
-}
-
-bool Server::set_socket_file()
-{
-  libtest::vchar_t file_buffer;
-  file_buffer.resize(FILENAME_MAX);
-  file_buffer[0]= 0;
-
-  if (broken_pid_file())
-  {
-    snprintf(&file_buffer[0], file_buffer.size(), "/tmp/%s.socketXXXXXX", name());
-  }
-  else
-  {
-    snprintf(&file_buffer[0], file_buffer.size(), "var/run/%s.socketXXXXXX", name());
-  }
-
-  int fd;
-  if ((fd= mkstemp(&file_buffer[0])) == -1)
-  {
-    perror(&file_buffer[0]);
-    return false;
-  }
-  close(fd);
-  unlink(&file_buffer[0]);
-
-  _socket= &file_buffer[0];
-
-  return true;
-}
-
-bool Server::set_pid_file()
-{
-  libtest::vchar_t file_buffer;
-  file_buffer.resize(FILENAME_MAX);
-  file_buffer[0]= 0;
-
-  if (broken_pid_file())
-  {
-    snprintf(&file_buffer[0], file_buffer.size(), "/tmp/%s.pidXXXXXX", name());
-  }
-  else
-  {
-    snprintf(&file_buffer[0], file_buffer.size(), "var/run/%s.pidXXXXXX", name());
-  }
-
-  int fd;
-  if ((fd= mkstemp(&file_buffer[0])) == -1)
-  {
-    throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "mkstemp() failed on %s with %s", &file_buffer[0], strerror(errno));
-  }
-  close(fd);
-  unlink(&file_buffer[0]);
-
-  _pid_file= &file_buffer[0];
-
-  return true;
-}
-
-bool Server::set_log_file()
-{
-  libtest::vchar_t file_buffer;
-  file_buffer.resize(FILENAME_MAX);
-  file_buffer[0]= 0;
-
-  snprintf(&file_buffer[0], file_buffer.size(), "var/log/%s.logXXXXXX", name());
-  int fd;
-  if ((fd= mkstemp(&file_buffer[0])) == -1)
-  {
-    throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "mkstemp() failed on %s with %s", &file_buffer[0], strerror(errno));
-  }
-  close(fd);
-
-  _log_file= &file_buffer[0];
-
-  return true;
-}
-
-bool Server::args(Application& app)
-{
-
-  // Set a log file if it was requested (and we can)
-  if (has_log_file_option())
-  {
-    set_log_file();
-    log_file_option(app, _log_file);
-  }
-
-  if (getenv("LIBTEST_SYSLOG") and has_syslog())
-  {
-    app.add_option("--syslog");
-  }
-
-  // Update pid_file
-  {
-    if (_pid_file.empty() and set_pid_file() == false)
-    {
-      return false;
-    }
-
-    pid_file_option(app, pid_file());
-  }
-
-  if (has_socket_file_option())
-  {
-    if (set_socket_file() == false)
-    {
-      return false;
-    }
-
-    socket_file_option(app, _socket);
-  }
-
-  if (has_port_option())
-  {
-    port_option(app, _port);
-  }
-
-  for (Options::const_iterator iter= _options.begin(); iter != _options.end(); ++iter)
-  {
-    if ((*iter).first.empty() == false)
-    {
-      if ((*iter).second.empty() == false)
-      {
-        app.add_option((*iter).first, (*iter).second);
-      }
-      else
-      {
-        app.add_option((*iter).first);
-      }
-    }
-  }
-
-  return true;
-}
-
-bool Server::kill()
-{
-  if (check_pid(_app.pid())) // If we kill it, reset
-  {
-    _app.murder();
-    if (broken_pid_file() and pid_file().empty() == false)
-    {
-      unlink(pid_file().c_str());
-    }
-
-    if (broken_socket_cleanup() and has_socket() and not socket().empty())
-    {
-      unlink(socket().c_str());
-    }
-
-    reset_pid();
-
-    return true;
-  }
-
-  return false;
-}
-
-} // namespace libtest
diff --git a/libtest/server.h b/libtest/server.h
deleted file mode 100644 (file)
index 73ad3bf..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <libtest/cmdline.h>
-
-#include <cassert>
-#include <cstdio>
-#include <cstring>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <string>
-#include <unistd.h>
-#include <vector>
-
-namespace libtest {
-
-struct Server {
-private:
-  typedef std::vector< std::pair<std::string, std::string> > Options;
-
-private:
-  uint64_t _magic;
-  bool _is_socket;
-  std::string _socket;
-  std::string _sasl;
-  std::string _pid_file;
-  std::string _log_file;
-  std::string _base_command; // executable command which include libtool, valgrind, gdb, etc
-  std::string _running; // Current string being used for system()
-
-protected:
-  in_port_t _port;
-  std::string _hostname;
-  std::string _extra_args;
-
-public:
-  Server(const std::string& hostname, const in_port_t port_arg,
-         const std::string& executable, const bool _is_libtool,
-         const bool is_socket_arg= false);
-
-  virtual ~Server();
-
-  virtual const char *name()= 0;
-  virtual bool is_libtool()= 0;
-
-  virtual bool has_socket_file_option() const
-  {
-    return false;
-  }
-
-  virtual void socket_file_option(Application& app, const std::string& socket_arg)
-  {
-    if (socket_arg.empty() == false)
-    {
-      std::string buffer("--socket=");
-      buffer+= socket_arg;
-      app.add_option(buffer);
-    }
-  }
-
-  virtual bool has_log_file_option() const
-  {
-    return false;
-  }
-
-  virtual void log_file_option(Application& app, const std::string& arg)
-  {
-    if (arg.empty() == false)
-    {
-      std::string buffer("--log-file=");
-      buffer+= arg;
-      app.add_option(buffer);
-    }
-  }
-
-  virtual void pid_file_option(Application& app, const std::string& arg)
-  {
-    if (arg.empty() == false)
-    {
-      std::string buffer("--pid-file=");
-      buffer+= arg;
-      app.add_option(buffer);
-    }
-  }
-
-  virtual bool has_port_option() const
-  {
-    return false;
-  }
-
-  virtual void port_option(Application& app, in_port_t arg)
-  {
-    if (arg > 0)
-    {
-      char buffer[1024];
-      snprintf(buffer, sizeof(buffer), "--port=%d", int(arg));
-      app.add_option(buffer);
-    }
-  }
-
-  virtual bool broken_socket_cleanup()
-  {
-    return false;
-  }
-
-  virtual bool broken_pid_file()
-  {
-    return false;
-  }
-
-  const std::string& pid_file() const
-  {
-    return _pid_file;
-  }
-
-  const std::string& base_command() const
-  {
-    return _base_command;
-  }
-
-  const std::string& log_file() const
-  {
-    return _log_file;
-  }
-
-  const std::string& hostname() const
-  {
-    return _hostname;
-  }
-
-  const std::string& socket() const
-  {
-    return _socket;
-  }
-
-  bool has_socket() const
-  {
-    return _is_socket;
-  }
-
-  bool cycle();
-
-  virtual bool ping()= 0;
-
-  bool init(const char *argv[]);
-  virtual bool build()= 0;
-
-  void add_option(const std::string&);
-  void add_option(const std::string&, const std::string&);
-
-  in_port_t port() const
-  {
-    return _port;
-  }
-
-  bool has_port() const
-  {
-    return (_port != 0);
-  }
-
-  virtual bool has_syslog() const
-  {
-    return false;
-  }
-
-  // Reset a server if another process has killed the server
-  void reset()
-  {
-    _pid_file.clear();
-    _log_file.clear();
-  }
-
-  std::pair<std::string, std::string> output()
-  {
-    return _app.output();
-  }
-
-  pid_t pid() const;
-
-  bool has_pid() const;
-
-  virtual bool has_pid_file() const
-  {
-    return true;
-  }
-
-  const std::string& error()
-  {
-    return _error;
-  }
-
-  void error(std::string arg)
-  {
-    _error= arg;
-  }
-
-  void reset_error()
-  {
-    _error.clear();
-  }
-
-  virtual bool wait_for_pidfile() const;
-
-  bool check_pid(pid_t pid_arg) const
-  {
-    return (pid_arg > 1);
-  }
-
-  bool is_socket() const
-  {
-    return _is_socket;
-  }
-
-  const std::string running() const
-  {
-    return _running;
-  }
-
-  bool check();
-
-  std::string log_and_pid();
-
-  bool kill();
-  bool start();
-  bool command(libtest::Application& app);
-
-  bool validate();
-
-  void out_of_ban_killed(bool arg)
-  {
-    out_of_ban_killed_= arg;
-  }
-
-  bool out_of_ban_killed()
-  {
-    return out_of_ban_killed_;
-  }
-
-  void timeout(uint32_t timeout_)
-  {
-    _timeout= timeout_;
-  }
-
-protected:
-  bool set_pid_file();
-  Options _options;
-  Application _app;
-
-private:
-  bool is_helgrind() const;
-  bool is_valgrind() const;
-  bool is_debug() const;
-  bool set_log_file();
-  bool set_socket_file();
-  void reset_pid();
-  bool out_of_ban_killed_;
-  bool args(Application&);
-
-  std::string _error;
-  uint32_t _timeout; // This number should be high enough for valgrind startup (which is slow)
-};
-
-std::ostream& operator<<(std::ostream& output, const libtest::Server &arg);
-
-} // namespace libtest
-
-
diff --git a/libtest/server_container.cc b/libtest/server_container.cc
deleted file mode 100644 (file)
index e6d2f1d..0000000
+++ /dev/null
@@ -1,403 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include "libtest/common.h"
-
-#include <cerrno>
-#include <cstdlib>
-#include <iostream>
-
-#include <algorithm> 
-#include <functional> 
-#include <locale>
-
-// trim from end 
-static inline std::string &rtrim(std::string &s)
-{ 
-  s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end()); 
-  return s; 
-}
-
-namespace libtest {
-
-Server* server_startup_st::last()
-{
-  return servers.back();
-}
-
-void server_startup_st::push_server(Server *arg)
-{
-  servers.push_back(arg);
-
-  std::string server_config_string;
-  if (arg->has_socket())
-  {
-    server_config_string+= "--socket=";
-    server_config_string+= '"';
-    server_config_string+= arg->socket();
-    server_config_string+= '"';
-    server_config_string+= " ";
-  }
-  else
-  {
-    libtest::vchar_t port_str;
-    port_str.resize(NI_MAXSERV);
-    snprintf(&port_str[0], port_str.size(), "%u", int(arg->port()));
-
-    server_config_string+= "--server=";
-    server_config_string+= arg->hostname();
-    server_config_string+= ":";
-    server_config_string+= &port_str[0];
-    server_config_string+= " ";
-  }
-
-  server_list+= server_config_string;
-}
-
-Server* server_startup_st::pop_server()
-{
-  Server *tmp= servers.back();
-  servers.pop_back();
-  return tmp;
-}
-
-// host_to_shutdown => host number to shutdown in array
-bool server_startup_st::shutdown(uint32_t host_to_shutdown)
-{
-  if (servers.size() > host_to_shutdown)
-  {
-    Server* tmp= servers[host_to_shutdown];
-
-    if (tmp and tmp->kill() == false)
-    { }
-    else
-    {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-void server_startup_st::clear()
-{
-  std::for_each(servers.begin(), servers.end(), DeleteFromVector());
-  servers.clear();
-}
-
-bool server_startup_st::check() const
-{
-  bool success= true;
-  for (std::vector<Server *>::const_iterator iter= servers.begin(); iter != servers.end(); ++iter)
-  {
-    if ((*iter)->check()  == false)
-    {
-      success= false;
-    }
-  }
-
-  return success;
-}
-
-bool server_startup_st::shutdown()
-{
-  bool success= true;
-  for (std::vector<Server *>::iterator iter= servers.begin(); iter != servers.end(); ++iter)
-  {
-    if ((*iter)->has_pid() and (*iter)->kill() == false)
-    {
-      Error << "Unable to kill:" <<  *(*iter);
-      success= false;
-    }
-  }
-
-  return success;
-}
-
-void server_startup_st::restart()
-{
-  for (std::vector<Server *>::iterator iter= servers.begin(); iter != servers.end(); ++iter)
-  {
-    Server *server = *iter;
-
-    if (server->check()) {
-      server->kill();
-    }
-    server->start();
-  }
-}
-
-#define MAGIC_MEMORY 123575
-server_startup_st::server_startup_st() :
-  _magic(MAGIC_MEMORY),
-  _socket(false),
-  _sasl(false),
-  udp(0),
-  _servers_to_run(5)
-{ }
-
-server_startup_st::~server_startup_st()
-{
-  clear();
-}
-
-bool server_startup_st::validate()
-{
-  return _magic == MAGIC_MEMORY;
-}
-
-bool server_startup(server_startup_st& construct, const std::string& server_type, in_port_t try_port, const char *argv[])
-{
-  return construct.start_server(server_type, try_port, argv);
-}
-
-libtest::Server* server_startup_st::create(const std::string& server_type, in_port_t try_port, const bool is_socket)
-{
-  libtest::Server *server= NULL;
-
-  if (is_socket == false)
-  {
-    if (try_port <= 0)
-    {
-      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "was passed the invalid port number %d", int(try_port));
-    }
-  }
-
-  if (is_socket)
-  { 
-    if (server_type.compare("memcached") == 0)
-    {
-      server= build_memcached_socket("localhost", try_port);
-    }
-    else
-    {
-      Error << "Socket is not support for server: " << server_type;
-      return NULL;
-    }
-  }
-  else if (server_type.compare("gearmand") == 0)
-  {
-    server= build_gearmand("localhost", try_port);
-  }
-  else if (server_type.compare("hostile-gearmand") == 0)
-  {
-    server= build_gearmand("localhost", try_port, "gearmand/hostile_gearmand");
-  }
-  else if (server_type.compare("drizzled") == 0)
-  {
-    if (has_drizzled())
-    {
-      if (has_libdrizzle())
-      {
-        server= build_drizzled("localhost", try_port);
-      }
-    }
-  }
-  else if (server_type.compare("blobslap_worker") == 0)
-  {
-    if (has_gearmand())
-    {
-#ifdef GEARMAND_BLOBSLAP_WORKER
-      if (GEARMAND_BLOBSLAP_WORKER)
-      {
-        if (HAVE_LIBGEARMAN)
-        {
-          server= build_blobslap_worker(try_port);
-        }
-      }
-#endif // GEARMAND_BLOBSLAP_WORKER
-    }
-  }
-  else if (server_type.compare("memcached") == 0)
-  {
-    if (has_memcached())
-    {
-      server= build_memcached("localhost", try_port);
-    }
-  }
-  else if (server_type == "memcached-sasl")
-  {
-    server = build_memcached_sasl("localhost", try_port, _username, _password);
-  }
-
-  return server;
-}
-
-class ServerPtr {
-public:
-  ServerPtr(libtest::Server* server_):
-    _server(server_)
-  { }
-
-  ~ServerPtr()
-  {
-    delete _server;
-  }
-
-  void reset()
-  {
-    delete _server;
-    _server= NULL;
-  }
-
-  libtest::Server* release(libtest::Server* server_= NULL)
-  {
-    libtest::Server* tmp= _server;
-    _server= server_;
-    return tmp;
-  }
-
-  libtest::Server* operator->() const
-  {
-    return _server;
-  }
-
-  libtest::Server* operator&() const
-  { 
-    return _server;
-  }
-
-private:
-  libtest::Server* _server;
-};
-
-bool server_startup_st::_start_server(const bool is_socket,
-                                      const std::string& server_type,
-                                      in_port_t try_port,
-                                      const char *argv[])
-{
-  try {
-    ServerPtr server(create(server_type, try_port, is_socket));
-
-    if (&server == NULL)
-    {
-      Error << "Could not allocate server: " << server_type;
-      return false;
-    }
-
-    /*
-      We will now cycle the server we have created.
-    */
-    if (server->cycle() == false)
-    {
-      Error << "Could not start up server " << &server;
-      return false;
-    }
-
-    server->init(argv);
-
-#if 0
-    if (false)
-    {
-      Out << "Pausing for startup, hit return when ready.";
-      std::string gdb_command= server->base_command();
-      getchar();
-    }
-    else
-#endif
-
-      if (server->start() == false)
-      {
-        return false;
-      }
-      else
-      {
-        {
-#ifdef DEBUG
-          if (DEBUG)
-          {
-            Outn();
-            Out << "STARTING SERVER(pid:" << server->pid() << "): " << server->running();
-          }
-#endif
-        }
-      }
-
-    push_server(server.release());
-
-    if (is_socket and &server)
-    {
-      set_default_socket(server->socket().c_str());
-    }
-  }
-  catch (const libtest::disconnected& err)
-  {
-    if (fatal::is_disabled() == false and try_port != LIBTEST_FAIL_PORT)
-    {
-      stream::cerr(err.file(), err.line(), err.func()) << err.what();
-      return false;
-    }
-  }
-  catch (const libtest::__test_result& err)
-  {
-    stream::cerr(err.file(), err.line(), err.func()) << err.what();
-    return false;
-  }
-  catch (const std::exception& err)
-  {
-    Error << err.what();
-    return false;
-  }
-  catch (...)
-  {
-    Error << "error occured while creating server: " << server_type;
-    return false;
-  }
-
-  return true;
-}
-
-bool server_startup_st::start_server(const std::string& server_type, in_port_t try_port, const char *argv[])
-{
-  return _start_server(false, server_type, try_port, argv);
-}
-
-bool server_startup_st::start_socket_server(const std::string& server_type, const in_port_t try_port, const char *argv[])
-{
-  return _start_server(true, server_type, try_port, argv);
-}
-
-std::string server_startup_st::option_string() const
-{
-  std::string temp= server_list;
-  rtrim(temp);
-  return temp;
-}
-
-
-} // namespace libtest
diff --git a/libtest/server_container.h b/libtest/server_container.h
deleted file mode 100644 (file)
index 88e4763..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <cassert>
-#include <cstdio>
-#include <cstring>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <string>
-#include <unistd.h>
-#include <vector>
-
-namespace libtest {
-
-class server_startup_st
-{
-private:
-  uint64_t _magic;
-  std::string server_list;
-  bool _socket;
-  bool _sasl;
-  std::string _username;
-  std::string _password;
-
-public:
-
-  uint8_t udp;
-  std::vector<Server *> servers;
-
-  server_startup_st();
-  ~server_startup_st();
-
-  bool validate();
-
-  bool start_socket_server(const std::string& server_type, const in_port_t try_port, const char *argv[]);
-  bool start_server(const std::string& server_type, const in_port_t try_port, const char *argv[]);
-
-  uint32_t count() const
-  {
-    return uint32_t(servers.size());
-  }
-
-  void restart();
-
-  std::string option_string() const;
-
-  const std::string& password() const
-  {
-    return _password;
-  }
-
-  const std::string& username() const
-  {
-    return _username;
-  }
-
-  bool socket()
-  {
-    return _socket;
-  }
-
-  bool sasl()
-  {
-    return _sasl;
-  }
-
-  void set_socket()
-  {
-    _socket= true;
-  }
-
-  void set_sasl(const std::string& username_arg, const std::string& password_arg)
-  {
-    _sasl= true;
-    _username= username_arg;
-    _password= password_arg;
-  }
-
-
-  // Just remove everything after shutdown
-  void clear();
-
-  bool shutdown();
-  bool shutdown(uint32_t number_of_host);
-
-  bool check() const;
-
-  void push_server(Server *);
-  Server* last();
-  Server *pop_server();
-
-  Server* create(const std::string& server_type, in_port_t try_port, const bool is_socket);
-
-  unsigned long int servers_to_run() const
-  {
-    return _servers_to_run;
-  }
-
-  void set_servers_to_run(unsigned long int arg)
-  {
-    _servers_to_run= arg;
-  }
-
-private:
-  bool _start_server(const bool is_socket,
-                     const std::string& server_type,
-                     const in_port_t try_port,
-                     const char *argv[]);
-
-private:
-  unsigned long int _servers_to_run;
-};
-
-bool server_startup(server_startup_st&, const std::string&, in_port_t try_port, const char *argv[]);
-
-} // namespace libtest
diff --git a/libtest/signal.cc b/libtest/signal.cc
deleted file mode 100644 (file)
index 70012f1..0000000
+++ /dev/null
@@ -1,259 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-#include <csignal>
-
-#include <libtest/signal.h>
-
-using namespace libtest;
-
-#define MAGIC_MEMORY 123569
-
-bool SignalThread::is_shutdown()
-{
-  bool ret;
-  pthread_mutex_lock(&shutdown_mutex);
-  ret= bool(__shutdown != SHUTDOWN_RUNNING);
-  pthread_mutex_unlock(&shutdown_mutex);
-
-  return ret;
-}
-
-void SignalThread::set_shutdown(shutdown_t arg)
-{
-  pthread_mutex_lock(&shutdown_mutex);
-  __shutdown= arg;
-  pthread_mutex_unlock(&shutdown_mutex);
-
-  if (arg == SHUTDOWN_GRACEFUL)
-  {
-    if (pthread_kill(thread, SIGUSR2) == 0)
-    {
-      void *retval;
-      pthread_join(thread, &retval);
-    }
-  }
-}
-
-shutdown_t SignalThread::get_shutdown()
-{
-  shutdown_t local;
-  pthread_mutex_lock(&shutdown_mutex);
-  local= __shutdown;
-  pthread_mutex_unlock(&shutdown_mutex);
-
-  return local;
-}
-
-void SignalThread::post()
-{
-  sem_post(&lock);
-}
-
-void SignalThread::test()
-{
-  assert(magic_memory == MAGIC_MEMORY);
-  if (bool(getenv("LIBTEST_IN_GDB")) == false)
-  {
-    assert(sigismember(&set, SIGALRM));
-    assert(sigismember(&set, SIGABRT));
-    assert(sigismember(&set, SIGQUIT));
-    assert(sigismember(&set, SIGINT));
-    assert(sigismember(&set, SIGVTALRM));
-  }
-  assert(sigismember(&set, SIGUSR2));
-}
-
-bool SignalThread::unblock()
-{
-  int error;
-  if ((error= pthread_sigmask(SIG_UNBLOCK, &set, NULL)) != 0)
-  {
-    Error << "While trying to reset signal mask to original set, pthread_sigmask() died during pthread_sigmask(" << strerror(error) << ")";
-    return false;
-  }
-
-  return true;
-}
-
-SignalThread::~SignalThread()
-{
-  if (is_shutdown() == false)
-  {
-    set_shutdown(SHUTDOWN_GRACEFUL);
-  }
-
-#if 0
-  if (pthread_equal(thread, pthread_self()) != 0 and (pthread_kill(thread, 0) == ESRCH) == true)
-  {
-    void *retval;
-    pthread_join(thread, &retval);
-  }
-#endif
-  sem_destroy(&lock);
-
-  unblock();
-}
-
-extern "C" {
-
-static void *sig_thread(void *arg)
-{   
-  SignalThread *context= (SignalThread*)arg;
-
-  context->test();
-  context->post();
-
-  while (context->get_shutdown() == SHUTDOWN_RUNNING)
-  {
-    int sig;
-
-    if (context->wait(sig) == -1)
-    {
-      Error << "sigwait() returned errno:" << strerror(errno);
-      continue;
-    }
-
-    switch (sig)
-    {
-    case SIGALRM:
-    case SIGVTALRM:
-      Error << strsignal(sig);
-      if (gdb_is_caller())
-      {
-        abort();
-      }
-      exit(EXIT_FAILURE);
-
-    case SIGABRT:
-    case SIGUSR2:
-    case SIGINT:
-    case SIGQUIT:
-      if (context->is_shutdown() == false)
-      {
-        context->set_shutdown(SHUTDOWN_FORCED);
-      }
-      break;
-    case SIGPIPE:
-      {
-        Error << "Ignoring SIGPIPE";
-      }
-      break;
-
-    case 0:
-      Error << "Inside of gdb";
-      break;
-
-    default:
-      Error << "Signal handling thread got unexpected signal " <<  strsignal(sig);
-      break;
-    }
-  }
-
-  return NULL;
-}
-
-}
-
-SignalThread::SignalThread() :
-  magic_memory(MAGIC_MEMORY),
-  thread(pthread_self())
-{
-  pthread_mutex_init(&shutdown_mutex, NULL);
-  sigemptyset(&set);
-  if (bool(getenv("LIBTEST_IN_GDB")) == false)
-  {
-    sigaddset(&set, SIGALRM);
-    sigaddset(&set, SIGABRT);
-    sigaddset(&set, SIGQUIT);
-    sigaddset(&set, SIGINT);
-    sigaddset(&set, SIGVTALRM);
-  }
-  sigaddset(&set, SIGPIPE);
-
-  sigaddset(&set, SIGUSR2);
-
-  sem_init(&lock, 0, 0);
-
-  sigemptyset(&original_set);
-  pthread_sigmask(SIG_BLOCK, NULL, &original_set);
-}
-
-
-bool SignalThread::setup()
-{
-  set_shutdown(SHUTDOWN_RUNNING);
-
-  if (sigismember(&original_set, SIGQUIT))
-  {
-    Error << strsignal(SIGQUIT) << " has been previously set.";
-  }
-
-  if (sigismember(&original_set, SIGINT))
-  {
-    Error << strsignal(SIGINT) << " has been previously set.";
-  }
-
-  if (sigismember(&original_set, SIGVTALRM))
-  {
-    Error << strsignal(SIGVTALRM) << " has been previously set.";
-  }
-
-  if (sigismember(&original_set, SIGUSR2))
-  {
-    Error << strsignal(SIGUSR2) << " has been previously set.";
-  }
-
-  int error;
-  if ((error= pthread_sigmask(SIG_BLOCK, &set, NULL)) != 0)
-  {
-    Error << "pthread_sigmask() died during pthread_sigmask(" << strerror(error) << ")";
-    return false;
-  }
-
-  if ((error= pthread_create(&thread, NULL, &sig_thread, this)) != 0)
-  {
-    Error << "pthread_create() died during pthread_create(" << strerror(error) << ")";
-    return false;
-  }
-
-  sem_wait(&lock);
-
-  return true;
-}
diff --git a/libtest/signal.h b/libtest/signal.h
deleted file mode 100644 (file)
index 6e68bb3..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once 
-
-#include <pthread.h>
-#include <semaphore.h>
-#include <signal.h>
-
-enum shutdown_t {
-  SHUTDOWN_RUNNING,
-  SHUTDOWN_GRACEFUL,
-  SHUTDOWN_FORCED
-};
-
-namespace libtest {
-
-class SignalThread {
-  sigset_t set;
-  sem_t lock;
-  uint64_t magic_memory;
-  volatile shutdown_t __shutdown;
-  pthread_mutex_t shutdown_mutex;
-  pthread_t thread;
-  sigset_t original_set;
-
-public:
-
-  SignalThread();
-  ~SignalThread();
-
-  void test();
-  void post();
-  bool setup();
-  bool unblock();
-
-  int wait(int& sig)
-  {
-    return sigwait(&set, &sig);
-  }
-
-  void set_shutdown(shutdown_t arg);
-  bool is_shutdown();
-  shutdown_t get_shutdown();
-};
-
-} // namespace libtest
diff --git a/libtest/skiptest.cc b/libtest/skiptest.cc
deleted file mode 100644 (file)
index 098a575..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include <libtest/test.hpp>
-
-#include <cstdlib>
-#include <unistd.h>
-
-using namespace libtest;
-
-
-static void *world_create(server_startup_st&, test_return_t& rc)
-{
-  rc= TEST_SKIPPED;
-
-  return NULL;
-}
-
-void get_world(libtest::Framework *world)
-{
-  world->create(world_create);
-}
diff --git a/libtest/socket.cc b/libtest/socket.cc
deleted file mode 100644 (file)
index 9e06841..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-static char global_socket[1024]= { 0 };
-
-namespace libtest {
-
-const char *default_socket()
-{
-  if (global_socket[0] == 0)
-  {
-    return NULL;
-  }
-
-  return global_socket;
-}
-
-void set_default_socket(const char *socket)
-{
-  if (socket)
-  {
-    strncpy(global_socket, socket, sizeof(global_socket)-1);
-  }
-}
-
-}
diff --git a/libtest/socket.hpp b/libtest/socket.hpp
deleted file mode 100644 (file)
index 9d13c34..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-namespace libtest {
-
-const char *default_socket();
-
-void set_default_socket(const char *socket);
-
-} // namespace libtest
-
diff --git a/libtest/stream.h b/libtest/stream.h
deleted file mode 100644 (file)
index 0124b9d..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <iostream>
-#include <cassert>
-#include <sstream>
-#include <ctime>
-#include <ostream>
-
-namespace libtest {
-namespace stream {
-
-namespace detail {
-
-template<class Ch, class Tr, class A>
-  class channel {
-  private:
-
-  public:
-    typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
-
-  public:
-    void operator()(const stream_buffer& s, std::ostream& _out,
-                    const char* filename, int line_number, const char* func)
-    {
-      if (filename)
-      {
-        _out
-          << filename 
-          << ":" 
-          << line_number 
-          << ": in " 
-          << func << "() "
-          << s.str()
-          << std::endl;
-      }
-      else
-      {
-        _out
-          << s.str()
-          << std::endl;
-      }
-    }
-  };
-
-template<class Ch, class Tr, class A>
-  class channelln {
-  private:
-
-  public:
-    typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
-
-  public:
-    void operator()(const stream_buffer& s, std::ostream& _out,
-                    const char* filename, int line_number, const char* func)
-    {
-      if (filename)
-      {
-        _out
-          << std::endl
-          << filename 
-          << ":" 
-          << line_number 
-          << ": in " 
-          << func << "() "
-          << s.str()
-          << std::endl;
-      }
-      else
-      {
-        _out
-          << std::endl
-          << s.str()
-          << std::endl;
-      }
-    }
-  };
-
-template<class Ch, class Tr, class A>
-  class channelfl {
-  private:
-
-  public:
-    typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
-
-  public:
-    void operator()(const stream_buffer& s, std::ostream& _out,
-                    const char* filename, int line_number, const char* func)
-    {
-      if (filename)
-      {
-        _out
-          << filename
-          << ":"
-          << line_number
-          << ": in "
-          << func << "() "
-          << s.str()
-          << std::flush;
-      }
-      else
-      {
-        _out
-          << s.str()
-          << std::flush;
-      }
-    }
-  };
-
-template<template <class Ch, class Tr, class A> class OutputPolicy, class Ch = char, class Tr = std::char_traits<Ch>, class A = std::allocator<Ch> >
-  class log {
-  private:
-    typedef OutputPolicy<Ch, Tr, A> output_policy;
-
-  private:
-    std::ostream& _out;
-    const char *_filename;
-    int _line_number;
-    const char *_func;
-
-  public:
-    log(std::ostream& out_arg, const char* filename, int line_number, const char* func) :
-      _out(out_arg),
-      _filename(filename),
-      _line_number(line_number),
-      _func(func)
-    { }
-
-    virtual ~log()
-    {
-      output_policy()(arg, _out, _filename, _line_number, _func);
-    }
-
-  public:
-    template<class T>
-      log &operator<<(const T &x)
-      {
-        arg << x;
-        return *this;
-      }
-
-  private:
-    typename output_policy::stream_buffer arg;
-
-  private:
-    log( const log& );
-    const log& operator=( const log& );
-  };
-} // namespace detail
-
-class make_cerr : public detail::log<detail::channelln> {
-public:
-  make_cerr(const char* filename, int line_number, const char* func) :
-    detail::log<detail::channelln>(std::cerr, filename, line_number, func)
-  { }
-
-private:
-  make_cerr( const make_cerr& );
-  const make_cerr& operator=( const make_cerr& );
-};
-
-class cerr : public detail::log<detail::channel> {
-public:
-  cerr(const char* filename, int line_number, const char* func) :
-    detail::log<detail::channel>(std::cout, filename, line_number, func)
-  { }
-
-private:
-  cerr( const cerr& );
-  const cerr& operator=( const cerr& );
-};
-
-class clog : public detail::log<detail::channel> {
-public:
-  clog(const char* filename, int line_number, const char* func) :
-    detail::log<detail::channel>(std::clog, filename, line_number, func)
-  { }
-
-private:
-  clog( const clog& );
-  const clog& operator=( const clog& );
-};
-
-class make_cout : public detail::log<detail::channelln> {
-public:
-  make_cout(const char* filename, int line_number, const char* func) :
-    detail::log<detail::channelln>(std::cout, filename, line_number, func)
-  { }
-
-private:
-  make_cout( const make_cout& );
-  const make_cout& operator=( const make_cout& );
-};
-
-class cout : public detail::log<detail::channel> {
-public:
-  cout(const char* filename, int line_number, const char* func) :
-    detail::log<detail::channel>(std::cout, filename, line_number, func)
-  { }
-
-private:
-  cout( const cout& );
-  const cout& operator=( const cout& );
-};
-
-class cecho : public detail::log<detail::channelfl> {
-public:
-  cecho(const char* filename, int line_number, const char* func) :
-    detail::log<detail::channelfl>(std::cout, filename, line_number, func)
-  { }
-
-private:
-  cecho( const cecho& );
-  const cecho& operator=( const cecho& );
-};
-
-} // namespace stream
-
-#define Error stream::cerr(__FILE__, __LINE__, __func__)
-
-#define Echo stream::cecho(NULL, __LINE__, __func__)
-
-#define Out stream::cout(NULL, __LINE__, __func__)
-
-#define Outn() stream::cout(NULL, __LINE__, __func__) << " "
-
-#define Log stream::clog(NULL, __LINE__, __func__)
-
-#define Logn() stream::clog(NULL, __LINE__, __func__) << " "
-
-} // namespace libtest
diff --git a/libtest/strerror.cc b/libtest/strerror.cc
deleted file mode 100644 (file)
index ebbc1e4..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-namespace libtest { 
-
-const char *test_strerror(test_return_t code)
-{
-  switch (code) {
-  case TEST_SUCCESS:
-    return "ok";
-
-  case TEST_FAILURE:
-    return "failed";
-
-  case TEST_SKIPPED:
-    return "skipped";
-  }
-
-  FATAL("No port could be found");
-}
-
-} // namespace libtest
-
-
-std::ostream& operator<<(std::ostream& output, const enum test_return_t &arg)
-{
-  output << libtest::test_strerror(arg);
-  return output;
-}
-
-std::ostream& operator<<(std::ostream& output, const std::vector<char> &arg)
-{
-  output << "std::vector<char>:" << arg.size(); 
-  return output;
-}
diff --git a/libtest/strerror.h b/libtest/strerror.h
deleted file mode 100644 (file)
index 4c2e2d2..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <vector>
-#include <iostream>
-
-namespace libtest {
-
-/**
-  @note Friendly print function for errors.
-*/
-LIBTEST_API
-const char *test_strerror(test_return_t code);
-
-} // namespace libtest
-
-std::ostream& operator<<(std::ostream& output, const enum test_return_t &arg);
-std::ostream& operator<<(std::ostream& output, const std::vector<char> &arg);
-
diff --git a/libtest/string.hpp b/libtest/string.hpp
deleted file mode 100644 (file)
index c32c819..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include "util/string.hpp"
-
-#define test_literal_param util_literal_param
-#define test_literal_compare_param util_literal_compare_param
-#define test_literal_param_size util_literal_param_size
-#define test_string_make_from_cstr util_string_make_from_cstr
-#define test_string_make_from_array util_string_make_from_array
-#define test_array_length util_array_length
diff --git a/libtest/test.h b/libtest/test.h
deleted file mode 100644 (file)
index 3c3c37d..0000000
+++ /dev/null
@@ -1,210 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
-
-#include <libtest/lite.h>
-
-/**
-  A structure describing the test case.
-*/
-struct test_st {
-  const char *name;
-  bool requires_flush;
-  test_callback_fn *test_fn;
-};
-
-#define test_assert_errno(A) \
-do \
-{ \
-  if ((A)) { \
-    fprintf(stderr, "\n%s:%d: Assertion failed for %s: ", __FILE__, __LINE__, __func__);\
-    perror(#A); \
-    fprintf(stderr, "\n"); \
-    libtest::create_core(); \
-    assert((A)); \
-  } \
-} while (0)
-
-#define test_truth(A) \
-do \
-{ \
-  if (! (A)) { \
-    fprintf(stderr, "\n%s:%d: Assertion \"%s\" failed, in %s\n", __FILE__, __LINE__, #A, __func__);\
-    libtest::create_core(); \
-    return TEST_FAILURE; \
-  } \
-} while (0)
-
-#define test_true(A) \
-do \
-{ \
-  if (! (A)) { \
-    fprintf(stderr, "\n%s:%d: Assertion \"%s\" failed, in %s\n", __FILE__, __LINE__, #A, __func__);\
-    libtest::create_core(); \
-    return TEST_FAILURE; \
-  } \
-} while (0)
-
-#define test_true_got(A, B) test_true(A);
-#define test_true_hint(A, B) test_true(A);
-
-#define test_compare_hint(A, B, C) test_compare(A, B);
-#define test_compare_got(A, B, C) test_compare(A, B);
-
-#define test_skip(__expected, __actual) \
-do \
-{ \
-  if (libtest::_compare(__FILE__, __LINE__, __func__, ((__expected)), ((__actual)), false) == false) \
-  { \
-    return TEST_SKIPPED; \
-  } \
-} while (0)
-
-#define test_skip_valgrind() \
-do \
-{ \
-  if (libtest::_in_valgrind(__FILE__, __LINE__, __func__)) \
-  { \
-    return TEST_SKIPPED; \
-  } \
-} while (0)
-
-#define test_fail(A) \
-do \
-{ \
-  if (1) { \
-    fprintf(stderr, "\n%s:%d: Failed with %s, in %s\n", __FILE__, __LINE__, #A, __func__);\
-    libtest::create_core(); \
-    return TEST_FAILURE; \
-  } \
-} while (0)
-
-
-#define test_false(A) \
-do \
-{ \
-  if ((A)) { \
-    fprintf(stderr, "\n%s:%d: Assertion failed %s, in %s\n", __FILE__, __LINE__, #A, __func__);\
-    libtest::create_core(); \
-    return TEST_FAILURE; \
-  } \
-} while (0)
-
-#define test_false_with(A,B) \
-do \
-{ \
-  if ((A)) { \
-    fprintf(stderr, "\n%s:%d: Assertion failed %s with %s\n", __FILE__, __LINE__, #A, (B));\
-    libtest::create_core(); \
-    return TEST_FAILURE; \
-  } \
-} while (0)
-
-#define test_ne_compare(__expected, __actual) \
-do \
-{ \
-  if (libtest::_ne_compare(__FILE__, __LINE__, __func__, ((__expected)), ((__actual)), true) == false) \
-  { \
-    libtest::create_core(); \
-    return TEST_FAILURE; \
-  } \
-} while (0)
-
-#define test_compare(__expected, __actual) \
-do \
-{ \
-  if (libtest::_compare(__FILE__, __LINE__, __func__, ((__expected)), ((__actual)), true) == false) \
-  { \
-    libtest::create_core(); \
-    return TEST_FAILURE; \
-  } \
-} while (0)
-
-#define test_zero(__actual) \
-do \
-{ \
-  if (libtest::_compare_zero(__FILE__, __LINE__, __func__, ((__actual))) == false) \
-  { \
-    libtest::create_core(); \
-    return TEST_FAILURE; \
-  } \
-} while (0)
-
-#define test_null test_zero
-
-#define test_compare_warn(__expected, __actual) \
-do \
-{ \
-  void(libtest::_compare(__FILE__, __LINE__, __func__, (__expected), (__actual)), true); \
-} while (0)
-
-#define test_warn(__truth, __explain) \
-do \
-{ \
-  void(libtest::_assert_truth(__FILE__, __LINE__, __func__, bool((__truth)), #__truth, __explain)); \
-} while (0)
-
-#define test_strcmp(__expected, __actual) \
-do \
-{ \
-  void(libtest::_compare_strcmp(__FILE__, __LINE__, __func__, (__expected), (__actual))); \
-} while (0)
-
-#define test_memcmp(A,B,C) \
-do \
-{ \
-  if ((A) == NULL or (B) == NULL or memcmp((A), (B), (C))) \
-  { \
-    fprintf(stderr, "\n%s:%d: %.*s -> %.*s\n", __FILE__, __LINE__, (int)(C), (char *)(A), (int)(C), (char *)(B)); \
-    libtest::create_core(); \
-    return TEST_FAILURE; \
-  } \
-} while (0)
-
-#define test_return_if(__test_return_t) \
-do \
-{ \
-  if ((__test_return_t) != TEST_SUCCESS) \
-  { \
-    return __test_return_t; \
-  } \
-} while (0)
-
diff --git a/libtest/test.hpp b/libtest/test.hpp
deleted file mode 100644 (file)
index d904070..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/*
-  Structures for generic tests.
-*/
-
-#pragma once
-
-#ifndef YATL_FULL
-# define YATL_FULL 1
-#endif
-
-#ifndef __PRETTY_FUNCTION__
-# define __PRETTY_FUNCTION__ __func__
-#endif
-
-#define YATL_STRINGIFY(x) #x
-#define YATL_TOSTRING(x) YATL_STRINGIFY(x)
-#define YATL_AT __FILE__ ":" YATL_TOSTRING(__LINE__)
-#define YATL_AT_PARAM __func__, AT
-#define YATL_UNIQUE __FILE__ ":" YATL_TOSTRING(__LINE__) "_unique"
-#define YATL_UNIQUE_FUNC_NAME __FILE__ ":" YATL_TOSTRING(__LINE__) "_unique_func"
-
-#define LIBYATL_DEFAULT_PARAM __FILE__, __LINE__, __PRETTY_FUNCTION__
-
-#include <cstdio>
-#include <cstdlib>
-#include <arpa/inet.h>
-
-#include <libtest/visibility.h>
-#include <libtest/version.h>
-
-#include <libtest/vchar.hpp>
-#include <libtest/error.h>
-#include <libtest/exception.hpp>
-#include <libtest/exception/disconnected.hpp>
-#include <libtest/exception/fatal.hpp>
-#include <libtest/result.hpp>
-
-#include <libtest/has.hpp>
-#include <libtest/error.h>
-#include <libtest/strerror.h>
-#include <libtest/timer.hpp>
-#include <libtest/alarm.h>
-#include <libtest/stream.h>
-#include <libtest/comparison.hpp>
-#include <libtest/server.h>
-#include <libtest/server_container.h>
-#include <libtest/wait.h>
-#include <libtest/callbacks.h>
-#include <libtest/test.h>
-#include <libtest/dream.h>
-#include <libtest/core.h>
-#include <libtest/runner.h>
-#include <libtest/port.h>
-#include <libtest/is_local.hpp>
-#include <libtest/socket.hpp>
-#include <libtest/collection.h>
-#include <libtest/framework.h>
-#include <libtest/get.h>
-#include <libtest/cmdline.h>
-#include <libtest/string.hpp>
-#include <libtest/binaries.h>
-#include <libtest/http.hpp>
-#include <libtest/cpu.hpp>
-#include <libtest/tmpfile.hpp>
-#include <libtest/client.hpp>
-#include <libtest/thread.hpp>
diff --git a/libtest/thread.hpp b/libtest/thread.hpp
deleted file mode 100644 (file)
index 640cb66..0000000
+++ /dev/null
@@ -1,329 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <pthread.h>
-
-#if __cplusplus < 201103L
-# define noexcept(a)
-#endif
-
-namespace libtest
-{
-namespace thread
-{
-
-class Mutex
-{
-public:
-  Mutex() :
-    _err(0)
-  {
-    _err= pthread_mutex_init(&_mutex, NULL);
-  }
-
-  ~Mutex() noexcept(false)
-  {
-    if ((_err= pthread_mutex_destroy(&_mutex)))
-    {
-      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_cond_destroy: %s", strerror(_err));
-    }
-  }
-
-  pthread_mutex_t* handle()
-  {
-    if (_err != 0)
-    {
-      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_mutex_init: %s", strerror(_err));
-    }
-
-    return &_mutex;
-  }
-
-private:
-  int _err;
-  pthread_mutex_t _mutex;
-};
-
-class ScopedLock
-{
-public:
-  ScopedLock(Mutex& mutex_) :
-    _mutex(mutex_)
-  {
-    init();
-  }
-
-  ~ScopedLock() noexcept(false)
-  {
-    int err;
-    if ((err= pthread_mutex_unlock(_mutex.handle())))
-    {
-      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_mutex_unlock: %s", strerror(err));
-    }
-  }
-
-  Mutex* handle()
-  {
-    return &_mutex;
-  }
-
-private:
-  void init()
-  {
-    int err;
-    if ((err= pthread_mutex_lock(_mutex.handle())))
-    {
-      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_mutex_lock: %s", strerror(err));
-    }
-  }
-
-private:
-  Mutex& _mutex;
-};
-
-class Condition
-{
-public:
-  Condition()
-  {
-    int err;
-    if ((err= pthread_cond_init(&_cond, NULL)))
-    {
-      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_mutex_init: %s", strerror(err));
-    }
-  }
-
-  ~Condition() noexcept(false)
-  {
-    int err;
-    if ((err= pthread_cond_destroy(&_cond)))
-    {
-      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_cond_destroy: %s", strerror(err));
-    }
-  }
-
-  void broadcast()
-  {
-    int err;
-    if ((err= pthread_cond_broadcast(&_cond)))
-    {
-      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_cond_broadcast: %s", strerror(err));
-    }
-  }
-
-  void signal()
-  {
-    int err;
-    if ((err= pthread_cond_signal(&_cond)))
-    {
-      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_cond_broadcast: %s", strerror(err));
-    }
-  }
-
-  void wait(ScopedLock& lock_)
-  {
-    int err;
-    if ((err= pthread_cond_wait(&_cond, lock_.handle()->handle())))
-    {
-      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_cond_wait: %s", strerror(err));
-    }
-  }
-
-private:
-  pthread_cond_t _cond;
-};
-
-class Barrier
-{
-public:
-  explicit Barrier(uint32_t count): 
-    _threshold(count),
-    _count(count),
-    _generation(0)
-  {   
-    if (_count == 0)
-    {
-      fatal_assert("Zero is an invalid value");
-    }
-  }
-
-  ~Barrier()
-  {
-  }
-
-  bool wait()
-  {   
-    ScopedLock l(_mutex);
-    uint32_t gen = _generation;
-
-    if (--_count == 0)
-    {   
-      _generation++;
-      _count = _threshold;
-      _cond.broadcast();
-
-      return true;
-    }
-
-    while (gen == _generation)
-    {
-      _cond.wait(l);
-    }
-
-    return false;
-  }
-
-private:
-  Mutex _mutex;
-  Condition _cond;
-  uint32_t _threshold;
-  uint32_t _count;
-  uint32_t _generation;
-};
-
-class Thread 
-{
-private:
-  typedef void *(*start_routine_fn) (void *);
-
-public:
-  template <class Function,class Arg1>
-    Thread(Function func, Arg1 arg):
-      _joined(false),
-      _func((start_routine_fn)func),
-      _context(arg)
-    {
-      int err;
-      if ((err= pthread_create(&_thread, NULL, entry_func, (void*)this)))
-      {
-        throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_create: %s", strerror(err));
-      }
-      _owner= pthread_self();
-    }
-
-  bool running() const
-  {
-    return (pthread_kill(_thread, 0) == 0);
-  }
-
-  bool detached()
-  {
-    if (EDEADLK == pthread_join(_thread, NULL))
-    {
-      return true;
-    }
-
-    /* Result of pthread_join was EINVAL == detached thread */
-    return false;
-  } 
-
-  bool join()
-  {
-    if (_thread == pthread_self())
-    {
-      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "Thread cannot join on itself");
-    }
-
-    if (_owner != pthread_self())
-    {
-      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "Attempt made by a non-owner thead to join on thread");
-    }
-
-    bool ret= false;
-    {
-      ScopedLock l(_join_mutex);
-      if (_joined == false)
-      {
-        int err;
-        if ((err= pthread_join(_thread, NULL)))
-        {
-          switch(err)
-          {
-          case EINVAL:
-            break;
-
-          case ESRCH:
-            ret= true;
-            break;
-
-          case EDEADLK:
-          default:
-            throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_join: %s", strerror(err));
-          }
-        }
-        else
-        {
-          ret= true;
-        }
-
-        _joined= true;
-      }
-    }
-
-    return ret;
-  }
-
-  ~Thread()
-  {
-    join();
-  }
-
-protected:
-  void run()
-  {
-    _func(_context);
-  }
-
-private:
-  static void * entry_func(void* This)
-  {
-    ((Thread *)This)->run();
-    return NULL;
-  }
-
-private:
-  bool _joined;
-  pthread_t _thread;
-  pthread_t _owner;
-  start_routine_fn _func;
-  void* _context;
-  Mutex _join_mutex;
-};
-
-} // namespace thread
-} // namespace libtest
diff --git a/libtest/timer.cc b/libtest/timer.cc
deleted file mode 100644 (file)
index fae814c..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include <libtest/timer.hpp>
-
-#include <ctime>
-#include <iomanip>
-
-#ifdef __MACH__
-# include <mach/clock.h>
-# include <mach/mach.h>
-#else
-# include <sys/time.h>
-#endif
-
-namespace libtest {
-
-Timer::Timer()
-{
-  _begin.tv_sec= 0;
-  _begin.tv_nsec= 0;
-  _end.tv_sec= 0;
-  _end.tv_nsec= 0;
-}
-
-void Timer::reset()
-{
-  _end.tv_sec= 0;
-  _end.tv_nsec= 0;
-  _time(_begin);
-}
-
-void Timer::sample()
-{
-  _time(_end);
-}
-
-void Timer::offset(int64_t minutes_arg, int64_t seconds_arg, int64_t nanoseconds)
-{
-  reset();
-  _end= _begin;
-  _end.tv_sec+= (minutes_arg * 60) +seconds_arg;
-  _end.tv_nsec+= nanoseconds;
-}
-
-int64_t Timer::minutes()
-{
-  struct timespec result;
-  difference(result);
-  return int64_t(result.tv_sec / 60);
-}
-
-uint64_t Timer::elapsed_milliseconds() const
-{
-  struct timespec temp;
-  difference(temp);
-
-  return temp.tv_sec*1000 +temp.tv_nsec/1000000;
-}
-
-void Timer::difference(struct timespec& arg) const
-{
-  if ((_end.tv_nsec -_begin.tv_nsec) < 0)
-  {
-    arg.tv_sec= _end.tv_sec -_begin.tv_sec -1;
-    arg.tv_nsec= 1000000000 +_end.tv_nsec -_begin.tv_nsec;
-
-  }
-  else
-  {
-    arg.tv_sec= _end.tv_sec -_begin.tv_sec;
-    arg.tv_nsec= _end.tv_nsec -_begin.tv_nsec;
-  }
-}
-
-void Timer::_time(struct timespec& ts)
-{
-#ifdef __MACH__ // OSX lacks clock_gettime()
-  clock_serv_t _clock_serv;
-  mach_timespec_t _mach_timespec;
-  host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &_clock_serv);
-  clock_get_time(_clock_serv, &_mach_timespec);
-  mach_port_deallocate(mach_task_self(), _clock_serv);
-  ts.tv_sec= _mach_timespec.tv_sec;
-  ts.tv_nsec= _mach_timespec.tv_nsec;
-#elif defined(_WIN32)
-  ts.tv_sec= time(NULL);
-  ts.tv_nsec= 0;
-#else
-  clock_gettime(CLOCK_REALTIME, &ts);
-#endif
-}
-
-std::ostream& operator<<(std::ostream& output, const libtest::Timer& arg)
-{
-  struct timespec temp;
-  arg.difference(temp);
-
-  if (temp.tv_sec > 60)
-  {
-    output << temp.tv_sec / 60;
-    output << "." << temp.tv_sec % 60;
-  }
-  else
-  {
-    output << temp.tv_sec;
-  }
-
-  output << ":";
-  output << std::setfill('0') << std::setw(9) << temp.tv_nsec;
-
-  return output;
-}
-
-} // namespace libtest
diff --git a/libtest/timer.hpp b/libtest/timer.hpp
deleted file mode 100644 (file)
index 18ed3e8..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <cstdlib>
-#include <ctime>
-#include <iostream>
-
-
-namespace libtest {
-
-class Timer {
-public:
-
-  Timer();
-
-  void reset();
-
-  void sample();
-
-  void offset(int64_t minutes_arg, int64_t seconds_arg, int64_t nanoseconds);
-
-  int64_t minutes();
-
-  uint64_t elapsed_milliseconds() const;
-
-  void difference(struct timespec& arg) const;
-
-private:
-  void _time(struct timespec& ts);
-
-private:
-  struct timespec _begin;
-  struct timespec _end;
-};
-
-std::ostream& operator<<(std::ostream& output, const libtest::Timer& arg);
-
-} // namespace libtest
diff --git a/libtest/tmpfile.cc b/libtest/tmpfile.cc
deleted file mode 100644 (file)
index 425a21e..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include <libtest/common.h>
-
-namespace libtest {
-
-std::string create_tmpfile(const std::string& name, int& fd)
-{
-  libtest::vchar_t file_buffer;
-  file_buffer.resize(FILENAME_MAX);
-  file_buffer[0]= 0;
-
-  int length= snprintf(&file_buffer[0], file_buffer.size(), "var/tmp/%s.XXXXXX", name.c_str());
-  fatal_assert(length > 0);
-
-  if ((fd= mkstemp(&file_buffer[0])) == -1)
-  {
-    throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "mkstemp() failed on %s with %s", &file_buffer[0], strerror(errno));
-  }
-
-  return &file_buffer[0];
-}
-
-std::string create_tmpfile(const std::string& name)
-{
-  int fd;
-  std::string ret_file= create_tmpfile(name, fd);
-  close(fd);
-  unlink(ret_file.c_str());
-
-  return ret_file.c_str();
-}
-
-} // namespace libtest
diff --git a/libtest/tmpfile.hpp b/libtest/tmpfile.hpp
deleted file mode 100644 (file)
index 9283b84..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <libtest/common.h>
-
-namespace libtest {
-
-std::string create_tmpfile(const std::string&, int&);
-std::string create_tmpfile(const std::string&);
-
-} // namespace libtest
-
diff --git a/libtest/unittest.cc b/libtest/unittest.cc
deleted file mode 100644 (file)
index fafe032..0000000
+++ /dev/null
@@ -1,1233 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include <libtest/yatl.h>
-
-#if defined(HAVE_LIBMEMCACHED_1_0_TYPES_RETURN_H) && HAVE_LIBMEMCACHED_1_0_TYPES_RETURN_H
-# include <libmemcached-1.0/types/return.h>
-#endif
-
-#if defined(HAVE_LIBGEARMAN_1_0_RETURN_H) && HAVE_LIBGEARMAN_1_0_RETURN_H
-# include <libgearman-1.0/return.h>
-#endif
-
-#include <cstdlib>
-#include <unistd.h>
-
-using namespace libtest;
-
-static std::string testing_service;
-
-// Used to track setups where we see if failure is happening
-static uint32_t fatal_calls= 0;
-
-static test_return_t getenv_TEST(void *)
-{
-#if 0
-  for (char **ptr= environ; *ptr; ptr++)
-  {
-    Error << *ptr;
-  }
-#endif
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t LIBTOOL_COMMAND_test(void *)
-{
-  test_true(getenv("LIBTOOL_COMMAND"));
-  return TEST_SUCCESS;
-}
-
-static test_return_t VALGRIND_COMMAND_test(void *)
-{
-  test_true(getenv("VALGRIND_COMMAND"));
-  return TEST_SUCCESS;
-}
-
-static test_return_t HELGRIND_COMMAND_test(void *)
-{
-  test_true(getenv("HELGRIND_COMMAND"));
-  return TEST_SUCCESS;
-}
-
-static test_return_t GDB_COMMAND_test(void *)
-{
-  test_true(getenv("GDB_COMMAND"));
-  return TEST_SUCCESS;
-}
-
-static test_return_t test_success_equals_one_test(void *)
-{
-  test_skip(HAVE_LIBMEMCACHED, 1);
-#if defined(HAVE_LIBMEMCACHED_1_0_TYPES_RETURN_H) && HAVE_LIBMEMCACHED_1_0_TYPES_RETURN_H
-  test_zero(MEMCACHED_SUCCESS);
-#endif
-  return TEST_SUCCESS;
-}
-
-static test_return_t test_success_test(void *)
-{
-  return TEST_SUCCESS;
-}
-
-static test_return_t test_throw_success_TEST(void *)
-{
-  try {
-    _SUCCESS;
-  }
-  catch (const libtest::__success&)
-  {
-    return TEST_SUCCESS;
-  }
-  catch (...)
-  {
-    return TEST_FAILURE;
-  }
-
-  return TEST_FAILURE;
-}
-
-static test_return_t test_throw_skip_macro_TEST(void *)
-{
-  try {
-    SKIP_IF(true);
-  }
-  catch (const libtest::__skipped&)
-  {
-    return TEST_SUCCESS;
-  }
-  catch (...)
-  {
-    FAIL("SLIP_IF() failed to throw libtest::_skipped");
-  }
-
-  FAIL("SLIP_IF() failed to throw");
-
-  return TEST_FAILURE;
-}
-
-static test_return_t test_throw_skip_unless_macro_TEST(void *)
-{
-  try {
-    SKIP_UNLESS(false);
-  }
-  catch (const libtest::__skipped&)
-  {
-    return TEST_SUCCESS;
-  }
-  catch (...)
-  {
-    FAIL("SLIP_UNLESS() failed to throw libtest::_skipped");
-  }
-
-  FAIL("SLIP_UNLESS() failed to throw");
-
-  return TEST_FAILURE;
-}
-
-static test_return_t test_throw_skip_TEST(void *)
-{
-  try {
-    throw libtest::__skipped(LIBYATL_DEFAULT_PARAM, "basic test");
-  }
-  catch (const libtest::__skipped&)
-  {
-    return TEST_SUCCESS;
-  }
-  catch (...)
-  {
-    FAIL("SLIP_IF() failed to throw libtest::_skipped");
-  }
-
-  FAIL("SLIP_IF() failed to throw");
-
-  return TEST_FAILURE;
-}
-
-static test_return_t test_throw_fail_TEST(void *)
-{
-  try {
-    FAIL("test message!");
-  }
-  catch (const libtest::__failure& e)
-  {
-    std::string compare_message("test message!");
-    test_zero(compare_message.compare(e.what()));
-    return TEST_SUCCESS;
-  }
-  catch (...)
-  {
-    return TEST_FAILURE;
-  }
-
-  return TEST_FAILURE;
-}
-#pragma GCC diagnostic ignored "-Wstack-protector"
-
-#ifdef __clang__
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wformat-security"
-#endif
-
-static test_return_t ASSERT_FALSE__TEST(void *)
-{
-  try {
-    ASSERT_FALSE(true);
-  }
-  catch (const libtest::__failure& e)
-  {
-    ASSERT_STREQ(e.what(), "Assertion '!true'");
-    return TEST_SUCCESS;
-  }
-  catch (...)
-  {
-    return TEST_FAILURE;
-  }
-
-  return TEST_FAILURE;
-}
-
-#ifdef __clang__
-# pragma GCC diagnostic pop
-#endif
-
-static test_return_t ASSERT_NEQ_FAIL_TEST(void *)
-{
-  try {
-    ASSERT_NEQ(1,1);
-  }
-  catch (const libtest::__failure& e)
-  {
-    ASSERT_STREQ(e.what(), "Assertion '1' == '1'");
-    return TEST_SUCCESS;
-  }
-  catch (...)
-  {
-    return TEST_FAILURE;
-  }
-
-  return TEST_FAILURE;
-}
-
-static test_return_t ASSERT_NEQ_TEST(void *)
-{
-  ASSERT_NEQ(1,0);
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t ASSERT_FALSE_TEST(void *)
-{
-  try {
-    FAIL(__func__);
-  }
-  catch (const libtest::__failure& e)
-  {
-    ASSERT_STREQ(e.what(), __func__);
-    return TEST_SUCCESS;
-  }
-  catch (...)
-  {
-    return TEST_FAILURE;
-  }
-
-  return TEST_FAILURE;
-}
-
-static test_return_t test_failure_test(void *)
-{
-  return TEST_SKIPPED; // Only run this when debugging
-
-  ASSERT_EQ(1, 2);
-  return TEST_SUCCESS;
-}
-
-static test_return_t local_test(void *)
-{
-  if (getenv("LIBTEST_LOCAL"))
-  {
-    test_true(test_is_local());
-  }
-  else
-  {
-    test_false(test_is_local());
-  }
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t local_not_test(void *)
-{
-  return TEST_SKIPPED;
-
-  std::string temp;
-
-  const char *ptr;
-  if ((ptr= getenv("LIBTEST_LOCAL")) == NULL)
-  {
-    temp.append(ptr);
-  }
-
-  // unsetenv() will cause issues with valgrind
-  _compare(__FILE__, __LINE__, __func__, 0, unsetenv("LIBTEST_LOCAL"), true);
-  ASSERT_EQ(0, unsetenv("LIBTEST_LOCAL"));
-  test_false(test_is_local());
-
-  ASSERT_EQ(0, setenv("LIBTEST_LOCAL", "1", 1));
-  test_true(test_is_local());
-
-  if (temp.empty())
-  {
-    ASSERT_EQ(0, unsetenv("LIBTEST_LOCAL"));
-  }
-  else
-  {
-    char *old_string= strdup(temp.c_str());
-    ASSERT_EQ(0, setenv("LIBTEST_LOCAL", old_string, 1));
-  }
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t var_exists_test(void *)
-{
-  ASSERT_EQ(0, access("var", R_OK | W_OK | X_OK));
-  return TEST_SUCCESS;
-}
-
-static test_return_t var_tmp_exists_test(void *)
-{
-  ASSERT_EQ(0, access("var/tmp", R_OK | W_OK | X_OK));
-  return TEST_SUCCESS;
-}
-
-static test_return_t var_run_exists_test(void *)
-{
-  ASSERT_EQ(0, access("var/run", R_OK | W_OK | X_OK));
-  return TEST_SUCCESS;
-}
-
-static test_return_t var_log_exists_test(void *)
-{
-  ASSERT_EQ(0, access("var/log", R_OK | W_OK | X_OK));
-  return TEST_SUCCESS;
-}
-
-static test_return_t var_drizzle_exists_test(void *)
-{
-  ASSERT_EQ(0, access("var/drizzle", R_OK | W_OK | X_OK));
-  return TEST_SUCCESS;
-}
-
-static test_return_t var_tmp_test(void *)
-{
-  FILE *file= fopen("var/tmp/junk", "w+");
-  test_true(file);
-  fclose(file);
-  return TEST_SUCCESS;
-}
-
-static test_return_t var_run_test(void *)
-{
-  FILE *file= fopen("var/run/junk", "w+");
-  test_true(file);
-  fclose(file);
-  return TEST_SUCCESS;
-}
-
-static test_return_t var_log_test(void *)
-{
-  FILE *file= fopen("var/log/junk", "w+");
-  test_true(file);
-  fclose(file);
-  return TEST_SUCCESS;
-}
-
-static test_return_t var_drizzle_test(void *)
-{
-  FILE *file= fopen("var/drizzle/junk", "w+");
-  test_true(file);
-  fclose(file);
-  return TEST_SUCCESS;
-}
-
-static test_return_t var_tmp_rm_test(void *)
-{
-  test_true(unlink("var/tmp/junk") == 0);
-  return TEST_SUCCESS;
-}
-
-static test_return_t var_run_rm_test(void *)
-{
-  test_true(unlink("var/run/junk") == 0);
-  return TEST_SUCCESS;
-}
-
-static test_return_t var_log_rm_test(void *)
-{
-  test_true(unlink("var/log/junk") == 0);
-  return TEST_SUCCESS;
-}
-
-static test_return_t var_drizzle_rm_test(void *)
-{
-  test_true(unlink("var/drizzle/junk") == 0);
-  return TEST_SUCCESS;
-}
-
-static test_return_t _compare_test_return_t_test(void *)
-{
-  ASSERT_EQ(TEST_SUCCESS, TEST_SUCCESS);
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t _compare_memcached_return_t_test(void *)
-{
-  test_skip(HAVE_LIBMEMCACHED, true);
-#if defined(HAVE_LIBMEMCACHED_1_0_TYPES_RETURN_H) && HAVE_LIBMEMCACHED_1_0_TYPES_RETURN_H
-  ASSERT_EQ(MEMCACHED_SUCCESS, MEMCACHED_SUCCESS);
-#endif
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t _compare_gearman_return_t_test(void *)
-{
-  test_skip(HAVE_LIBGEARMAN, true);
-#if defined(HAVE_LIBGEARMAN_1_0_RETURN_H) && HAVE_LIBGEARMAN_1_0_RETURN_H
-  ASSERT_EQ(GEARMAN_SUCCESS, GEARMAN_SUCCESS);
-#endif
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t drizzled_cycle_test(void *object)
-{
-  server_startup_st *servers= (server_startup_st*)object;
-  test_true(servers and servers->validate());
-
-#if defined(HAVE_GEARMAND_BINARY) && HAVE_GEARMAND_BINARY
-  test_true(has_drizzled());
-#endif
-
-  test_skip(true, has_drizzled());
-
-  test_skip(true, server_startup(*servers, "drizzled", get_free_port(), NULL));
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t gearmand_cycle_test(void *object)
-{
-  server_startup_st *servers= (server_startup_st*)object;
-  test_true(servers and servers->validate());
-
-  test_skip(true, has_gearmand());
-  test_skip(true, server_startup(*servers, "gearmand", get_free_port(), NULL));
-  servers->clear();
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t skip_shim(bool a, bool b)
-{
-  test_skip(a, b);
-  return TEST_SUCCESS;
-}
-
-static test_return_t test_skip_true_TEST(void*)
-{
-  ASSERT_EQ(true, true);
-  ASSERT_EQ(false, false);
-  ASSERT_EQ(TEST_SUCCESS, skip_shim(true, true));
-  ASSERT_EQ(TEST_SUCCESS, skip_shim(false, false));
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t test_skip_false_TEST(void*)
-{
-  ASSERT_EQ(TEST_SKIPPED, skip_shim(true, false));
-  ASSERT_EQ(TEST_SKIPPED, skip_shim(false, true));
-  return TEST_SUCCESS;
-}
-
-static test_return_t server_startup_fail_TEST(void *object)
-{
-  server_startup_st *servers= (server_startup_st*)object;
-  test_true(servers);
-
-  fatal::disable();
-  ASSERT_EQ(servers->start_server(testing_service, LIBTEST_FAIL_PORT, NULL), true);
-  fatal::enable();
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t server_startup_TEST(void *object)
-{
-  server_startup_st *servers= (server_startup_st*)object;
-  test_true(servers);
-
-  ASSERT_EQ(servers->start_server(testing_service, get_free_port(), NULL), true);
-
-  test_true(servers->last());
-  pid_t last_pid= servers->last()->pid();
-
-  ASSERT_EQ(servers->last()->pid(), last_pid);
-  test_true(last_pid > 1);
-  ASSERT_EQ(kill(last_pid, 0), 0);
-
-  test_true(servers->shutdown());
-#if 0
-  ASSERT_EQ(servers->last()->pid(), -1);
-  ASSERT_EQ(kill(last_pid, 0), -1);
-#endif
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t socket_server_startup_TEST(void *object)
-{
-  server_startup_st *servers= (server_startup_st*)object;
-  test_true(servers);
-
-  test_true(servers->start_socket_server(testing_service, get_free_port(), NULL));
-
-  return TEST_SUCCESS;
-}
-
-#if 0
-static test_return_t memcached_sasl_test(void *object)
-{
-  server_startup_st *servers= (server_startup_st*)object;
-  test_true(servers);
-
-  test_skip(false, bool(getenv("LOG_COMPILER")));
-
-  if (MEMCACHED_SASL_BINARY)
-  {
-    if (HAVE_LIBMEMCACHED)
-    {
-      test_true(has_memcached_sasl());
-      test_true(server_startup(*servers, "memcached-sasl", get_free_port(), NULL));
-
-      return TEST_SUCCESS;
-    }
-  }
-
-  return TEST_SKIPPED;
-}
-#endif
-
-static test_return_t application_true_BINARY(void *)
-{
-  test_skip(0, access("/usr/bin/true", X_OK ));
-  Application true_app("/usr/bin/true");
-
-  ASSERT_EQ(Application::SUCCESS, true_app.run());
-  ASSERT_EQ(Application::SUCCESS, true_app.join());
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t application_gdb_true_BINARY2(void *)
-{
-  test_skip(0, access("/usr/bin/gdb", X_OK ));
-  test_skip(0, access("/usr/bin/true", X_OK ));
-
-  Application true_app("/usr/bin/true");
-  true_app.use_gdb(true);
-
-  ASSERT_EQ(Application::SUCCESS, true_app.run());
-  ASSERT_EQ(Application::SUCCESS, true_app.join());
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t application_gdb_true_BINARY(void *)
-{
-  test_skip(0, access("/usr/bin/gdb", X_OK ));
-  test_skip(0, access("/usr/bin/true", X_OK ));
-
-  Application true_app("/usr/bin/true");
-  true_app.use_gdb(true);
-
-  const char *args[]= { "--fubar", 0 };
-  ASSERT_EQ(Application::SUCCESS, true_app.run(args));
-  ASSERT_EQ(Application::SUCCESS, true_app.join());
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t application_true_fubar_BINARY(void *)
-{
-  test_skip(0, access("/usr/bin/true", X_OK ));
-  Application true_app("/usr/bin/true");
-
-  const char *args[]= { "--fubar", 0 };
-  ASSERT_EQ(Application::SUCCESS, true_app.run(args));
-  ASSERT_EQ(Application::SUCCESS, true_app.join());
-  test_zero(true_app.stdout_result().size());
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t application_doesnotexist_BINARY(void *)
-{
-
-  test_skip_valgrind();
-  Application true_app("doesnotexist");
-  true_app.will_fail();
-
-  const char *args[]= { "--fubar", 0 };
-#if defined(__APPLE__) && __APPLE__
-  ASSERT_EQ(Application::INVALID_POSIX_SPAWN, true_app.run(args));
-#elif defined(__FreeBSD__) && __FreeBSD__
-  ASSERT_EQ(Application::INVALID_POSIX_SPAWN, true_app.run(args));
-#else
-  Application::error_t rc = true_app.run(args);
-  if (Application::SUCCESS == rc) {
-    ASSERT_EQ(Application::INVALID_POSIX_SPAWN, true_app.join());
-  } else {
-    ASSERT_EQ(Application::INVALID_POSIX_SPAWN, rc);
-  }
-#endif
-
-  test_zero(true_app.stdout_result().size());
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t GET_TEST(void *)
-{
-  libtest::http::GET get("http://foo.example.com/");
-
-  ASSERT_EQ(false, get.execute());
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t POST_TEST(void *)
-{
-  libtest::vchar_t body;
-  libtest::http::POST post("http://foo.example.com/", body);
-
-  ASSERT_EQ(false, post.execute());
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t TRACE_TEST(void *)
-{
-  libtest::vchar_t body;
-  libtest::http::TRACE trace("http://foo.example.com/", body);
-
-  ASSERT_EQ(false, trace.execute());
-
-  return TEST_SUCCESS;
-}
-
-
-static test_return_t vchar_t_TEST(void *)
-{
-  libtest::vchar_t response;
-  libtest::make_vector(response, test_literal_param("fubar\n"));
-  ASSERT_EQ(response, response);
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t vchar_t_make_append_TEST(void *)
-{
-  libtest::vchar_t hostname;
-  libtest::vchar::make(hostname, 23);
-  libtest::vchar::append(hostname, ".com");
-  ASSERT_EQ(28, hostname.size());
-  ASSERT_EQ(0, hostname[27]);
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t vchar_t_compare_neg_TEST(void *)
-{
-  libtest::vchar_t response;
-  libtest::vchar_t response2;
-  libtest::make_vector(response, test_literal_param("fubar\n"));
-  libtest::make_vector(response2, test_literal_param(__func__));
-  test_true(response != response2);
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t application_echo_fubar_BINARY(void *)
-{
-  if (0)
-  {
-    test_skip(0, access("/bin/echo", X_OK ));
-    Application true_app("/bin/echo");
-
-    const char *args[]= { "fubar", 0 };
-    ASSERT_EQ(Application::SUCCESS, true_app.run(args));
-
-    while (true_app.slurp() == false) {} ;
-
-    libtest::vchar_t response;
-    make_vector(response, test_literal_param("fubar\n"));
-    ASSERT_EQ(response, true_app.stdout_result());
-  }
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t application_echo_fubar_BINARY2(void *)
-{
-  if (0)
-  {
-    test_skip(0, access("/bin/echo", X_OK ));
-    Application true_app("/bin/echo");
-
-    true_app.add_option("fubar");
-
-    ASSERT_EQ(Application::SUCCESS, true_app.run());
-    ASSERT_EQ(Application::SUCCESS, true_app.join());
-
-    libtest::vchar_t response;
-    make_vector(response, test_literal_param("fubar\n"));
-    ASSERT_EQ(response, true_app.stdout_result());
-  }
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t echo_fubar_BINARY(void *)
-{
-  const char *args[]= { "fubar", 0 };
-  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("/bin/echo", args));
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t core_count_BINARY(void *)
-{
-  const char *args[]= { 0 };
-
-  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("libtest/core-count", args, true));
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t wait_BINARY(void *)
-{
-  const char *args[]= { "--quiet", 0 };
-
-  ASSERT_EQ(EXIT_FAILURE, exec_cmdline("libtest/wait", args, true));
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t wait_help_BINARY(void *)
-{
-  const char *args[]= { "--quiet", "--help", 0 };
-
-  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true));
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t wait_version_BINARY(void *)
-{
-  const char *args[]= { "--quiet", "--version", 0 };
-
-  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true));
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t wait_services_BINARY(void *)
-{
-  test_skip(0, access("/etc/services", R_OK ));
-
-  const char *args[]= { "--quiet", "/etc/services", 0 };
-
-  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true));
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t wait_services_BINARY2(void *)
-{
-  test_skip(0, access("/etc/services", R_OK ));
-
-  const char *args[]= { "/etc/services", 0 };
-
-  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true));
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t wait_services_appliction_TEST(void *)
-{
-  test_skip(0, access("/etc/services", R_OK ));
-  test_skip(0, access("/usr/bin/gdb", X_OK ));
-  test_skip(0, access("libtest/wait", X_OK ));
-
-  libtest::Application wait_app("libtest/wait", true);
-  wait_app.use_gdb(true);
-
-  const char *args[]= { "/etc/services", 0 };
-  ASSERT_EQ(Application::SUCCESS, wait_app.run(args));
-  ASSERT_EQ(Application::SUCCESS, wait_app.join());
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t gdb_wait_services_appliction_TEST(void *)
-{
-  test_skip(true, false);
-#if defined(__APPLE__) && __APPLE__
-  test_skip(0, __APPLE__);
-#endif
-
-  test_skip(0, access("/etc/services", R_OK ));
-  test_skip(0, access("/usr/bin/gdb", X_OK ));
-  test_skip(0, access("libtest/wait", X_OK ));
-
-  libtest::Application wait_app("libtest/wait", true);
-  wait_app.use_gdb(true);
-
-  const char *args[]= { "/etc/services", 0 };
-  ASSERT_EQ(Application::SUCCESS, wait_app.run(args));
-  ASSERT_EQ(Application::SUCCESS, wait_app.join());
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t gdb_abort_services_appliction_TEST(void *)
-{
-  test_skip(0, access("/usr/bin/gdb", X_OK ));
-  test_skip(0, access("libtest/abort", X_OK ));
-  test_skip(true, false);
-
-#if defined(__APPLE__) && __APPLE__
-  test_skip(0, __APPLE__);
-#endif
-
-  libtest::Application abort_app("libtest/abort", true);
-  abort_app.use_gdb(true);
-
-  ASSERT_EQ(Application::SUCCESS, abort_app.run());
-  ASSERT_EQ(Application::SUCCESS, abort_app.join());
-
-  std::string gdb_filename= abort_app.gdb_filename();
-  test_skip(0, access(gdb_filename.c_str(), R_OK ));
-  const char *args[]= { "SIGABRT", gdb_filename.c_str(), 0 };
-  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("grep", args));
-
-  // Sanity test
-  args[0]= "THIS_WILL_NOT_BE_FOUND";
-  ASSERT_EQ(EXIT_FAILURE, exec_cmdline("grep", args));
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t get_free_port_TEST(void *)
-{
-  in_port_t ret_port;
-  test_true((ret_port= get_free_port()));
-  test_true(get_free_port() != default_port());
-  test_true(get_free_port() != get_free_port());
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t fatal_TEST(void *)
-{
-  ASSERT_EQ(fatal_calls++, fatal::disabled_counter());
-  throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "Testing va_args based fatal(): %d", 10); 
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t number_of_cpus_TEST(void *)
-{
-  test_true(number_of_cpus() >= 1);
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t check_dns_TEST(void *)
-{
-  test_warn(libtest::check_dns(), "Broken DNS server/no DNS server found");
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t Timer_TEST(void *)
-{
-  int64_t minutes= random() % 50;
-  minutes++;
-
-  Timer check;
-
-  check.reset();
-  check.offset(minutes, 2, 200);
-
-  ASSERT_EQ(check.minutes(), minutes);
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t lookup_true_TEST(void *)
-{
-  test_warn(libtest::lookup("exist.gearman.info"), "dns is not currently working");
-  return TEST_SUCCESS;
-}
-
-static test_return_t lookup_false_TEST(void *)
-{
-  SKIP_IF_(libtest::lookup("does_not_exist.gearman.info"),
-           "Broken DNS server detected");
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t create_tmpfile_TEST(void *)
-{
-  test_skip(0, access("/usr/bin/touch", X_OK ));
-  std::string tmp= create_tmpfile(__func__);
-  ASSERT_EQ(-1, access(tmp.c_str(), R_OK));
-  ASSERT_EQ(-1, access(tmp.c_str(), F_OK));
-
-  Application touch_app("/usr/bin/touch");
-  const char *args[]= { tmp.c_str(), 0 };
-  ASSERT_EQ(Application::SUCCESS, touch_app.run(args));
-  ASSERT_EQ(Application::SUCCESS, touch_app.join());
-
-  ASSERT_EQ(0, access(tmp.c_str(), R_OK));
-  ASSERT_EQ(0, unlink(tmp.c_str()));
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t fatal_message_TEST(void *)
-{
-  ASSERT_EQ(fatal_calls++, fatal::disabled_counter());
-  FATAL("Fatal test");
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t default_port_TEST(void *)
-{
-  in_port_t ret_port= default_port();
-  ASSERT_EQ(ret_port, libtest::default_port());
-  ASSERT_EQ(ret_port, libtest::default_port());
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t check_for_VALGRIND(void *)
-{
-  test_skip_valgrind();
-  return TEST_SUCCESS;
-}
-
-static test_return_t check_for_gearman(void *)
-{
-  test_skip(true, HAVE_LIBGEARMAN);
-  test_skip(true, has_gearmand());
-#if defined(HAVE_GEARMAND_BINARY) && HAVE_GEARMAND_BINARY
-  if (GEARMAND_BINARY)
-  {
-    if (strcmp(GEARMAND_BINARY, "./gearmand/gearmand"))
-    {
-      test_zero(access(GEARMAND_BINARY, X_OK ));
-    }
-  }
-  else
-  {
-    return TEST_SKIPPED;
-  }
-#endif
-
-  testing_service= "gearmand";
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t check_for_drizzle(void *)
-{
-  test_skip(true, has_drizzled());
-
-  testing_service= "drizzled";
-
-  return TEST_SUCCESS;
-}
-
-
-test_st drizzled_tests[] ={
-  {"drizzled startup-shutdown", 0, drizzled_cycle_test },
-  {0, 0, 0}
-};
-
-test_st gearmand_tests[] ={
-#if 0
-  {"pause", 0, pause_test },
-#endif
-  {"gearmand startup-shutdown", 0, gearmand_cycle_test },
-  {"_compare(gearman_return_t)", 0, _compare_gearman_return_t_test },
-  {"server_startup(fail)", 0, server_startup_fail_TEST },
-  {0, 0, 0}
-};
-
-static test_return_t clear_servers(void* object)
-{
-  server_startup_st *servers= (server_startup_st*)object;
-  test_true(servers);
-  servers->clear();
-
-  testing_service.clear();
-
-  return TEST_SUCCESS;
-}
-
-static test_return_t check_for_memcached(void* object)
-{
-  test_skip(true, has_memcached());
-
-  server_startup_st *servers= (server_startup_st*)object;
-  test_true(servers);
-  servers->clear();
-
-  testing_service= "memcached";
-
-  return TEST_SUCCESS;
-}
-
-test_st memcached_TESTS[] ={
-  {"memcached startup-shutdown", 0, server_startup_TEST },
-  {"memcached(socket file) startup-shutdown", 0, socket_server_startup_TEST },
-  {"_compare(memcached_return_t)", 0, _compare_memcached_return_t_test },
-  {"server_startup(fail)", 0, server_startup_fail_TEST },
-  {0, 0, 0}
-};
-
-test_st test_skip_TESTS[] ={
-  {"true, true", 0, test_skip_true_TEST },
-  {"true, false", 0, test_skip_false_TEST },
-  {0, 0, 0}
-};
-
-test_st environment_tests[] ={
-  {"getenv()", 0, getenv_TEST },
-  {"LIBTOOL_COMMAND", 0, LIBTOOL_COMMAND_test },
-  {"VALGRIND_COMMAND", 0, VALGRIND_COMMAND_test },
-  {"HELGRIND_COMMAND", 0, HELGRIND_COMMAND_test },
-  {"GDB_COMMAND", 0, GDB_COMMAND_test },
-  {0, 0, 0}
-};
-
-test_st tests_log[] ={
-  {"TEST_SUCCESS", false, test_success_test },
-  {"TEST_FAILURE", false, test_failure_test },
-  {"TEST_SUCCESS == 0", false, test_success_equals_one_test },
-  {"SUCCESS", false, test_throw_success_TEST },
-  {"libtest::__skipped", false, test_throw_skip_TEST },
-  {"SKIP_IF", false, test_throw_skip_macro_TEST },
-  {"SKIP_UNLESS", false, test_throw_skip_unless_macro_TEST },
-  {"FAIL", false, test_throw_fail_TEST },
-  {"ASSERT_FALSE_", false, ASSERT_FALSE__TEST },
-  {"ASSERT_FALSE", false, ASSERT_FALSE_TEST },
-  {"ASSERT_NEQ", false, ASSERT_NEQ_TEST },
-  {"ASSERT_NEQ FAIL", false, ASSERT_NEQ_FAIL_TEST },
-  {0, 0, 0}
-};
-
-test_st local_log[] ={
-  {"test_is_local()", 0, local_test },
-  {"test_is_local(NOT)", 0, local_not_test },
-  {0, 0, 0}
-};
-
-test_st directories_tests[] ={
-  {"var exists", 0, var_exists_test },
-  {"var/tmp exists", 0, var_tmp_exists_test },
-  {"var/run exists", 0, var_run_exists_test },
-  {"var/log exists", 0, var_log_exists_test },
-  {"var/drizzle exists", 0, var_drizzle_exists_test },
-  {"var/tmp", 0, var_tmp_test },
-  {"var/run", 0, var_run_test },
-  {"var/log", 0, var_log_test },
-  {"var/drizzle", 0, var_drizzle_test },
-  {"var/tmp rm", 0, var_tmp_rm_test },
-  {"var/run rm", 0, var_run_rm_test },
-  {"var/log rm", 0, var_log_rm_test },
-  {"var/drizzle rm", 0, var_drizzle_rm_test },
-  {0, 0, 0}
-};
-
-test_st comparison_tests[] ={
-  {"_compare(test_return_t)", 0, _compare_test_return_t_test },
-  {0, 0, 0}
-};
-
-test_st cmdline_tests[] ={
-  {"echo fubar", 0, echo_fubar_BINARY },
-  {"core-count", 0, core_count_BINARY },
-  {"wait --quiet", 0, wait_BINARY },
-  {"wait --quiet --help", 0, wait_help_BINARY },
-  {"wait --quiet --version", 0, wait_version_BINARY },
-  {"wait --quiet /etc/services", 0, wait_services_BINARY },
-  {"wait /etc/services", 0, wait_services_BINARY2 },
-  {"wait /etc/services", 0, wait_services_appliction_TEST },
-  {"gdb wait /etc/services", 0, gdb_wait_services_appliction_TEST },
-  {"gdb abort", 0, gdb_abort_services_appliction_TEST },
-  {0, 0, 0}
-};
-
-test_st get_free_port_TESTS[] ={
-  {"get_free_port()", 0, get_free_port_TEST },
-  {"default_port()", 0, default_port_TEST },
-  {0, 0, 0}
-};
-
-test_st fatal_message_TESTS[] ={
-  {"libtest::fatal", 0, fatal_TEST },
-  {"fatal_message()", 0, fatal_message_TEST },
-  {0, 0, 0}
-};
-
-test_st number_of_cpus_TESTS[] ={
-  {"libtest::number_of_cpus()", 0, number_of_cpus_TEST },
-  {0, 0, 0}
-};
-
-test_st create_tmpfile_TESTS[] ={
-  {"libtest::create_tmpfile()", 0, create_tmpfile_TEST },
-  {0, 0, 0}
-};
-
-test_st timer_TESTS[] ={
-  {"libtest::Timer", 0, Timer_TEST },
-  {0, 0, 0}
-};
-
-test_st dns_TESTS[] ={
-  {"libtest::lookup(true)", 0, lookup_true_TEST },
-  {"libtest::lookup(false)", 0, lookup_false_TEST },
-  {"libtest::check_dns()", 0, check_dns_TEST },
-  {0, 0, 0}
-};
-
-test_st application_tests[] ={
-  {"vchar_t", 0, vchar_t_TEST },
-  {"vchar_t make() append()", 0, vchar_t_make_append_TEST },
-  {"vchar_t compare()", 0, vchar_t_compare_neg_TEST },
-  {"true", 0, application_true_BINARY },
-  {"gbd true --fubar", 0, application_gdb_true_BINARY },
-  {"gbd true", 0, application_gdb_true_BINARY2 },
-  {"true --fubar", 0, application_true_fubar_BINARY },
-  {"doesnotexist --fubar", 0, application_doesnotexist_BINARY },
-  {"echo fubar", 0, application_echo_fubar_BINARY },
-  {"echo fubar (as option)", 0, application_echo_fubar_BINARY2 },
-  {0, 0, 0}
-};
-
-static test_return_t check_for_curl(void *)
-{
-  test_skip_valgrind();
-  test_skip(true, HAVE_LIBCURL);
-  return TEST_SUCCESS;
-}
-
-static test_return_t disable_fatal_exception(void *)
-{
-  fatal_calls= 0;
-  fatal::disable();
-  return TEST_SUCCESS;
-}
-
-static test_return_t enable_fatal_exception(void *)
-{
-  fatal::enable();
-  return TEST_SUCCESS;
-}
-
-test_st http_tests[] ={
-  {"GET", 0, GET_TEST },
-  {"POST", 0, POST_TEST },
-  {"TRACE", 0, TRACE_TEST },
-  {0, 0, 0}
-};
-
-collection_st collection[] ={
-  {"environment", 0, 0, environment_tests},
-  {"return values", 0, 0, tests_log},
-  {"test_skip()", 0, 0, test_skip_TESTS },
-  {"local", 0, 0, local_log},
-  {"directories", 0, 0, directories_tests},
-  {"comparison", 0, 0, comparison_tests},
-  {"gearmand", check_for_gearman, clear_servers, gearmand_tests},
-  {"memcached", check_for_memcached, clear_servers, memcached_TESTS },
-  {"drizzled", check_for_drizzle, clear_servers, drizzled_tests},
-  {"cmdline", 0, 0, cmdline_tests},
-  {"application", 0, 0, application_tests},
-  {"http", check_for_curl, 0, http_tests},
-  {"http", check_for_curl, 0, http_tests},
-  {"get_free_port()", 0, 0, get_free_port_TESTS },
-  {"fatal", disable_fatal_exception, enable_fatal_exception, fatal_message_TESTS },
-  {"number_of_cpus()", 0, 0, number_of_cpus_TESTS },
-  {"create_tmpfile()", 0, 0, create_tmpfile_TESTS },
-  {"dns", check_for_VALGRIND, 0, dns_TESTS },
-  {"libtest::Timer", 0, 0, timer_TESTS },
-  {0, 0, 0, 0}
-};
-
-static void *world_create(server_startup_st& servers, test_return_t&)
-{
-  return &servers;
-}
-
-void get_world(libtest::Framework *world)
-{
-  world->collections(collection);
-  world->create(world_create);
-}
diff --git a/libtest/valgrind.h b/libtest/valgrind.h
deleted file mode 100644 (file)
index effeddc..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-static inline bool valgrind_is_caller(void)
-{
-  if (getenv("LOG_COMPILER")  && strstr(getenv("LOG_COMPILER"), "valgrind"))
-  {
-    if (strstr(getenv("LOG_COMPILER"), "--tool") == NULL)
-    {
-      return true;
-    }
-
-    if (strstr(getenv("LOG_COMPILER"), "--tool=memcheck"))
-    {
-      return true;
-    }
-  }
-
-  return false;
-}
diff --git a/libtest/vchar.cc b/libtest/vchar.cc
deleted file mode 100644 (file)
index a4bddfd..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-#include <libtest/common.h>
-
-/* Use this for string generation */
-static const char ALPHANUMERICS[]=
-  "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
-
-#define ALPHANUMERICS_SIZE (sizeof(ALPHANUMERICS)-1)
-
-static size_t get_alpha_num(void)
-{
-  return (size_t)random() % ALPHANUMERICS_SIZE;
-}
-
-namespace libtest {
-
-int random_alpha_num(void)
-{
-  return ALPHANUMERICS[get_alpha_num()];
-}
-
-static std::string printer(const char *str, size_t length)
-{
-  std::ostringstream buf;
-  for (size_t x= 0; x < length; x++)
-  {
-    if (isprint(str[x]))
-    {
-      buf << str[x];
-    }
-    else
-    {
-      buf << "(" << int(str[x]) << ")";
-    }
-  }
-
-  return buf.str();
-}
-
-namespace vchar {
-
-int compare(libtest::vchar_t& arg, const char *str, size_t length)
-{
-  if (arg.size() == length and (memcmp(&arg[0], str, length) == 0))
-  {
-    return 0;
-  }
-  else if (arg.size() > length)
-  {
-    return 1;
-  }
-
-  return -1;
-}
-
-void make(libtest::vchar_t& arg)
-{
-  size_t length= rand() % 1024;
-  make(arg, length);
-}
-
-void make(libtest::vchar_t& arg, size_t length)
-{
-  arg.reserve(length);
-  for (uint32_t x= 0; x < length; ++x)
-  {
-    arg.push_back(ALPHANUMERICS[get_alpha_num()]);
-  }
-}
-
-void chomp(libtest::vchar_t& arg)
-{
-  while(arg.size())
-  {
-    if (arg.back() == 0)
-    {
-      arg.pop_back();
-    }
-    else
-    {
-      break;
-    }
-  }
-}
-
-void append(libtest::vchar_ptr_t& arg, const char* ptr)
-{
-  if (ptr)
-  {
-    char* new_ptr= strdup(ptr);
-    if (new_ptr == NULL)
-    {
-      FATAL("UNABLE to allocate %s(%p)", ptr, ptr);
-    }
-
-    arg.push_back(new_ptr);
-  }
-}
-
-void append(libtest::vchar_t& arg, const char* ptr)
-{
-  if (ptr)
-  {
-    size_t length= strlen(ptr);
-    ASSERT_TRUE(length);
-    arg.reserve(length);
-    do
-    {
-      arg.push_back(*ptr);
-      ++ptr;
-    } while (*ptr);
-
-    arg.push_back(0);
-  }
-}
-
-} // namespace vchar
-
-void make_vector(libtest::vchar_t& arg, const char *str, size_t length)
-{
-  arg.resize(length);
-  memcpy(&arg[0], str, length);
-}
-
-std::ostream& operator<<(std::ostream& output, const libtest::vchar_t& arg)
-{
-  std::string tmp= libtest::printer(arg.data(), arg.size());
-  output << tmp <<  "[" << arg.size() << "]";
-
-  return output;
-}
-
-} // namespace libtest
diff --git a/libtest/vchar.hpp b/libtest/vchar.hpp
deleted file mode 100644 (file)
index 541bb92..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <cstring>
-#include <iostream>
-#include <ostream>
-#include <sstream>
-#include <vector>
-
-namespace libtest {
-
-int random_alpha_num(void);
-
-typedef std::vector<char*> vchar_ptr_t;
-typedef std::vector<char> vchar_t;
-
-void make_vector(libtest::vchar_t& arg, const char *str, size_t length);
-
-namespace vchar {
-
-int compare(libtest::vchar_t& arg, const char *str, size_t length);
-void chomp(libtest::vchar_t& arg);
-void make(libtest::vchar_t& arg);
-void make(libtest::vchar_t& arg, size_t length);
-void append(libtest::vchar_ptr_t& arg, const char*);
-void append(libtest::vchar_t& arg, const char*);
-
-} // namespace vchar
-
-#define vchar_param(__arg) (&__arg[0]), (__arg.size())
-#define vchar_printf(__arg) int(__arg.size()), (&__arg[0])
-
-std::ostream& operator<<(std::ostream& output, const libtest::vchar_t& arg);
-
-} // namespace libtest
-
diff --git a/libtest/version.h.in b/libtest/version.h.in
deleted file mode 100644 (file)
index 1bec2a8..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Data Differential YATL (i.e. libtest) library
- *
- *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#define LIBTEST_VERSION @LIBTEST_VERSION@
-#define LIBTEST_VERSION_STRING "@LIBTEST_VERSION@"
diff --git a/libtest/visibility.h b/libtest/visibility.h
deleted file mode 100644 (file)
index 72a15c1..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#if defined(BUILDING_LIBTEST)
-# if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
-#  define LIBTEST_API __attribute__ ((visibility("default")))
-#  define LIBTEST_LOCAL  __attribute__ ((visibility("default")))
-# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
-#  define LIBTEST_API __global
-#  define LIBTEST_LOCAL __global
-# elif defined(_MSC_VER)
-#  define LIBTEST_API extern __declspec(dllexport) 
-#  define LIBTEST_LOCAL extern __declspec(dllexport)
-# else
-#  define LIBTEST_API
-#  define LIBTEST_LOCAL
-# endif
-#else
-# if defined(BUILDING_LIBTEST)
-#  if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
-#   define LIBTEST_API __attribute__ ((visibility("default")))
-#   define LIBTEST_LOCAL  __attribute__ ((visibility("hidden")))
-#  elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
-#   define LIBTEST_API __global
-#   define LIBTEST_LOCAL __hidden
-#  elif defined(_MSC_VER)
-#   define LIBTEST_API extern __declspec(dllexport) 
-#   define LIBTEST_LOCAL
-#  else
-#   define LIBTEST_API
-#   define LIBTEST_LOCAL
-#  endif /* defined(HAVE_VISIBILITY) */
-# else  /* defined(BUILDING_LIBTEST) */
-#  if defined(_MSC_VER)
-#   define LIBTEST_API extern __declspec(dllimport) 
-#   define LIBTEST_LOCAL
-#  else
-#   define LIBTEST_API
-#   define LIBTEST_LOCAL
-#  endif /* defined(_MSC_VER) */
-# endif /* defined(BUILDING_LIBTEST) */
-#endif /* defined(BUILDING_LIBTESTINTERNAL) */
diff --git a/libtest/wait.cc b/libtest/wait.cc
deleted file mode 100644 (file)
index d1292e1..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "libtest/yatlcon.h"
-
-#include <cstdlib>
-#include <fcntl.h>
-#include <getopt.h>
-#include <iostream>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <libtest/wait.h>
-
-static void version_command(const char *command_name, int major_version, int minor_version)
-{
-  std::cout << command_name << " " << major_version << "." << minor_version << std::endl;
-}
-
-static void help_command(const char *command_name,
-                         int major_version, int minor_version,
-                         const struct option *long_options)
-{
-  std::cout << command_name << " " << major_version << "." << minor_version << std::endl;
-  std::cout << "Current options. A '=' means the option takes a value." << std::endl << std::endl;
-
-  for (uint32_t x= 0; long_options[x].name; x++)
-  {
-    std::cout << "\t --" << long_options[x].name << char(long_options[x].has_arg ? '=' : ' ') << std::endl;
-  }
-
-  std::cout << std::endl;
-}
-
-static void close_stdio(void)
-{
-  int fd;
-  if ((fd = open("/dev/null", O_RDWR, 0)) < 0)
-  {
-    return;
-  }
-  else
-  {
-    if (dup2(fd, STDIN_FILENO) < 0)
-    {
-      return;
-    }
-
-    if (dup2(fd, STDOUT_FILENO) < 0)
-    {
-      return;
-    }
-
-    if (dup2(fd, STDERR_FILENO) < 0)
-    {
-      return;
-    }
-
-    if (fd > STDERR_FILENO)
-    {
-      close(fd);
-    }
-  }
-}
-
-enum {
-  OPT_HELP,
-  OPT_QUIET,
-  OPT_VERSION
-};
-
-static void options_parse(int argc, char *argv[])
-{
-  static struct option long_options[]=
-  {
-    { "version", no_argument, NULL, OPT_VERSION},
-    { "help", no_argument, NULL, OPT_HELP},
-    { "quiet", no_argument, NULL, OPT_QUIET},
-    {0, 0, 0, 0},
-  };
-
-  bool opt_version= false;
-  bool opt_help= false;
-  bool opt_quiet= false;
-  int option_index= 0;
-
-  while (1)
-  {
-    int option_rv= getopt_long(argc, argv, "", long_options, &option_index);
-    if (option_rv == -1) 
-    {
-      break;
-    }
-
-    switch (option_rv)
-    {
-    case OPT_HELP: /* --help or -h */
-      opt_help= true;
-      break;
-
-    case OPT_VERSION: /* --version or -v */
-      opt_version= true;
-      break;
-
-    case OPT_QUIET:
-      opt_quiet= true;
-      break;
-
-    case '?':
-      /* getopt_long already printed an error message. */
-      exit(EXIT_FAILURE);
-
-    default:
-      help_command(argv[0], 1, 0, long_options);
-      exit(EXIT_FAILURE);
-    }
-  }
-
-  if (opt_quiet)
-  {
-    close_stdio();
-  }
-
-  if (opt_version)
-  {
-    version_command(argv[0], 1, 0);
-    exit(EXIT_SUCCESS);
-  }
-
-  if (opt_help)
-  {
-    help_command(argv[0], 1, 0, long_options);
-    exit(EXIT_SUCCESS);
-  }
-}
-
-int main(int argc, char *argv[])
-{
-  if (argc == 1)
-  {
-    return EXIT_FAILURE;
-  }
-
-  options_parse(argc, argv);
-
-  int ret= EXIT_FAILURE;
-  while (optind < argc)
-  {
-    libtest::Wait wait(argv[optind++]);
-
-    if (wait.successful() == false)
-    {
-      return EXIT_FAILURE;
-    }
-
-    ret= EXIT_SUCCESS;
-  }
-
-  return ret;
-}
diff --git a/libtest/wait.h b/libtest/wait.h
deleted file mode 100644 (file)
index e5cdcb3..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <unistd.h>
-#include <string>
-#include <signal.h>
-
-#include <libtest/dream.h>
-
-namespace libtest {
-
-class Wait 
-{
-public:
-
-  Wait(const std::string &filename, uint32_t timeout= 6) :
-    _successful(false)
-  {
-    uint32_t waited;
-    uint32_t this_wait;
-    uint32_t retry;
-
-    if (filename.empty())
-    {
-      _successful= false;
-      return;
-    }
-
-    for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
-    {
-      if (access(filename.c_str(), R_OK) == 0)
-      {
-        _successful= true;
-        break;
-      }
-      else if (waited >= timeout)
-      {
-        break;
-      }
-
-      this_wait= retry * retry / 3 + 1;
-      libtest::dream(0, this_wait * 10000000);
-    }
-  }
-
-  Wait(const pid_t &_pid_arg, uint32_t timeout= 6) :
-    _successful(false)
-  {
-    uint32_t waited;
-    uint32_t this_wait;
-    uint32_t retry;
-
-    for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
-    {
-      if (kill(_pid_arg, 0) == 0)
-      {
-        _successful= true;
-        break;
-      }
-      else if (waited >= timeout)
-      {
-        break;
-      }
-
-      this_wait= retry * retry / 3 + 1;
-      libtest::dream(0, this_wait * 10000000);
-    }
-  }
-
-  bool successful() const
-  {
-    return _successful;
-  }
-
-private:
-  bool _successful;
-};
-
-} // namespace libtest
diff --git a/libtest/yatl.h b/libtest/yatl.h
deleted file mode 100644 (file)
index 6da02a3..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential YATL (i.e. libtest)  library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#ifndef YATL_FULL
-# define YATL_FULL 1
-#endif
-
-#include <libtest/test.hpp>
diff --git a/libtest/yatlcon.h.in b/libtest/yatlcon.h.in
deleted file mode 100644 (file)
index e5adefb..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  Data Differential YATL (i.e. libtest) library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#pragma once
-
-#include "@AUTOHEADER_FILE@"
-
-#ifndef LIBTEST_TEMP
-# define LIBTEST_TEMP "/tmp"
-#endif
-
-#define HAVE_LIBMEMCACHED 1
diff --git a/mem_config.h.in b/mem_config.h.in
deleted file mode 100644 (file)
index de2cdb7..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#pragma once
-
-#cmakedefine01 LIBMEMCACHED_WITH_SASL_SUPPORT
-
-#define LIBMEMCACHED_WITH_SASL_PWDB "@LIBMEMCACHED_WITH_SASL_PWDB@"
-#define LIBMEMCACHED_WITH_SASL_CONF "@LIBMEMCACHED_WITH_SASL_CONF@"
-
-#cmakedefine HAVE_C_STDATOMIC 1
-#cmakedefine HAVE_CXX_STDATOMIC 1
-
-#cmakedefine HAVE_ARPA_INET_H 1
-#cmakedefine HAVE_DLFCN_H 1
-#cmakedefine HAVE_DTRACE 1
-#cmakedefine HAVE_ERRNO_H 1
-#cmakedefine HAVE_EXECINFO_H 1
-#cmakedefine HAVE_FCNTL 1
-#cmakedefine HAVE_FCNTL_H 1
-#cmakedefine HAVE_FNV64_HASH 1
-#cmakedefine HAVE_GETLINE
-#cmakedefine HAVE_HSIEH_HASH 1
-#cmakedefine HAVE_HTONLL 1
-#cmakedefine HAVE_IN_PORT_T 1
-#cmakedefine HAVE_IO_H 1
-#cmakedefine HAVE_LIBEVENT 1
-#cmakedefine HAVE_LIBSASL 1
-#cmakedefine HAVE_LIBUUID 1
-#cmakedefine HAVE_LIMITS_H 1
-#cmakedefine HAVE_MSG_DONTWAIT 1
-#cmakedefine HAVE_MSG_MORE 1
-#cmakedefine HAVE_MSG_NOSIGNAL 1
-#cmakedefine HAVE_MURMUR_HASH 1
-#cmakedefine HAVE_NETDB_H 1
-#cmakedefine HAVE_POLL_H 1
-#cmakedefine HAVE_RCVTIMEO 1
-#cmakedefine HAVE_SASL_SASL_H 1
-#cmakedefine HAVE_SHARED_ENABLED 1
-#cmakedefine HAVE_SNDTIMEO 1
-#cmakedefine HAVE_STDDEF_H 1
-#cmakedefine HAVE_STDLIB_H 1
-#cmakedefine HAVE_STRERROR 1
-#cmakedefine HAVE_STRERROR_R 1
-#cmakedefine HAVE_STRINGS_H 1
-#cmakedefine HAVE_SYS_SOCKET_H 1
-#cmakedefine HAVE_SYS_TIME_H 1
-#cmakedefine HAVE_SYS_TYPES_H 1
-#cmakedefine HAVE_SYS_WAIT_H 1
-#cmakedefine HAVE_SYS_UN_H 1
-#cmakedefine HAVE_TIME_H 1
-#cmakedefine HAVE_UMEM_H 1
-#cmakedefine HAVE_UNISTD_H 1
-#cmakedefine HAVE_VISIBILITY 1
-#cmakedefine HAVE_WINSOCK2_H 1
-#cmakedefine HAVE_WS2TCPIP_H 1
-
-#cmakedefine HAVE_ABI____CXA_DEMANGLE 1
-#cmakedefine HAVE_GCC_ABI_DEMANGLE 1
-
-#cmakedefine HAVE_CINTTYPES 1
-#cmakedefine HAVE_CSTDINT 1
-#if defined(__cplusplus)
-# if defined HAVE_CINTTYPES
-#  include <cinttypes>
-# elif defined HAVE_CSTDINT
-#  include <cstdint>
-# endif
-#else
-#  include <inttypes.h>
-#endif
-
-#define HAVE_LIBMEMCACHED 1
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1069911
--- /dev/null
@@ -0,0 +1,9 @@
+
+add_subdirectory(bin)
+add_subdirectory(libhashkit)
+add_subdirectory(libmemcached)
+add_subdirectory(libmemcachedutil)
+
+if(BUILD_TESTING)
+    add_subdirectory(libtest)
+endif()
diff --git a/src/bin/CMakeLists.txt b/src/bin/CMakeLists.txt
new file mode 100644 (file)
index 0000000..8cd4246
--- /dev/null
@@ -0,0 +1,35 @@
+
+add_library(libclient_utilities STATIC utilities.cc generator.cc execute.cc)
+add_library(client_utilities ALIAS libclient_utilities)
+target_link_libraries(libclient_utilities libmemcachedinternal)
+
+foreach(CLIENT IN LISTS CLIENTS)
+    add_executable(${CLIENT} ${CLIENT}.cc)
+    target_include_directories(${CLIENT} PRIVATE ..)
+    target_link_libraries(${CLIENT} libclient_utilities)
+    install(TARGETS ${CLIENT}
+            RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+endforeach()
+
+# extra sources
+
+target_sources(memcapable PRIVATE ../libmemcached/byteorder.cc)
+
+# extra libs
+
+target_link_libraries(memcapable Threads::Threads)
+target_link_libraries(memping libmemcachedutil)
+target_link_libraries(memslap Threads::Threads)
+
+# memaslap is special
+
+if(ENABLE_MEMASLAP)
+    if(LIBEVENT AND HAVE_C_STDATOMIC)
+        add_executable(memaslap memaslap.c
+                ms_conn.c ms_setting.c ms_sigsegv.c ms_stats.c ms_task.c ms_thread.c)
+        target_include_directories(memaslap PRIVATE ${LIBEVENT_INCLUDEDIR})
+        target_link_libraries(memaslap libclient_utilities ${LIBEVENT_LIBRARIES} Threads::Threads)
+        install(TARGETS memaslap
+                RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
+    endif()
+endif()
diff --git a/src/bin/client_options.h b/src/bin/client_options.h
new file mode 100644 (file)
index 0000000..16ce4be
--- /dev/null
@@ -0,0 +1,45 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+#pragma once
+
+typedef struct memcached_help_text_st memcached_help_text_st;
+
+enum memcached_options {
+  OPT_SERVERS= 's',
+  OPT_VERSION= 'V',
+  OPT_HELP= 'h',
+  OPT_VERBOSE= 'v',
+  OPT_DEBUG= 'd',
+  OPT_ANALYZE= 'a',
+  OPT_FLAG= 257,
+  OPT_EXPIRE,
+  OPT_SET,
+  OPT_REPLACE,
+  OPT_ADD,
+  OPT_SLAP_EXECUTE_NUMBER,
+  OPT_SLAP_INITIAL_LOAD,
+  OPT_SLAP_TEST,
+  OPT_SLAP_CONCURRENCY,
+  OPT_SLAP_NON_BLOCK,
+  OPT_SLAP_TCP_NODELAY,
+  OPT_FLUSH,
+  OPT_HASH,
+  OPT_BINARY,
+  OPT_UDP,
+  OPT_BUFFER,
+  OPT_USERNAME,
+  OPT_PASSWD,
+  OPT_STAT_ARGS,
+  OPT_SERVER_VERSION,
+  OPT_QUIET,
+  OPT_FILE= 'f'
+};
diff --git a/src/bin/execute.cc b/src/bin/execute.cc
new file mode 100644 (file)
index 0000000..3714840
--- /dev/null
@@ -0,0 +1,142 @@
+/* LibMemcached
+ * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+/*
+  Execute a memcached_set() a set of pairs.
+  Return the number of rows set.
+*/
+
+#include <mem_config.h>
+#include "execute.h"
+
+unsigned int execute_set(memcached_st *memc, pairs_st *pairs, unsigned int number_of)
+{
+  uint32_t count= 0;
+  for (; count < number_of; ++count)
+  {
+    memcached_return_t rc= memcached_set(memc, pairs[count].key, pairs[count].key_length,
+                                         pairs[count].value, pairs[count].value_length,
+                                         0, 0);
+    if (memcached_failed(rc))
+    {
+      fprintf(stderr, "%s:%d Failure on %u insert (%s) of %.*s\n",
+              __FILE__, __LINE__, count,
+              memcached_last_error_message(memc),
+              (unsigned int)pairs[count].key_length, pairs[count].key);
+      
+      // We will try to reconnect and see if that fixes the issue
+      memcached_quit(memc);
+
+      return count;
+    }
+  }
+
+  return count;
+}
+
+/*
+  Execute a memcached_get() on a set of pairs.
+  Return the number of rows retrieved.
+*/
+unsigned int execute_get(memcached_st *memc, pairs_st *pairs, unsigned int number_of)
+{
+  unsigned int x;
+  unsigned int retrieved;
+
+
+  for (retrieved= 0,x= 0; x < number_of; x++)
+  {
+    size_t value_length;
+    uint32_t flags;
+
+    unsigned int fetch_key= (unsigned int)((unsigned int)random() % number_of);
+
+    memcached_return_t rc;
+    char *value= memcached_get(memc, pairs[fetch_key].key, pairs[fetch_key].key_length,
+                               &value_length, &flags, &rc);
+
+    if (memcached_failed(rc))
+    {
+      fprintf(stderr, "%s:%d Failure on read(%s) of %.*s\n",
+              __FILE__, __LINE__,
+              memcached_last_error_message(memc),
+              (unsigned int)pairs[fetch_key].key_length, pairs[fetch_key].key);
+    }
+    else
+    {
+      retrieved++;
+    }
+
+    ::free(value);
+  }
+
+  return retrieved;
+}
+
+/**
+ * Callback function to count the number of results
+ */
+static memcached_return_t callback_counter(const memcached_st *ptr,
+                                           memcached_result_st *result,
+                                           void *context)
+{
+  (void)ptr;
+  (void)result;
+  unsigned int *counter= (unsigned int *)context;
+  *counter= *counter + 1;
+
+  return MEMCACHED_SUCCESS;
+}
+
+/**
+ * Try to run a large mget to get all of the keys
+ * @param memc memcached handle
+ * @param keys the keys to get
+ * @param key_length the length of the keys
+ * @param number_of the number of keys to try to get
+ * @return the number of keys received
+ */
+unsigned int execute_mget(memcached_st *memc,
+                          const char * const *keys,
+                          size_t *key_length,
+                          unsigned int number_of)
+{
+  unsigned int retrieved= 0;
+  memcached_execute_fn callbacks[]= { callback_counter };
+  memcached_return_t rc;
+  rc= memcached_mget_execute(memc, keys, key_length,
+                             (size_t)number_of, callbacks, &retrieved, 1);
+
+  if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_NOTFOUND ||
+          rc == MEMCACHED_BUFFERED || rc == MEMCACHED_END)
+  {
+    rc= memcached_fetch_execute(memc, callbacks, (void *)&retrieved, 1);
+    if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_NOTFOUND && rc != MEMCACHED_END)
+    {
+      fprintf(stderr, "%s:%d Failed to execute mget: %s\n",
+              __FILE__, __LINE__,
+              memcached_strerror(memc, rc));
+      memcached_quit(memc);
+      return 0;
+    }
+  }
+  else
+  {
+    fprintf(stderr, "%s:%d Failed to execute mget: %s\n",
+            __FILE__, __LINE__,
+            memcached_strerror(memc, rc));
+    memcached_quit(memc);
+    return 0;
+  }
+
+  return retrieved;
+}
diff --git a/src/bin/execute.h b/src/bin/execute.h
new file mode 100644 (file)
index 0000000..e66b0c5
--- /dev/null
@@ -0,0 +1,30 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+#pragma once 
+
+#include <stdio.h>
+
+#include <libmemcached-1.0/memcached.h>
+#include "generator.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+unsigned int execute_set(memcached_st *memc, pairs_st *pairs, unsigned int number_of);
+unsigned int execute_get(memcached_st *memc, pairs_st *pairs, unsigned int number_of);
+unsigned int execute_mget(memcached_st *memc, const char * const *keys, size_t *key_length,
+                          unsigned int number_of);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/bin/generator.cc b/src/bin/generator.cc
new file mode 100644 (file)
index 0000000..e418fd7
--- /dev/null
@@ -0,0 +1,109 @@
+/* LibMemcached
+ * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+#include <mem_config.h>
+
+#include <stdint.h>
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <unistd.h>
+
+#include "generator.h"
+
+#define KEY_BYTES 20
+
+/* Use this for string generation */
+static const char ALPHANUMERICS[]=
+  "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
+
+#define ALPHANUMERICS_SIZE (sizeof(ALPHANUMERICS)-1)
+
+static size_t get_alpha_num(void)
+{
+  return (size_t)random() % ALPHANUMERICS_SIZE;
+}
+
+void get_random_string(char *buffer, size_t size)
+{
+  char *buffer_ptr= buffer;
+
+  while (--size)
+  {
+    *buffer_ptr++= ALPHANUMERICS[get_alpha_num()];
+  }
+  *buffer_ptr++= ALPHANUMERICS[get_alpha_num()];
+}
+
+void pairs_free(pairs_st *pairs)
+{
+  if (pairs == NULL)
+  {
+    return;
+  }
+
+  /* We free until we hit the null pair we stores during creation */
+  for (uint32_t x= 0; pairs[x].key; x++)
+  {
+    free(pairs[x].key);
+    if (pairs[x].value)
+    {
+      free(pairs[x].value);
+    }
+  }
+
+  free(pairs);
+}
+
+pairs_st *pairs_generate(uint64_t number_of, size_t value_length)
+{
+  pairs_st *pairs= (pairs_st*)calloc((size_t)number_of + 1, sizeof(pairs_st));
+
+  if (pairs == NULL)
+  {
+    goto error;
+  }
+
+  for (uint64_t x= 0; x < number_of; x++)
+  {
+    pairs[x].key= (char *)calloc(KEY_BYTES, sizeof(char));
+
+    if (pairs[x].key == NULL)
+      goto error;
+
+    get_random_string(pairs[x].key, KEY_BYTES);
+    pairs[x].key_length= KEY_BYTES;
+
+    if (value_length)
+    {
+      pairs[x].value= (char *)calloc(value_length, sizeof(char));
+
+      if (pairs[x].value == NULL)
+        goto error;
+
+      get_random_string(pairs[x].value, value_length);
+      pairs[x].value_length= value_length;
+    }
+    else
+    {
+      pairs[x].value= NULL;
+      pairs[x].value_length= 0;
+    }
+  }
+
+  return pairs;
+error:
+  std::cerr << "Memory Allocation failure in pairs_generate." << std::endl;
+  exit(EXIT_SUCCESS);
+}
diff --git a/src/bin/generator.h b/src/bin/generator.h
new file mode 100644 (file)
index 0000000..e60bfb3
--- /dev/null
@@ -0,0 +1,36 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+/*
+  Code to generate data to be pushed into memcached
+*/
+
+#pragma once
+
+typedef struct pairs_st pairs_st;
+
+struct pairs_st {
+  char *key;
+  size_t key_length;
+  char *value;
+  size_t value_length;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+pairs_st *pairs_generate(uint64_t number_of, size_t value_length);
+void pairs_free(pairs_st *pairs);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/bin/memaslap.c b/src/bin/memaslap.c
new file mode 100644 (file)
index 0000000..dc41135
--- /dev/null
@@ -0,0 +1,917 @@
+/*
+ *  memslap
+ *
+ *  (c) Copyright 2009, Schooner Information Technology, Inc.
+ *  All rights reserved.
+ *  http://www.schoonerinfotech.com/
+ *
+ *  Use and distribution licensed under the BSD license.  See
+ *  the COPYING file for full text.
+ *
+ *  Authors:
+ *      Brian Aker
+ *      Mingqiang Zhuang <mingqiangzhuang@hengtiansoft.com>
+ *
+ */
+#include "mem_config.h"
+
+#include <stdlib.h>
+#include <getopt.h>
+#include <limits.h>
+
+#if defined(HAVE_SYS_TIME_H)
+# include <sys/time.h>
+#endif
+
+#if defined(HAVE_TIME_H)
+# include <time.h>
+#endif
+
+
+#include "ms_sigsegv.h"
+#include "ms_setting.h"
+#include "ms_thread.h"
+
+#define PROGRAM_NAME    "memslap"
+#define PROGRAM_DESCRIPTION \
+                        "Generates workload against memcached servers."
+
+#ifdef __sun
+  /* For some odd reason the option struct on solaris defines the argument
+   * as char* and not const char*
+   */
+#define OPTIONSTRING char*
+#else
+#define OPTIONSTRING const char*
+#endif
+
+/* options */
+static struct option long_options[]=
+{
+  { (OPTIONSTRING)"servers",        required_argument,            NULL,
+    OPT_SERVERS            },
+  { (OPTIONSTRING)"threads",        required_argument,            NULL,
+    OPT_THREAD_NUMBER      },
+  { (OPTIONSTRING)"concurrency",    required_argument,            NULL,
+    OPT_CONCURRENCY        },
+  { (OPTIONSTRING)"conn_sock",      required_argument,            NULL,
+    OPT_SOCK_PER_CONN      },
+  { (OPTIONSTRING)"execute_number", required_argument,            NULL,
+    OPT_EXECUTE_NUMBER     },
+  { (OPTIONSTRING)"time",           required_argument,            NULL,
+    OPT_TIME               },
+  { (OPTIONSTRING)"cfg_cmd",        required_argument,            NULL,
+    OPT_CONFIG_CMD         },
+  { (OPTIONSTRING)"win_size",       required_argument,            NULL,
+    OPT_WINDOW_SIZE        },
+  { (OPTIONSTRING)"fixed_size",     required_argument,            NULL,
+    OPT_FIXED_LTH          },
+  { (OPTIONSTRING)"verify",         required_argument,            NULL,
+    OPT_VERIFY             },
+  { (OPTIONSTRING)"division",       required_argument,            NULL,
+    OPT_GETS_DIVISION      },
+  { (OPTIONSTRING)"stat_freq",      required_argument,            NULL,
+    OPT_STAT_FREQ          },
+  { (OPTIONSTRING)"exp_verify",     required_argument,            NULL,
+    OPT_EXPIRE             },
+  { (OPTIONSTRING)"overwrite",      required_argument,            NULL,
+    OPT_OVERWRITE          },
+  { (OPTIONSTRING)"reconnect",      no_argument,                  NULL,
+    OPT_RECONNECT          },
+  { (OPTIONSTRING)"udp",            no_argument,                  NULL,
+    OPT_UDP                },
+  { (OPTIONSTRING)"facebook",       no_argument,                  NULL,
+    OPT_FACEBOOK_TEST      },
+  { (OPTIONSTRING)"binary",         no_argument,                  NULL,
+    OPT_BINARY_PROTOCOL    },
+  { (OPTIONSTRING)"tps",            required_argument,            NULL,
+    OPT_TPS                },
+  { (OPTIONSTRING)"rep_write",      required_argument,            NULL,
+    OPT_REP_WRITE_SRV      },
+  { (OPTIONSTRING)"verbose",        no_argument,                  NULL,
+    OPT_VERBOSE            },
+  { (OPTIONSTRING)"help",           no_argument,                  NULL,
+    OPT_HELP               },
+  { (OPTIONSTRING)"version",        no_argument,                  NULL,
+    OPT_VERSION            },
+  { 0, 0, 0, 0 },
+};
+
+/* Prototypes */
+static void ms_sync_lock_init(void);
+static void ms_sync_lock_destroy(void);
+static void ms_global_struct_init(void);
+static void ms_global_struct_destroy(void);
+static void ms_version_command(const char *command_name);
+static const char *ms_lookup_help(ms_options_t option);
+static int64_t ms_parse_time(void);
+static int64_t ms_parse_size(void);
+static void ms_options_parse(int argc, char *argv[]);
+static int ms_check_para(void);
+static void ms_statistic_init(void);
+static void ms_stats_init(void);
+static void ms_print_statistics(int in_time);
+static void ms_print_memslap_stats(struct timeval *start_time,
+                                   struct timeval *end_time);
+static void ms_monitor_slap_mode(void);
+
+/**
+ * output the help information
+ *
+ * @param command_name, the string of this process
+ * @param description, description of this process
+ * @param long_options, global options array
+ */
+static __attribute__((noreturn)) void ms_help_command(const char *command_name, const char *description)
+{
+  char *help_message= NULL;
+
+  printf("%s v%u.%u\n", command_name, 1U, 0U);
+  printf("    %s\n\n", description);
+  printf(
+    "Usage:\n"
+    "    memslap -hV | -s servers [-F config_file] [-t time | -x exe_num] [...]\n\n"
+    "Options:\n");
+
+  for (int x= 0; long_options[x].name; x++)
+  {
+    printf("    -%c, --%s%c\n", long_options[x].val, long_options[x].name,
+           long_options[x].has_arg ? '=' : ' ');
+
+    if ((help_message= (char *)ms_lookup_help(long_options[x].val)) != NULL)
+    {
+      printf("        %s\n", help_message);
+    }
+  }
+
+  printf(
+    "\nExamples:\n"
+    "    memslap -s 127.0.0.1:11211 -S 5s\n"
+    "    memslap -s 127.0.0.1:11211 -t 2m -v 0.2 -e 0.05 -b\n"
+    "    memslap -s 127.0.0.1:11211 -F config -t 2m -w 40k -S 20s -o 0.2\n"
+    "    memslap -s 127.0.0.1:11211 -F config -t 2m -T 4 -c 128 -d 20 -P 40k\n"
+    "    memslap -s 127.0.0.1:11211 -F config -t 2m -d 50 -a -n 40\n"
+    "    memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m\n"
+    "    memslap -s 127.0.0.1:11211,127.0.0.1:11212 -F config -t 2m -p 2\n\n");
+
+  exit(0);
+} /* ms_help_command */
+
+
+/* initialize the global locks */
+static void ms_sync_lock_init()
+{
+  ms_global.init_lock.count= 0;
+  pthread_mutex_init(&ms_global.init_lock.lock, NULL);
+  pthread_cond_init(&ms_global.init_lock.cond, NULL);
+
+  ms_global.warmup_lock.count = 0;
+  pthread_mutex_init(&ms_global.warmup_lock.lock, NULL);
+  pthread_cond_init(&ms_global.warmup_lock.cond, NULL);
+
+  ms_global.run_lock.count= 0;
+  pthread_mutex_init(&ms_global.run_lock.lock, NULL);
+  pthread_cond_init(&ms_global.run_lock.cond, NULL);
+
+  pthread_mutex_init(&ms_global.quit_mutex, NULL);
+  pthread_mutex_init(&ms_global.seq_mutex, NULL);
+} /* ms_sync_lock_init */
+
+
+/* destroy the global locks */
+static void ms_sync_lock_destroy()
+{
+  pthread_mutex_destroy(&ms_global.init_lock.lock);
+  pthread_cond_destroy(&ms_global.init_lock.cond);
+
+  pthread_mutex_destroy(&ms_global.warmup_lock.lock);
+  pthread_cond_destroy(&ms_global.warmup_lock.cond);
+
+  pthread_mutex_destroy(&ms_global.run_lock.lock);
+  pthread_cond_destroy(&ms_global.run_lock.cond);
+
+  pthread_mutex_destroy(&ms_global.quit_mutex);
+  pthread_mutex_destroy(&ms_global.seq_mutex);
+
+  if (ms_setting.stat_freq > 0)
+  {
+    pthread_mutex_destroy(&ms_statistic.stat_mutex);
+  }
+} /* ms_sync_lock_destroy */
+
+
+/* initialize the global structure */
+static void ms_global_struct_init()
+{
+  ms_sync_lock_init();
+  ms_global.finish_warmup= false;
+  ms_global.time_out= false;
+}
+
+
+/* destroy the global structure */
+static void ms_global_struct_destroy()
+{
+  ms_sync_lock_destroy();
+}
+
+
+/**
+ * output the version information
+ *
+ * @param command_name, the string of this process
+ */
+static void ms_version_command(const char *command_name)
+{
+  printf("%s v%u.%u\n", command_name, 1U, 0U);
+  exit(0);
+}
+
+
+/**
+ * get the description of the option
+ *
+ * @param option, option of command line
+ *
+ * @return char*, description of the command option
+ */
+static const char *ms_lookup_help(ms_options_t option)
+{
+  switch (option)
+  {
+  case OPT_SERVERS:
+    return
+      "List one or more servers to connect. Servers count must be less than\n"
+      "        threads count. e.g.: --servers=localhost:1234,localhost:11211";
+
+  case OPT_VERSION:
+    return "Display the version of the application and then exit.";
+
+  case OPT_HELP:
+    return "Display this message and then exit.";
+
+  case OPT_EXECUTE_NUMBER:
+    return "Number of operations(get and set) to execute for the\n"
+           "        given test. Default 1000000.";
+
+  case OPT_THREAD_NUMBER:
+    return
+      "Number of threads to startup, better equal to CPU numbers. Default 8.";
+
+  case OPT_CONCURRENCY:
+    return "Number of concurrency to simulate with load. Default 128.";
+
+  case OPT_FIXED_LTH:
+    return "Fixed length of value.";
+
+  case OPT_VERIFY:
+    return "The proportion of date verification, e.g.: --verify=0.01";
+
+  case OPT_GETS_DIVISION:
+    return "Number of keys to multi-get once. Default 1, means single get.";
+
+  case OPT_TIME:
+    return
+      "How long the test to run, suffix: s-seconds, m-minutes, h-hours,\n"
+      "        d-days e.g.: --time=2h.";
+
+  case OPT_CONFIG_CMD:
+    return
+      "Load the configure file to get command,key and value distribution list.";
+
+  case OPT_WINDOW_SIZE:
+    return
+      "Task window size of each concurrency, suffix: K, M e.g.: --win_size=10k.\n"
+      "        Default 10k.";
+
+  case OPT_UDP:
+    return
+      "UDP support, default memslap uses TCP, TCP port and UDP port of\n"
+      "        server must be same.";
+
+  case OPT_EXPIRE:
+    return
+      "The proportion of objects with expire time, e.g.: --exp_verify=0.01.\n"
+      "        Default no object with expire time";
+
+  case OPT_OVERWRITE:
+    return
+      "The proportion of objects need overwrite, e.g.: --overwrite=0.01.\n"
+      "        Default never overwrite object.";
+
+  case OPT_STAT_FREQ:
+    return
+      "Frequency of dumping statistic information. suffix: s-seconds,\n"
+      "        m-minutes, e.g.: --resp_freq=10s.";
+
+  case OPT_SOCK_PER_CONN:
+    return "Number of TCP socks per concurrency. Default 1.";
+
+  case OPT_RECONNECT:
+    return
+      "Reconnect support, when connection is closed it will be reconnected.";
+
+  case OPT_VERBOSE:
+    return
+      "Whether it outputs detailed information when verification fails.";
+
+  case OPT_FACEBOOK_TEST:
+    return
+      "Whether it enables facebook test feature, set with TCP and multi-get with UDP.";
+
+  case OPT_BINARY_PROTOCOL:
+    return
+      "Whether it enables binary protocol. Default with ASCII protocol.";
+
+  case OPT_TPS:
+    return "Expected throughput, suffix: K, e.g.: --tps=10k.";
+
+  case OPT_REP_WRITE_SRV:
+    return "The first nth servers can write data, e.g.: --rep_write=2.";
+
+  default:
+    return "Forgot to document this option :)";
+  } /* switch */
+} /* ms_lookup_help */
+
+
+/* used to parse the time string  */
+static int64_t ms_parse_time()
+{
+  int64_t ret= 0;
+  char unit= optarg[strlen(optarg) - 1];
+
+  optarg[strlen(optarg) - 1]= '\0';
+  ret= atoi(optarg);
+
+  switch (unit)
+  {
+  case 'd':
+  case 'D':
+    ret*= 24;
+    /* fall through */
+  case 'h':
+  case 'H':
+    ret*= 60;
+    /* fall through */
+  case 'm':
+  case 'M':
+    ret*= 60;
+    /* fall through */
+  case 's':
+  case 'S':
+    break;
+
+  default:
+    ret= -1;
+    break;
+  } /* switch */
+
+  return ret;
+} /* ms_parse_time */
+
+
+/* used to parse the size string */
+static int64_t ms_parse_size()
+{
+  int64_t ret= -1;
+  char unit= optarg[strlen(optarg) - 1];
+
+  optarg[strlen(optarg) - 1]= '\0';
+  errno= 0;
+  ret= strtoll(optarg, (char **)NULL, 10);
+  if (errno != 0)
+  {
+    fprintf(stderr, "strtoll(optarg,..): %s\n", strerror(errno));
+    exit(1);
+  }
+
+  switch (unit)
+  {
+  case 'k':
+  case 'K':
+    ret*= 1024;
+    break;
+
+  case 'm':
+  case 'M':
+    ret*= 1024 * 1024;
+    break;
+
+  case 'g':
+  case 'G':
+    ret*= 1024 * 1024 * 1024;
+    break;
+
+  default:
+    ret= -1;
+    break;
+  } /* switch */
+
+  return ret;
+} /* ms_parse_size */
+
+
+/* used to parse the options of command line */
+static void ms_options_parse(int argc, char *argv[])
+{
+  int option_index= 0;
+  int option_rv;
+
+  while ((option_rv= getopt_long(argc, argv, "VhURbaBs:x:T:c:X:v:d:"
+                                             "t:S:F:w:e:o:n:P:p:",
+                                 long_options, &option_index)) != -1)
+  {
+    switch (option_rv)
+    {
+    case 0:
+      break;
+
+    case OPT_VERSION:     /* --version or -V */
+      ms_version_command(PROGRAM_NAME);
+      break;
+
+    case OPT_HELP:     /* --help or -h */
+      ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION);
+      break;
+
+    case OPT_SERVERS:     /* --servers or -s */
+      ms_setting.srv_str= strdup(optarg);
+      break;
+
+    case OPT_CONCURRENCY:       /* --concurrency or -c */
+      errno= 0;
+      ms_setting.nconns= (uint32_t)strtoul(optarg, (char **) NULL, 10);
+      if (ms_setting.nconns <= 0 || errno != 0)
+      {
+        fprintf(stderr, "Concurrency must be greater than 0.:-)\n");
+        exit(1);
+      }
+      break;
+
+    case OPT_EXECUTE_NUMBER:        /* --execute_number or -x */
+      errno= 0;
+      ms_setting.exec_num= (int)strtol(optarg, (char **) NULL, 10);
+      if (ms_setting.exec_num <= 0 || errno != 0)
+      {
+        fprintf(stderr, "Execute number must be greater than 0.:-)\n");
+        exit(1);
+      }
+      break;
+
+    case OPT_THREAD_NUMBER:     /* --threads or -T */
+      errno= 0;
+      ms_setting.nthreads= (uint32_t)strtoul(optarg, (char **) NULL, 10);
+      if (ms_setting.nthreads <= 0 || errno != 0)
+      {
+        fprintf(stderr, "Threads number must be greater than 0.:-)\n");
+        exit(1);
+      }
+      break;
+
+    case OPT_FIXED_LTH:         /* --fixed_size or -X */
+      errno= 0;
+      ms_setting.fixed_value_size= (size_t)strtoull(optarg, (char **) NULL, 10);
+      if ((ms_setting.fixed_value_size <= 0 || errno != 0)
+          || (ms_setting.fixed_value_size > MAX_VALUE_SIZE))
+      {
+        fprintf(stderr, "Value size must be between 0 and 1M.:-)\n");
+        exit(1);
+      }
+      break;
+
+    case OPT_VERIFY:        /* --verify or -v */
+      ms_setting.verify_percent= atof(optarg);
+      if ((ms_setting.verify_percent <= 0)
+          || (ms_setting.verify_percent > 1.0))
+      {
+        fprintf(stderr, "Data verification rate must be "
+                        "greater than 0 and less than 1.0. :-)\n");
+        exit(1);
+      }
+      break;
+
+    case OPT_GETS_DIVISION:         /* --division or -d */
+      errno= 0;
+      ms_setting.mult_key_num= (int)strtol(optarg, (char **) NULL, 10);
+      if (ms_setting.mult_key_num <= 0 || errno != 0)
+      {
+        fprintf(stderr, "Multi-get key number must be greater than 0.:-)\n");
+        exit(1);
+      }
+      break;
+
+    case OPT_TIME:      /* --time or -t */
+      ms_setting.run_time= (int)ms_parse_time();
+      if (ms_setting.run_time == -1)
+      {
+        fprintf(stderr, "Please specify the run time. :-)\n"
+                        "'s' for second, 'm' for minute, 'h' for hour, "
+                        "'d' for day. e.g.: --time=24h (means 24 hours).\n");
+        exit(1);
+      }
+
+      if (ms_setting.run_time == 0)
+      {
+        fprintf(stderr, "Running time can not be 0. :-)\n");
+        exit(1);
+      }
+      break;
+
+    case OPT_CONFIG_CMD:        /* --cfg_cmd or -F */
+      ms_setting.cfg_file= strdup(optarg);
+      break;
+
+    case OPT_WINDOW_SIZE:       /* --win_size or -w */
+      ms_setting.win_size= (size_t)ms_parse_size();
+      if (ms_setting.win_size == (size_t)-1)
+      {
+        fprintf(
+          stderr,
+          "Please specify the item window size. :-)\n"
+          "e.g.: --win_size=10k (means 10k task window size).\n");
+        exit(1);
+      }
+      break;
+
+    case OPT_UDP:       /* --udp or -U*/
+      ms_setting.udp= true;
+      break;
+
+    case OPT_EXPIRE:        /* --exp_verify or -e */
+      ms_setting.exp_ver_per= atof(optarg);
+      if ((ms_setting.exp_ver_per <= 0) || (ms_setting.exp_ver_per > 1.0))
+      {
+        fprintf(stderr, "Expire time verification rate must be "
+                        "greater than 0 and less than 1.0. :-)\n");
+        exit(1);
+      }
+      break;
+
+    case OPT_OVERWRITE:         /* --overwrite or -o */
+      ms_setting.overwrite_percent= atof(optarg);
+      if ((ms_setting.overwrite_percent <= 0)
+          || (ms_setting.overwrite_percent > 1.0))
+      {
+        fprintf(stderr, "Objects overwrite rate must be "
+                        "greater than 0 and less than 1.0. :-)\n");
+        exit(1);
+      }
+      break;
+
+    case OPT_STAT_FREQ:         /* --stat_freq or -S */
+      ms_setting.stat_freq= (int)ms_parse_time();
+      if (ms_setting.stat_freq == -1)
+      {
+        fprintf(stderr, "Please specify the frequency of dumping "
+                        "statistic information. :-)\n"
+                        "'s' for second, 'm' for minute, 'h' for hour, "
+                        "'d' for day. e.g.: --time=24h (means 24 hours).\n");
+        exit(1);
+      }
+
+      if (ms_setting.stat_freq == 0)
+      {
+        fprintf(stderr, "The frequency of dumping statistic information "
+                        "can not be 0. :-)\n");
+        exit(1);
+      }
+      break;
+
+    case OPT_SOCK_PER_CONN:         /* --conn_sock or -n */
+      errno= 0;
+      ms_setting.sock_per_conn= (uint32_t)strtoul(optarg, (char **) NULL, 10);
+      if (ms_setting.sock_per_conn <= 0 || errno != 0)
+      {
+        fprintf(stderr, "Number of socks of each concurrency "
+                        "must be greater than 0.:-)\n");
+        exit(1);
+      }
+      break;
+
+    case OPT_RECONNECT:     /* --reconnect or -R */
+      ms_setting.reconnect= true;
+      break;
+
+    case OPT_VERBOSE:       /* --verbose or -b */
+      ms_setting.verbose= true;
+      break;
+
+    case OPT_FACEBOOK_TEST:         /* --facebook or -a */
+      ms_setting.facebook_test= true;
+      break;
+
+    case OPT_BINARY_PROTOCOL:       /* --binary or -B */
+      ms_setting.binary_prot_= true;
+      break;
+
+    case OPT_TPS:       /* --tps or -P */
+      ms_setting.expected_tps= (int)ms_parse_size();
+      if (ms_setting.expected_tps == -1)
+      {
+        fprintf(stderr,
+                "Please specify the item expected throughput. :-)\n"
+                "e.g.: --tps=10k (means 10k throughput).\n");
+        exit(1);
+      }
+      break;
+
+    case OPT_REP_WRITE_SRV:         /* --rep_write or -p */
+      errno= 0;
+      ms_setting.rep_write_srv= (uint32_t)strtoul(optarg, (char **) NULL, 10);
+      if (ms_setting.rep_write_srv <= 0 || errno != 0)
+      {
+        fprintf(stderr,
+                "Number of replication writing server must be greater "
+                "than 0.:-)\n");
+        exit(1);
+      }
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(1);
+
+    default:
+      abort();
+    } /* switch */
+  }
+} /* ms_options_parse */
+
+
+static int ms_check_para()
+{
+  if (ms_setting.srv_str == NULL)
+  {
+    char *temp;
+
+    if ((temp= getenv("MEMCACHED_SERVERS")))
+    {
+      ms_setting.srv_str= strdup(temp);
+    }
+    else
+    {
+      fprintf(stderr, "No Servers provided\n\n");
+      return -1;
+    }
+  }
+
+  if (ms_setting.nconns % (uint32_t)ms_setting.nthreads != 0)
+  {
+    fprintf(stderr, "Concurrency must be the multiples of threads count.\n");
+    return -1;
+  }
+
+  if (ms_setting.win_size % UNIT_ITEMS_COUNT != 0)
+  {
+    fprintf(stderr, "Window size must be the multiples of 1024.\n\n");
+    return -1;
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_check_para */
+
+
+/* initialize the statistic structure */
+static void ms_statistic_init()
+{
+  pthread_mutex_init(&ms_statistic.stat_mutex, NULL);
+  ms_init_stats(&ms_statistic.get_stat, "Get");
+  ms_init_stats(&ms_statistic.set_stat, "Set");
+  ms_init_stats(&ms_statistic.total_stat, "Total");
+} /* ms_statistic_init */
+
+
+/* initialize the global state structure */
+static void ms_stats_init()
+{
+  memset(&ms_stats, 0, sizeof(ms_stats_t));
+  if (ms_setting.stat_freq > 0)
+  {
+    ms_statistic_init();
+  }
+} /* ms_stats_init */
+
+
+/* use to output the statistic */
+static void ms_print_statistics(int in_time)
+{
+  int obj_size= (int)(ms_setting.avg_key_size + ms_setting.avg_val_size);
+
+  printf("\033[1;1H\033[2J\n");
+  ms_dump_format_stats(&ms_statistic.get_stat, in_time,
+                       ms_setting.stat_freq, obj_size);
+  ms_dump_format_stats(&ms_statistic.set_stat, in_time,
+                       ms_setting.stat_freq, obj_size);
+  ms_dump_format_stats(&ms_statistic.total_stat, in_time,
+                       ms_setting.stat_freq, obj_size);
+} /* ms_print_statistics */
+
+
+/* used to print the states of memslap */
+static void ms_print_memslap_stats(struct timeval *start_time,
+                                   struct timeval *end_time)
+{
+  char buf[1024];
+  char *pos= buf;
+
+  pos+= snprintf(pos,
+                 sizeof(buf), "cmd_get: %lu\n",
+                 (unsigned long) ms_stats.cmd_get);
+  pos+= snprintf(pos,
+                 sizeof(buf) - (size_t)(pos -buf),
+                 "cmd_set: %lu\n",
+                 (unsigned long) ms_stats.cmd_set);
+  pos+= snprintf(pos,
+                 sizeof(buf) - (size_t)(pos -buf),
+                 "get_misses: %lu\n",
+                 (unsigned long) ms_stats.get_misses);
+
+  if (ms_setting.verify_percent > 0)
+  {
+    pos+= snprintf(pos,
+                   sizeof(buf) - (size_t)(pos -buf),
+                   "verify_misses: %lu\n",
+                   (unsigned long) ms_stats.vef_miss);
+    pos+= snprintf(pos,
+                   sizeof(buf) - (size_t)(pos -buf),
+                   "verify_failed: %lu\n",
+                   (unsigned long) ms_stats.vef_failed);
+  }
+
+  if (ms_setting.exp_ver_per > 0)
+  {
+    pos+= snprintf(pos,
+                   sizeof(buf) - (size_t)(pos -buf),
+                   "expired_get: %lu\n",
+                   (unsigned long) ms_stats.exp_get);
+    pos+= snprintf(pos,
+                   sizeof(buf) - (size_t)(pos -buf),
+                   "unexpired_unget: %lu\n",
+                   (unsigned long) ms_stats.unexp_unget);
+  }
+
+  pos+= snprintf(pos,
+                 sizeof(buf) - (size_t)(pos -buf),
+                 "written_bytes: %lu\n",
+                 (unsigned long) ms_stats.bytes_written);
+  pos+= snprintf(pos,
+                 sizeof(buf) - (size_t)(pos -buf),
+                 "read_bytes: %lu\n",
+                 (unsigned long) ms_stats.bytes_read);
+  pos+= snprintf(pos,
+                 sizeof(buf) - (size_t)(pos -buf),
+                 "object_bytes: %lu\n",
+                 (unsigned long) ms_stats.obj_bytes);
+
+  if (ms_setting.udp || ms_setting.facebook_test)
+  {
+    pos+= snprintf(pos,
+                   sizeof(buf) - (size_t)(pos -buf),
+                   "packet_disorder: %lu\n",
+                   (unsigned long) ms_stats.pkt_disorder);
+    pos+= snprintf(pos,
+                   sizeof(buf) - (size_t)(pos -buf),
+                   "packet_drop: %lu\n",
+                   (unsigned long)ms_stats.pkt_drop);
+    pos+= snprintf(pos,
+                   sizeof(buf) - (size_t)(pos -buf),
+                   "udp_timeout: %lu\n",
+                   (unsigned long)ms_stats.udp_timeout);
+  }
+
+  if (ms_setting.stat_freq > 0)
+  {
+    ms_dump_stats(&ms_statistic.get_stat);
+    ms_dump_stats(&ms_statistic.set_stat);
+    ms_dump_stats(&ms_statistic.total_stat);
+  }
+
+  int64_t time_diff= ms_time_diff(start_time, end_time);
+  pos+= snprintf(pos,
+                 sizeof(buf) - (size_t)(pos -buf),
+                 "\nRun time: %.1fs Ops: %llu TPS: %.0Lf Net_rate: %.1fM/s\n",
+                 (double)time_diff / 1000000,
+                 (unsigned long long)(ms_stats.cmd_get + ms_stats.cmd_set),
+                 (ms_stats.cmd_get
+                  + ms_stats.cmd_set) / ((long double)time_diff / 1000000),
+                 (double)(
+                          ms_stats.bytes_written
+                          + ms_stats.bytes_read) / 1024 / 1024
+                 / ((double)time_diff / 1000000));
+  assert(pos <= buf);
+
+  fprintf(stdout, "%s", buf);
+  fflush(stdout);
+} /* ms_print_memslap_stats */
+
+
+/* the loop of the main thread, wait the work threads to complete */
+static void ms_monitor_slap_mode()
+{
+  struct timeval start_time, end_time;
+
+  /* Wait all the threads complete initialization. */
+  pthread_mutex_lock(&ms_global.init_lock.lock);
+  while (ms_global.init_lock.count < ms_setting.nthreads)
+  {
+    pthread_cond_wait(&ms_global.init_lock.cond,
+                      &ms_global.init_lock.lock);
+  }
+  pthread_mutex_unlock(&ms_global.init_lock.lock);
+
+  /* only when there is no set operation it need warm up */
+  if (ms_setting.cmd_distr[CMD_SET].cmd_prop < PROP_ERROR)
+  {
+    /* Wait all the connects complete warm up. */
+    pthread_mutex_lock(&ms_global.warmup_lock.lock);
+    while (ms_global.warmup_lock.count < ms_setting.nconns)
+    {
+      pthread_cond_wait(&ms_global.warmup_lock.cond, &ms_global.warmup_lock.lock);
+    }
+    pthread_mutex_unlock(&ms_global.warmup_lock.lock);
+  }
+  ms_global.finish_warmup= true;
+
+  /* running in "run time" mode, user specify run time */
+  if (ms_setting.run_time > 0)
+  {
+    int second= 0;
+    gettimeofday(&start_time, NULL);
+    while (1)
+    {
+      sleep(1);
+      second++;
+
+      if ((ms_setting.stat_freq > 0) && (second % ms_setting.stat_freq == 0)
+          && (ms_stats.active_conns >= ms_setting.nconns)
+          && (ms_stats.active_conns <= INT_MAX))
+      {
+        ms_print_statistics(second);
+      }
+
+      if (ms_setting.run_time <= second)
+      {
+        ms_global.time_out= true;
+        break;
+      }
+
+      /* all connections disconnect */
+      if ((second > 5) && (ms_stats.active_conns == 0))
+      {
+        break;
+      }
+    }
+    gettimeofday(&end_time, NULL);
+    sleep(1);       /* wait all threads clean up */
+  }
+  else
+  {
+    /* running in "execute number" mode, user specify execute number */
+    gettimeofday(&start_time, NULL);
+
+    /*
+     * We loop until we know that all connects have cleaned up.
+     */
+    pthread_mutex_lock(&ms_global.run_lock.lock);
+    while (ms_global.run_lock.count < ms_setting.nconns)
+    {
+      pthread_cond_wait(&ms_global.run_lock.cond, &ms_global.run_lock.lock);
+    }
+    pthread_mutex_unlock(&ms_global.run_lock.lock);
+
+    gettimeofday(&end_time, NULL);
+  }
+
+  ms_print_memslap_stats(&start_time, &end_time);
+} /* ms_monitor_slap_mode */
+
+
+/* the main function */
+int main(int argc, char *argv[])
+{
+  srandom((unsigned int)time(NULL));
+  ms_global_struct_init();
+
+  /* initialization */
+  ms_setting_init_pre();
+  ms_options_parse(argc, argv);
+  if (ms_check_para())
+  {
+    ms_help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION);
+    exit(1);
+  }
+  ms_setting_init_post();
+  ms_stats_init();
+  ms_thread_init();
+
+  /* waiting work thread complete its task */
+  ms_monitor_slap_mode();
+
+  /* clean up */
+  ms_thread_cleanup();
+  ms_global_struct_destroy();
+  ms_setting_cleanup();
+
+  return EXIT_SUCCESS;
+} /* main */
diff --git a/src/bin/memcapable.cc b/src/bin/memcapable.cc
new file mode 100644 (file)
index 0000000..81e619f
--- /dev/null
@@ -0,0 +1,2253 @@
+/* LibMemcached
+ * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+#undef NDEBUG
+
+#include <mem_config.h>
+
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#else
+#include "poll/poll.h"
+#endif
+
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctype.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <libmemcached-1.0/memcached.h>
+
+#include "libmemcached/socket.hpp"
+#include "libmemcachedprotocol-0.0/binary.h"
+#include "libmemcached/byteorder.h"
+#include "utilities.h"
+
+#include <vector>
+
+#ifdef linux
+/* /usr/include/netinet/in.h defines macros from ntohs() to _bswap_nn to
+ * optimize the conversion functions, but the prototypes generate warnings
+ * from gcc. The conversion methods isn't the bottleneck for my app, so
+ * just remove the warnings by undef'ing the optimization ..
+ */
+#undef ntohs
+#undef ntohl
+#endif
+
+/* Should we generate coredumps when we enounter an error (-c) */
+static bool do_core= false;
+/* connection to the server */
+static memcached_socket_t sock;
+/* Should the output from test failures be verbose or quiet? */
+static bool verbose= false;
+
+/* The number of seconds to wait for an IO-operation */
+static int timeout= 2;
+
+/*
+ * Instead of having to cast between the different datatypes we create
+ * a union of all of the different types of pacages we want to send.
+ * A lot of the different commands use the same packet layout, so I'll
+ * just define the different types I need. The typedefs only contain
+ * the header of the message, so we need some space for keys and body
+ * To avoid to have to do multiple writes, lets add a chunk of memory
+ * to use. 1k should be more than enough for header, key and body.
+ */
+typedef union
+{
+  protocol_binary_request_no_extras plain;
+  protocol_binary_request_flush flush;
+  protocol_binary_request_incr incr;
+  protocol_binary_request_set set;
+  char bytes[1024];
+} command;
+
+typedef union
+{
+  protocol_binary_response_no_extras plain;
+  protocol_binary_response_incr incr;
+  protocol_binary_response_decr decr;
+  char bytes[1024];
+} response;
+
+enum test_return
+{
+  TEST_SKIP, TEST_PASS, TEST_PASS_RECONNECT, TEST_FAIL
+};
+
+/**
+ * Try to get an addrinfo struct for a given port on a given host
+ */
+static struct addrinfo *lookuphost(const char *hostname, const char *port)
+{
+  struct addrinfo *ai= 0;
+  struct addrinfo hints;
+  memset(&hints, 0, sizeof(struct addrinfo));
+  hints.ai_family=AF_UNSPEC;
+  hints.ai_protocol=IPPROTO_TCP;
+  hints.ai_socktype=SOCK_STREAM;
+
+  int error= getaddrinfo(hostname, port, &hints, &ai);
+  if (error != 0)
+  {
+    if (error != EAI_SYSTEM)
+    {
+      fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(error));
+    }
+    else
+    {
+      perror("getaddrinfo()");
+    }
+  }
+
+  return ai;
+}
+
+/**
+ * Set the socket in nonblocking mode
+ * @return -1 if failure, the socket otherwise
+ */
+static memcached_socket_t set_noblock(void)
+{
+#if defined(_WIN32)
+  u_long arg = 1;
+  if (ioctlsocket(sock, FIONBIO, &arg) == SOCKET_ERROR)
+  {
+    perror("Failed to set nonblocking io");
+    closesocket(sock);
+    return INVALID_SOCKET;
+  }
+#else
+  int flags= fcntl(sock, F_GETFL, 0);
+  if (flags == -1)
+  {
+    perror("Failed to get socket flags");
+    memcached_close_socket(sock);
+    return INVALID_SOCKET;
+  }
+
+  if ((flags & O_NONBLOCK) != O_NONBLOCK)
+  {
+    if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)
+    {
+      perror("Failed to set socket to nonblocking mode");
+      memcached_close_socket(sock);
+      return INVALID_SOCKET;
+    }
+  }
+#endif
+  return sock;
+}
+
+/**
+ * Try to open a connection to the server
+ * @param hostname the name of the server to connect to
+ * @param port the port number (or service) to connect to
+ * @return positive integer if success, -1 otherwise
+ */
+static memcached_socket_t connect_server(const char *hostname, const char *port)
+{
+  struct addrinfo *ai= lookuphost(hostname, port);
+  sock= INVALID_SOCKET;
+  if (ai != NULL)
+  {
+    if ((sock= socket(ai->ai_family, ai->ai_socktype,
+                      ai->ai_protocol)) != INVALID_SOCKET)
+    {
+      if (connect(sock, ai->ai_addr, ai->ai_addrlen) == SOCKET_ERROR)
+      {
+        fprintf(stderr, "Failed to connect socket: %s\n",
+                strerror(get_socket_errno()));
+        closesocket(sock);
+        sock= INVALID_SOCKET;
+      }
+      else
+      {
+        sock= set_noblock();
+      }
+    }
+    else
+    {
+      fprintf(stderr, "Failed to create socket: %s\n", strerror(get_socket_errno()));
+    }
+
+    freeaddrinfo(ai);
+  }
+
+  return sock;
+}
+
+static ssize_t timeout_io_op(memcached_socket_t fd, short direction, void *buf, size_t len)
+{
+  ssize_t ret;
+
+  if (direction == POLLOUT)
+  {
+    ret= send(fd, buf, len, 0);
+  }
+  else
+  {
+    ret= recv(fd, buf, len, 0);
+  }
+
+  if (ret == SOCKET_ERROR && get_socket_errno() == EWOULDBLOCK) 
+  {
+    struct pollfd fds;
+    memset(&fds, 0, sizeof(struct pollfd));
+    fds.events= direction;
+    fds.fd= fd;
+
+    int err= poll(&fds, 1, timeout * 1000);
+    if (err == 1)
+    {
+      if (direction == POLLOUT)
+      {
+        ret= send(fd, buf, len, 0);
+      }
+      else
+      {
+        ret= recv(fd, buf, len, 0);
+      }
+    }
+    else if (err == 0)
+    {
+      errno= ETIMEDOUT;
+    }
+    else
+    {
+      perror("Failed to poll");
+      return -1;
+    }
+  }
+
+  return ret;
+}
+
+/**
+ * Ensure that an expression is true. If it isn't print out a message similar
+ * to assert() and create a coredump if the user wants that. If not an error
+ * message is returned.
+ *
+ */
+static enum test_return ensure(bool val, const char *expression, const char *file, int line)
+{
+  if (!val)
+  {
+    if (verbose)
+    {
+      fprintf(stdout, "\n%s:%d: %s", file, line, expression);
+    }
+
+    if (do_core)
+    {
+      abort();
+    }
+
+    return TEST_FAIL;
+  }
+
+  return TEST_PASS;
+}
+
+#define verify(expression) do { if (ensure(expression, #expression, __FILE__, __LINE__) == TEST_FAIL) return TEST_FAIL; } while (0)
+#define execute(expression) do { if (ensure(expression == TEST_PASS, #expression, __FILE__, __LINE__) == TEST_FAIL) return TEST_FAIL; } while (0)
+
+/**
+ * Send a chunk of memory over the socket (retry if the call is iterrupted
+ */
+static enum test_return retry_write(const void* buf, size_t len)
+{
+  size_t offset= 0;
+  const char* ptr= static_cast<const char *>(buf);
+
+  do
+  {
+    size_t num_bytes= len - offset;
+    ssize_t nw= timeout_io_op(sock, POLLOUT, (void*)(ptr + offset), num_bytes);
+    if (nw == -1)
+    {
+      verify(get_socket_errno() == EINTR || get_socket_errno() == EAGAIN);
+    }
+    else
+    {
+      offset+= (size_t)nw;
+    }
+
+  } while (offset < len);
+
+  return TEST_PASS;
+}
+
+/**
+ * Resend a packet to the server (All fields in the command header should
+ * be in network byte order)
+ */
+static enum test_return resend_packet(command *cmd)
+{
+  size_t length= sizeof (protocol_binary_request_no_extras) +
+    ntohl(cmd->plain.message.header.request.bodylen);
+
+  execute(retry_write(cmd, length));
+  return TEST_PASS;
+}
+
+/**
+ * Send a command to the server. The command header needs to be updated
+ * to network byte order
+ */
+static enum test_return send_packet(command *cmd)
+{
+  /* Fix the byteorder of the header */
+  cmd->plain.message.header.request.keylen=
+          ntohs(cmd->plain.message.header.request.keylen);
+  cmd->plain.message.header.request.bodylen=
+          ntohl(cmd->plain.message.header.request.bodylen);
+  cmd->plain.message.header.request.cas=
+          memcached_ntohll(cmd->plain.message.header.request.cas);
+
+  execute(resend_packet(cmd));
+  return TEST_PASS;
+}
+
+/**
+ * Read a fixed length chunk of data from the server
+ */
+static enum test_return retry_read(void *buf, size_t len)
+{
+  size_t offset= 0;
+  do
+  {
+    ssize_t nr= timeout_io_op(sock, POLLIN, ((char*) buf) + offset, len - offset);
+    switch (nr) {
+    case -1 :
+      fprintf(stderr, "Errno: %d %s\n", get_socket_errno(), strerror(errno));
+      verify(get_socket_errno() == EINTR || get_socket_errno() == EAGAIN);
+      break;
+
+    case 0:
+      return TEST_FAIL;
+
+    default:
+      offset+= (size_t)nr;
+    }
+  } while (offset < len);
+
+  return TEST_PASS;
+}
+
+/**
+ * Receive a response from the server and conver the fields in the header
+ * to local byte order
+ */
+static enum test_return recv_packet(response *rsp)
+{
+  execute(retry_read(rsp, sizeof(protocol_binary_response_no_extras)));
+
+  /* Fix the byte order in the packet header */
+  rsp->plain.message.header.response.keylen=
+          ntohs(rsp->plain.message.header.response.keylen);
+  rsp->plain.message.header.response.status=
+          ntohs(rsp->plain.message.header.response.status);
+  rsp->plain.message.header.response.bodylen=
+          ntohl(rsp->plain.message.header.response.bodylen);
+  rsp->plain.message.header.response.cas=
+          memcached_ntohll(rsp->plain.message.header.response.cas);
+
+  size_t bodysz= rsp->plain.message.header.response.bodylen;
+  if (bodysz > 0)
+    execute(retry_read(rsp->bytes + sizeof (protocol_binary_response_no_extras), bodysz));
+
+  return TEST_PASS;
+}
+
+/**
+ * Create a storage command (add, set, replace etc)
+ *
+ * @param cmd destination buffer
+ * @param cc the storage command to create
+ * @param key the key to store
+ * @param keylen the length of the key
+ * @param dta the data to store with the key
+ * @param dtalen the length of the data to store with the key
+ * @param flags the flags to store along with the key
+ * @param exptime the expiry time for the key
+ */
+static void storage_command(command *cmd,
+                            uint8_t cc,
+                            const void* key,
+                            size_t keylen,
+                            const void* dta,
+                            size_t dtalen,
+                            uint32_t flags,
+                            uint32_t exptime)
+{
+  /* all of the storage commands use the same command layout */
+  protocol_binary_request_set *request= &cmd->set;
+
+  memset(request, 0, sizeof (*request));
+  request->message.header.request.magic= PROTOCOL_BINARY_REQ;
+  request->message.header.request.opcode= cc;
+  request->message.header.request.keylen= (uint16_t)keylen;
+  request->message.header.request.extlen= 8;
+  request->message.header.request.bodylen= (uint32_t)(keylen + 8 + dtalen);
+  request->message.header.request.opaque= 0xdeadbeef;
+  request->message.body.flags= flags;
+  request->message.body.expiration= exptime;
+
+  off_t key_offset= sizeof (protocol_binary_request_no_extras) + 8;
+  memcpy(cmd->bytes + key_offset, key, keylen);
+  if (dta != NULL)
+    memcpy(cmd->bytes + key_offset + keylen, dta, dtalen);
+}
+
+/**
+ * Create a basic command to send to the server
+ * @param cmd destination buffer
+ * @param cc the command to create
+ * @param key the key to store
+ * @param keylen the length of the key
+ * @param dta the data to store with the key
+ * @param dtalen the length of the data to store with the key
+ */
+static void raw_command(command *cmd,
+                        uint8_t cc,
+                        const void* key,
+                        size_t keylen,
+                        const void* dta,
+                        size_t dtalen)
+{
+  /* all of the storage commands use the same command layout */
+  memset(cmd, 0, sizeof (*cmd));
+  cmd->plain.message.header.request.magic= PROTOCOL_BINARY_REQ;
+  cmd->plain.message.header.request.opcode= cc;
+  cmd->plain.message.header.request.keylen= (uint16_t)keylen;
+  cmd->plain.message.header.request.bodylen= (uint32_t)(keylen + dtalen);
+  cmd->plain.message.header.request.opaque= 0xdeadbeef;
+
+  off_t key_offset= sizeof (protocol_binary_request_no_extras);
+
+  if (key != NULL)
+    memcpy(cmd->bytes + key_offset, key, keylen);
+
+  if (dta != NULL)
+    memcpy(cmd->bytes + key_offset + keylen, dta, dtalen);
+}
+
+/**
+ * Create the flush command
+ * @param cmd destination buffer
+ * @param cc the command to create (FLUSH/FLUSHQ)
+ * @param exptime when to flush
+ * @param use_extra to force using of the extra field?
+ */
+static void flush_command(command *cmd,
+                          uint8_t cc, uint32_t exptime, bool use_extra)
+{
+  memset(cmd, 0, sizeof (cmd->flush));
+  cmd->flush.message.header.request.magic= PROTOCOL_BINARY_REQ;
+  cmd->flush.message.header.request.opcode= cc;
+  cmd->flush.message.header.request.opaque= 0xdeadbeef;
+
+  if (exptime != 0 || use_extra)
+  {
+    cmd->flush.message.header.request.extlen= 4;
+    cmd->flush.message.body.expiration= htonl(exptime);
+    cmd->flush.message.header.request.bodylen= 4;
+  }
+}
+
+/**
+ * Create a incr/decr command
+ * @param cc the cmd to create (FLUSH/FLUSHQ)
+ * @param key the key to operate on
+ * @param keylen the number of bytes in the key
+ * @param delta the number to add/subtract
+ * @param initial the initial value if the key doesn't exist
+ * @param exptime when the key should expire if it isn't set
+ */
+static void arithmetic_command(command *cmd,
+                               uint8_t cc,
+                               const void* key,
+                               size_t keylen,
+                               uint64_t delta,
+                               uint64_t initial,
+                               uint32_t exptime)
+{
+  memset(cmd, 0, sizeof (cmd->incr));
+  cmd->incr.message.header.request.magic= PROTOCOL_BINARY_REQ;
+  cmd->incr.message.header.request.opcode= cc;
+  cmd->incr.message.header.request.keylen= (uint16_t)keylen;
+  cmd->incr.message.header.request.extlen= 20;
+  cmd->incr.message.header.request.bodylen= (uint32_t)(keylen + 20);
+  cmd->incr.message.header.request.opaque= 0xdeadbeef;
+  cmd->incr.message.body.delta= memcached_htonll(delta);
+  cmd->incr.message.body.initial= memcached_htonll(initial);
+  cmd->incr.message.body.expiration= htonl(exptime);
+
+  off_t key_offset= sizeof (protocol_binary_request_no_extras) + 20;
+  memcpy(cmd->bytes + key_offset, key, keylen);
+}
+
+/**
+ * Validate the response header from the server
+ * @param rsp the response to check
+ * @param cc the expected command
+ * @param status the expected status
+ */
+static enum test_return do_validate_response_header(response *rsp,
+                                                    uint8_t cc, uint16_t status)
+{
+  verify(rsp->plain.message.header.response.magic == PROTOCOL_BINARY_RES);
+  verify(rsp->plain.message.header.response.opcode == cc);
+  verify(rsp->plain.message.header.response.datatype == PROTOCOL_BINARY_RAW_BYTES);
+  verify(rsp->plain.message.header.response.status == status);
+  verify(rsp->plain.message.header.response.opaque == 0xdeadbeef);
+
+  if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS)
+  {
+    switch (cc) {
+    case PROTOCOL_BINARY_CMD_ADDQ:
+    case PROTOCOL_BINARY_CMD_APPENDQ:
+    case PROTOCOL_BINARY_CMD_DECREMENTQ:
+    case PROTOCOL_BINARY_CMD_DELETEQ:
+    case PROTOCOL_BINARY_CMD_FLUSHQ:
+    case PROTOCOL_BINARY_CMD_INCREMENTQ:
+    case PROTOCOL_BINARY_CMD_PREPENDQ:
+    case PROTOCOL_BINARY_CMD_QUITQ:
+    case PROTOCOL_BINARY_CMD_REPLACEQ:
+    case PROTOCOL_BINARY_CMD_SETQ:
+      verify("Quiet command shouldn't return on success" == NULL);
+      /* fall through */
+    default:
+      break;
+    }
+
+    switch (cc) {
+    case PROTOCOL_BINARY_CMD_ADD:
+    case PROTOCOL_BINARY_CMD_REPLACE:
+    case PROTOCOL_BINARY_CMD_SET:
+    case PROTOCOL_BINARY_CMD_APPEND:
+    case PROTOCOL_BINARY_CMD_PREPEND:
+      verify(rsp->plain.message.header.response.keylen == 0);
+      verify(rsp->plain.message.header.response.extlen == 0);
+      verify(rsp->plain.message.header.response.bodylen == 0);
+      verify(rsp->plain.message.header.response.cas != 0);
+      break;
+    case PROTOCOL_BINARY_CMD_FLUSH:
+    case PROTOCOL_BINARY_CMD_NOOP:
+    case PROTOCOL_BINARY_CMD_QUIT:
+    case PROTOCOL_BINARY_CMD_DELETE:
+      verify(rsp->plain.message.header.response.keylen == 0);
+      verify(rsp->plain.message.header.response.extlen == 0);
+      verify(rsp->plain.message.header.response.bodylen == 0);
+      verify(rsp->plain.message.header.response.cas == 0);
+      break;
+
+    case PROTOCOL_BINARY_CMD_DECREMENT:
+    case PROTOCOL_BINARY_CMD_INCREMENT:
+      verify(rsp->plain.message.header.response.keylen == 0);
+      verify(rsp->plain.message.header.response.extlen == 0);
+      verify(rsp->plain.message.header.response.bodylen == 8);
+      verify(rsp->plain.message.header.response.cas != 0);
+      break;
+
+    case PROTOCOL_BINARY_CMD_STAT:
+      verify(rsp->plain.message.header.response.extlen == 0);
+      /* key and value exists in all packets except in the terminating */
+      verify(rsp->plain.message.header.response.cas == 0);
+      break;
+
+    case PROTOCOL_BINARY_CMD_VERSION:
+      verify(rsp->plain.message.header.response.keylen == 0);
+      verify(rsp->plain.message.header.response.extlen == 0);
+      verify(rsp->plain.message.header.response.bodylen != 0);
+      verify(rsp->plain.message.header.response.cas == 0);
+      break;
+
+    case PROTOCOL_BINARY_CMD_GET:
+    case PROTOCOL_BINARY_CMD_GETQ:
+      verify(rsp->plain.message.header.response.keylen == 0);
+      verify(rsp->plain.message.header.response.extlen == 4);
+      verify(rsp->plain.message.header.response.cas != 0);
+      break;
+
+    case PROTOCOL_BINARY_CMD_GETK:
+    case PROTOCOL_BINARY_CMD_GETKQ:
+      verify(rsp->plain.message.header.response.keylen != 0);
+      verify(rsp->plain.message.header.response.extlen == 4);
+      verify(rsp->plain.message.header.response.cas != 0);
+      break;
+
+    default:
+      /* Undefined command code */
+      break;
+    }
+  }
+  else
+  {
+    verify(rsp->plain.message.header.response.cas == 0);
+    verify(rsp->plain.message.header.response.extlen == 0);
+    if (cc != PROTOCOL_BINARY_CMD_GETK)
+    {
+      verify(rsp->plain.message.header.response.keylen == 0);
+    }
+  }
+
+  return TEST_PASS;
+}
+
+/* We call verify(validate_response_header), but that macro
+ * expects a boolean expression, and the function returns
+ * an enum.... Let's just create a macro to avoid cluttering
+ * the code with all of the == TEST_PASS ;-)
+ */
+#define validate_response_header(a,b,c) \
+        do_validate_response_header(a,b,c) == TEST_PASS
+
+
+static enum test_return send_binary_noop(void)
+{
+  command cmd;
+  raw_command(&cmd, PROTOCOL_BINARY_CMD_NOOP, NULL, 0, NULL, 0);
+  execute(send_packet(&cmd));
+  return TEST_PASS;
+}
+
+static enum test_return receive_binary_noop(void)
+{
+  response rsp;
+  execute(recv_packet(&rsp));
+  verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_NOOP,
+                                  PROTOCOL_BINARY_RESPONSE_SUCCESS));
+  return TEST_PASS;
+}
+
+static enum test_return test_binary_noop(void)
+{
+  execute(send_binary_noop());
+  execute(receive_binary_noop());
+  return TEST_PASS;
+}
+
+static enum test_return test_binary_quit_impl(uint8_t cc)
+{
+  command cmd;
+  response rsp;
+  raw_command(&cmd, cc, NULL, 0, NULL, 0);
+
+  execute(send_packet(&cmd));
+  if (cc == PROTOCOL_BINARY_CMD_QUIT)
+  {
+    execute(recv_packet(&rsp));
+    verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_QUIT,
+                                    PROTOCOL_BINARY_RESPONSE_SUCCESS));
+  }
+
+  /* Socket should be closed now, read should return EXIT_SUCCESS */
+  verify(timeout_io_op(sock, POLLIN, rsp.bytes, sizeof(rsp.bytes)) == 0);
+
+  return TEST_PASS_RECONNECT;
+}
+
+static enum test_return test_binary_quit(void)
+{
+  return test_binary_quit_impl(PROTOCOL_BINARY_CMD_QUIT);
+}
+
+static enum test_return test_binary_quitq(void)
+{
+  return test_binary_quit_impl(PROTOCOL_BINARY_CMD_QUITQ);
+}
+
+static enum test_return test_binary_set_impl(const char* key, uint8_t cc)
+{
+  command cmd;
+  response rsp;
+
+  uint64_t value= 0xdeadbeefdeadcafeULL;
+  storage_command(&cmd, cc, key, strlen(key), &value, sizeof (value), 0, 0);
+
+  /* set should always work */
+  for (int ii= 0; ii < 10; ii++)
+  {
+    if (ii == 0)
+    {
+      execute(send_packet(&cmd));
+    }
+    else
+    {
+      execute(resend_packet(&cmd));
+    }
+
+    if (cc == PROTOCOL_BINARY_CMD_SET)
+    {
+      execute(recv_packet(&rsp));
+      verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
+    }
+    else
+      execute(test_binary_noop());
+  }
+
+  /*
+   * We need to get the current CAS id, and at this time we haven't
+   * verified that we have a working get
+   */
+  if (cc == PROTOCOL_BINARY_CMD_SETQ)
+  {
+    cmd.set.message.header.request.opcode= PROTOCOL_BINARY_CMD_SET;
+    execute(resend_packet(&cmd));
+    execute(recv_packet(&rsp));
+    verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_SET,
+                                    PROTOCOL_BINARY_RESPONSE_SUCCESS));
+    cmd.set.message.header.request.opcode= PROTOCOL_BINARY_CMD_SETQ;
+  }
+
+  /* try to set with the correct CAS value */
+  cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas);
+  execute(resend_packet(&cmd));
+  if (cc == PROTOCOL_BINARY_CMD_SET)
+  {
+    execute(recv_packet(&rsp));
+    verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
+  }
+  else
+    execute(test_binary_noop());
+
+  /* try to set with an incorrect CAS value */
+  cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas - 1);
+  execute(resend_packet(&cmd));
+  execute(send_binary_noop());
+  execute(recv_packet(&rsp));
+  verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS));
+  execute(receive_binary_noop());
+
+  return TEST_PASS;
+}
+
+static enum test_return test_binary_set(void)
+{
+  return test_binary_set_impl("test_binary_set", PROTOCOL_BINARY_CMD_SET);
+}
+
+static enum test_return test_binary_setq(void)
+{
+  return test_binary_set_impl("test_binary_setq", PROTOCOL_BINARY_CMD_SETQ);
+}
+
+static enum test_return test_binary_add_impl(const char* key, uint8_t cc)
+{
+  command cmd;
+  response rsp;
+  uint64_t value= 0xdeadbeefdeadcafeULL;
+  storage_command(&cmd, cc, key, strlen(key), &value, sizeof (value), 0, 0);
+
+  /* first add should work, rest of them should fail (even with cas
+     as wildcard */
+  for (int ii=0; ii < 10; ii++)
+  {
+    if (ii == 0)
+      execute(send_packet(&cmd));
+    else
+      execute(resend_packet(&cmd));
+
+    if (cc == PROTOCOL_BINARY_CMD_ADD || ii > 0)
+    {
+      uint16_t expected_result;
+      if (ii == 0)
+        expected_result= PROTOCOL_BINARY_RESPONSE_SUCCESS;
+      else
+        expected_result= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS;
+
+      execute(send_binary_noop());
+      execute(recv_packet(&rsp));
+      execute(receive_binary_noop());
+      verify(validate_response_header(&rsp, cc, expected_result));
+    }
+    else
+      execute(test_binary_noop());
+  }
+
+  return TEST_PASS;
+}
+
+static enum test_return test_binary_add(void)
+{
+  return test_binary_add_impl("test_binary_add", PROTOCOL_BINARY_CMD_ADD);
+}
+
+static enum test_return test_binary_addq(void)
+{
+  return test_binary_add_impl("test_binary_addq", PROTOCOL_BINARY_CMD_ADDQ);
+}
+
+static enum test_return binary_set_item(const char *key, const char *value)
+{
+  command cmd;
+  response rsp;
+  storage_command(&cmd, PROTOCOL_BINARY_CMD_SET, key, strlen(key),
+                  value, strlen(value), 0, 0);
+  execute(send_packet(&cmd));
+  execute(recv_packet(&rsp));
+  verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_SET,
+                                  PROTOCOL_BINARY_RESPONSE_SUCCESS));
+  return TEST_PASS;
+}
+
+static enum test_return test_binary_replace_impl(const char* key, uint8_t cc)
+{
+  command cmd;
+  response rsp;
+  uint64_t value= 0xdeadbeefdeadcafeULL;
+  storage_command(&cmd, cc, key, strlen(key), &value, sizeof (value), 0, 0);
+
+  /* first replace should fail, successive should succeed (when the
+     item is added! */
+  for (int ii= 0; ii < 10; ii++)
+  {
+    if (ii == 0)
+    {
+      execute(send_packet(&cmd));
+    }
+    else
+    {
+      execute(resend_packet(&cmd));
+    }
+
+    if (cc == PROTOCOL_BINARY_CMD_REPLACE || ii == 0)
+    {
+      uint16_t expected_result;
+      if (ii == 0)
+      {
+        expected_result=PROTOCOL_BINARY_RESPONSE_KEY_ENOENT;
+      }
+      else
+      {
+        expected_result=PROTOCOL_BINARY_RESPONSE_SUCCESS;
+      }
+
+      execute(send_binary_noop());
+      execute(recv_packet(&rsp));
+      execute(receive_binary_noop());
+      verify(validate_response_header(&rsp, cc, expected_result));
+
+      if (ii == 0)
+        execute(binary_set_item(key, key));
+    }
+    else
+    {
+      execute(test_binary_noop());
+    }
+  }
+
+  /* verify that replace with CAS value works! */
+  cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas);
+  execute(resend_packet(&cmd));
+
+  if (cc == PROTOCOL_BINARY_CMD_REPLACE)
+  {
+    execute(recv_packet(&rsp));
+    verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
+  }
+  else
+    execute(test_binary_noop());
+
+  /* try to set with an incorrect CAS value */
+  cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas - 1);
+  execute(resend_packet(&cmd));
+  execute(send_binary_noop());
+  execute(recv_packet(&rsp));
+  execute(receive_binary_noop());
+  verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS));
+
+  return TEST_PASS;
+}
+
+static enum test_return test_binary_replace(void)
+{
+  return test_binary_replace_impl("test_binary_replace", PROTOCOL_BINARY_CMD_REPLACE);
+}
+
+static enum test_return test_binary_replaceq(void)
+{
+  return test_binary_replace_impl("test_binary_replaceq", PROTOCOL_BINARY_CMD_REPLACEQ);
+}
+
+static enum test_return test_binary_delete_impl(const char *key, uint8_t cc)
+{
+  command cmd;
+  response rsp;
+  raw_command(&cmd, cc, key, strlen(key), NULL, 0);
+
+  /* The delete shouldn't work the first time, because the item isn't there */
+  execute(send_packet(&cmd));
+  execute(send_binary_noop());
+  execute(recv_packet(&rsp));
+  verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT));
+  execute(receive_binary_noop());
+  execute(binary_set_item(key, key));
+
+  /* The item should be present now, resend*/
+  execute(resend_packet(&cmd));
+  if (cc == PROTOCOL_BINARY_CMD_DELETE)
+  {
+    execute(recv_packet(&rsp));
+    verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
+  }
+
+  execute(test_binary_noop());
+
+  return TEST_PASS;
+}
+
+static enum test_return test_binary_delete(void)
+{
+  return test_binary_delete_impl("test_binary_delete", PROTOCOL_BINARY_CMD_DELETE);
+}
+
+static enum test_return test_binary_deleteq(void)
+{
+  return test_binary_delete_impl("test_binary_deleteq", PROTOCOL_BINARY_CMD_DELETEQ);
+}
+
+static enum test_return test_binary_get_impl(const char *key, uint8_t cc)
+{
+  command cmd;
+  response rsp;
+
+  raw_command(&cmd, cc, key, strlen(key), NULL, 0);
+  execute(send_packet(&cmd));
+  execute(send_binary_noop());
+
+  if (cc == PROTOCOL_BINARY_CMD_GET || cc == PROTOCOL_BINARY_CMD_GETK)
+  {
+    execute(recv_packet(&rsp));
+    verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT));
+  }
+
+  execute(receive_binary_noop());
+
+  execute(binary_set_item(key, key));
+  execute(resend_packet(&cmd));
+  execute(send_binary_noop());
+
+  execute(recv_packet(&rsp));
+  verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
+  execute(receive_binary_noop());
+
+  return TEST_PASS;
+}
+
+static enum test_return test_binary_get(void)
+{
+  return test_binary_get_impl("test_binary_get", PROTOCOL_BINARY_CMD_GET);
+}
+
+static enum test_return test_binary_getk(void)
+{
+  return test_binary_get_impl("test_binary_getk", PROTOCOL_BINARY_CMD_GETK);
+}
+
+static enum test_return test_binary_getq(void)
+{
+  return test_binary_get_impl("test_binary_getq", PROTOCOL_BINARY_CMD_GETQ);
+}
+
+static enum test_return test_binary_getkq(void)
+{
+  return test_binary_get_impl("test_binary_getkq", PROTOCOL_BINARY_CMD_GETKQ);
+}
+
+static enum test_return test_binary_incr_impl(const char* key, uint8_t cc)
+{
+  command cmd;
+  response rsp;
+  arithmetic_command(&cmd, cc, key, strlen(key), 1, 0, 0);
+
+  uint64_t ii;
+  for (ii= 0; ii < 10; ++ii)
+  {
+    if (ii == 0)
+      execute(send_packet(&cmd));
+    else
+      execute(resend_packet(&cmd));
+
+    if (cc == PROTOCOL_BINARY_CMD_INCREMENT)
+    {
+      execute(recv_packet(&rsp));
+      verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
+      verify(memcached_ntohll(rsp.incr.message.body.value) == ii);
+    }
+    else
+      execute(test_binary_noop());
+  }
+
+  /* @todo add incorrect CAS */
+  return TEST_PASS;
+}
+
+static enum test_return test_binary_incr(void)
+{
+  return test_binary_incr_impl("test_binary_incr", PROTOCOL_BINARY_CMD_INCREMENT);
+}
+
+static enum test_return test_binary_incrq(void)
+{
+  return test_binary_incr_impl("test_binary_incrq", PROTOCOL_BINARY_CMD_INCREMENTQ);
+}
+
+static enum test_return test_binary_decr_impl(const char* key, uint8_t cc)
+{
+  command cmd;
+  response rsp;
+  arithmetic_command(&cmd, cc, key, strlen(key), 1, 9, 0);
+
+  int ii;
+  for (ii= 9; ii > -1; --ii)
+  {
+    if (ii == 9)
+      execute(send_packet(&cmd));
+    else
+      execute(resend_packet(&cmd));
+
+    if (cc == PROTOCOL_BINARY_CMD_DECREMENT)
+    {
+      execute(recv_packet(&rsp));
+      verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
+      verify(memcached_ntohll(rsp.decr.message.body.value) == (uint64_t)ii);
+    }
+    else
+      execute(test_binary_noop());
+  }
+
+  /* decr 0 should not wrap */
+  execute(resend_packet(&cmd));
+  if (cc == PROTOCOL_BINARY_CMD_DECREMENT)
+  {
+    execute(recv_packet(&rsp));
+    verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
+    verify(memcached_ntohll(rsp.decr.message.body.value) == 0);
+  }
+  else
+  {
+    /* @todo get the value and verify! */
+
+  }
+
+  /* @todo add incorrect cas */
+  execute(test_binary_noop());
+  return TEST_PASS;
+}
+
+static enum test_return test_binary_decr(void)
+{
+  return test_binary_decr_impl("test_binary_decr",
+                               PROTOCOL_BINARY_CMD_DECREMENT);
+}
+
+static enum test_return test_binary_decrq(void)
+{
+  return test_binary_decr_impl("test_binary_decrq",
+                               PROTOCOL_BINARY_CMD_DECREMENTQ);
+}
+
+static enum test_return test_binary_version(void)
+{
+  command cmd;
+  response rsp;
+  raw_command(&cmd, PROTOCOL_BINARY_CMD_VERSION, NULL, 0, NULL, 0);
+
+  execute(send_packet(&cmd));
+  execute(recv_packet(&rsp));
+  verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_VERSION,
+                                  PROTOCOL_BINARY_RESPONSE_SUCCESS));
+
+  return TEST_PASS;
+}
+
+static enum test_return test_binary_flush_impl(const char *key, uint8_t cc)
+{
+  command cmd;
+  response rsp;
+
+  for (int ii= 0; ii < 2; ++ii)
+  {
+    execute(binary_set_item(key, key));
+    flush_command(&cmd, cc, 0, ii == 0);
+    execute(send_packet(&cmd));
+
+    if (cc == PROTOCOL_BINARY_CMD_FLUSH)
+    {
+      execute(recv_packet(&rsp));
+      verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
+    }
+    else
+      execute(test_binary_noop());
+
+    raw_command(&cmd, PROTOCOL_BINARY_CMD_GET, key, strlen(key), NULL, 0);
+    execute(send_packet(&cmd));
+    execute(recv_packet(&rsp));
+    verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_GET,
+                                    PROTOCOL_BINARY_RESPONSE_KEY_ENOENT));
+  }
+
+  return TEST_PASS;
+}
+
+static enum test_return test_binary_flush(void)
+{
+  return test_binary_flush_impl("test_binary_flush", PROTOCOL_BINARY_CMD_FLUSH);
+}
+
+static enum test_return test_binary_flushq(void)
+{
+  return test_binary_flush_impl("test_binary_flushq", PROTOCOL_BINARY_CMD_FLUSHQ);
+}
+
+static enum test_return test_binary_concat_impl(const char *key, uint8_t cc)
+{
+  command cmd;
+  response rsp;
+  const char *value;
+
+  if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_APPENDQ)
+  {
+    value="hello";
+  }
+  else
+  {
+    value=" world";
+  }
+
+  execute(binary_set_item(key, value));
+
+  if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_APPENDQ)
+  {
+    value=" world";
+  }
+  else
+  {
+    value="hello";
+  }
+
+  raw_command(&cmd, cc, key, strlen(key), value, strlen(value));
+  execute(send_packet(&cmd));
+  if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_PREPEND)
+  {
+    execute(recv_packet(&rsp));
+    verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
+  }
+  else
+  {
+    execute(test_binary_noop());
+  }
+
+  raw_command(&cmd, PROTOCOL_BINARY_CMD_GET, key, strlen(key), NULL, 0);
+  execute(send_packet(&cmd));
+  execute(recv_packet(&rsp));
+  verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_GET,
+                                  PROTOCOL_BINARY_RESPONSE_SUCCESS));
+  verify(rsp.plain.message.header.response.bodylen - 4 == 11);
+  verify(memcmp(rsp.bytes + 28, "hello world", 11) == 0);
+
+  return TEST_PASS;
+}
+
+static enum test_return test_binary_append(void)
+{
+  return test_binary_concat_impl("test_binary_append", PROTOCOL_BINARY_CMD_APPEND);
+}
+
+static enum test_return test_binary_prepend(void)
+{
+  return test_binary_concat_impl("test_binary_prepend", PROTOCOL_BINARY_CMD_PREPEND);
+}
+
+static enum test_return test_binary_appendq(void)
+{
+  return test_binary_concat_impl("test_binary_appendq", PROTOCOL_BINARY_CMD_APPENDQ);
+}
+
+static enum test_return test_binary_prependq(void)
+{
+  return test_binary_concat_impl("test_binary_prependq", PROTOCOL_BINARY_CMD_PREPENDQ);
+}
+
+static enum test_return test_binary_stat(void)
+{
+  command cmd;
+  response rsp;
+
+  raw_command(&cmd, PROTOCOL_BINARY_CMD_STAT, NULL, 0, NULL, 0);
+  execute(send_packet(&cmd));
+
+  do
+  {
+    execute(recv_packet(&rsp));
+    verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_STAT,
+                                    PROTOCOL_BINARY_RESPONSE_SUCCESS));
+  } while (rsp.plain.message.header.response.keylen != 0);
+
+  return TEST_PASS;
+}
+
+static enum test_return send_string(const char *cmd)
+{
+  execute(retry_write(cmd, strlen(cmd)));
+  return TEST_PASS;
+}
+
+static enum test_return receive_line(char *buffer, size_t size)
+{
+  size_t offset= 0;
+  while (offset < size)
+  {
+    execute(retry_read(buffer + offset, 1));
+    if (buffer[offset] == '\n')
+    {
+      if (offset + 1 < size)
+      {
+        buffer[offset + 1]= '\0';
+        return TEST_PASS;
+      }
+      else
+        return TEST_FAIL;
+    }
+    ++offset;
+  }
+
+  return TEST_FAIL;
+}
+
+static enum test_return receive_response(const char *msg) {
+  char buffer[80];
+  execute(receive_line(buffer, sizeof(buffer)));
+  if (strcmp(msg, buffer) != 0) {
+      fprintf(stderr, "[%s]\n", buffer);
+  }
+  verify(strcmp(msg, buffer) == 0);
+  return TEST_PASS;
+}
+
+static enum test_return receive_error_response(void)
+{
+  char buffer[80];
+  execute(receive_line(buffer, sizeof(buffer)));
+  verify(strncmp(buffer, "ERROR", 5) == 0 ||
+         strncmp(buffer, "CLIENT_ERROR", 12) == 0 ||
+         strncmp(buffer, "SERVER_ERROR", 12) == 0);
+  return TEST_PASS;
+}
+
+static enum test_return test_ascii_quit(void)
+{
+  /* Verify that quit handles unknown options */
+  execute(send_string("quit foo bar\r\n"));
+  execute(receive_error_response());
+
+  /* quit doesn't support noreply */
+  execute(send_string("quit noreply\r\n"));
+  execute(receive_error_response());
+
+  /* Verify that quit works */
+  execute(send_string("quit\r\n"));
+
+  /* Socket should be closed now, read should return EXIT_SUCCESS */
+  char buffer[80];
+  verify(timeout_io_op(sock, POLLIN, buffer, sizeof(buffer)) == 0);
+  return TEST_PASS_RECONNECT;
+
+}
+
+static enum test_return test_ascii_version(void)
+{
+  /* Verify that version command handles unknown options */
+  execute(send_string("version foo bar\r\n"));
+  execute(receive_error_response());
+
+  /* version doesn't support noreply */
+  execute(send_string("version noreply\r\n"));
+  execute(receive_error_response());
+
+  /* Verify that verify works */
+  execute(send_string("version\r\n"));
+  char buffer[256];
+  execute(receive_line(buffer, sizeof(buffer)));
+  verify(strncmp(buffer, "VERSION ", 8) == 0);
+
+  return TEST_PASS;
+}
+
+static enum test_return test_ascii_verbosity(void)
+{
+  /* This command does not adhere to the spec! */
+  execute(send_string("verbosity foo bar my\r\n"));
+  execute(receive_error_response());
+
+  execute(send_string("verbosity noreply\r\n"));
+  execute(test_ascii_version());
+
+  execute(send_string("verbosity 0 noreply\r\n"));
+  execute(test_ascii_version());
+
+  execute(send_string("verbosity\r\n"));
+  execute(receive_error_response());
+
+  execute(send_string("verbosity 1\r\n"));
+  execute(receive_response("OK\r\n"));
+
+  execute(send_string("verbosity 0\r\n"));
+  execute(receive_response("OK\r\n"));
+
+  return TEST_PASS;
+}
+
+
+
+static enum test_return test_ascii_set_impl(const char* key, bool noreply)
+{
+  /* @todo add tests for bogus format! */
+  char buffer[1024];
+  snprintf(buffer, sizeof(buffer), "set %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : "");
+  execute(send_string(buffer));
+
+  if (!noreply)
+  {
+    execute(receive_response("STORED\r\n"));
+  }
+
+  return test_ascii_version();
+}
+
+static enum test_return test_ascii_set(void)
+{
+  return test_ascii_set_impl("test_ascii_set", false);
+}
+
+static enum test_return test_ascii_set_noreply(void)
+{
+  return test_ascii_set_impl("test_ascii_set_noreply", true);
+}
+
+static enum test_return test_ascii_add_impl(const char* key, bool noreply)
+{
+  /* @todo add tests for bogus format! */
+  char buffer[1024];
+  snprintf(buffer, sizeof(buffer), "add %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : "");
+  execute(send_string(buffer));
+
+  if (!noreply)
+  {
+    execute(receive_response("STORED\r\n"));
+  }
+
+  execute(send_string(buffer));
+
+  if (!noreply)
+  {
+    execute(receive_response("NOT_STORED\r\n"));
+  }
+
+  return test_ascii_version();
+}
+
+static enum test_return test_ascii_add(void)
+{
+  return test_ascii_add_impl("test_ascii_add", false);
+}
+
+static enum test_return test_ascii_add_noreply(void)
+{
+  return test_ascii_add_impl("test_ascii_add_noreply", true);
+}
+
+static enum test_return ascii_get_unknown_value(char **key, char **value, ssize_t *ndata)
+{
+  char buffer[1024];
+
+  execute(receive_line(buffer, sizeof(buffer)));
+  verify(strncmp(buffer, "VALUE ", 6) == 0);
+  char *end= strchr(buffer + 6, ' ');
+  verify(end != NULL);
+  if (end)
+  {
+    *end= '\0';
+  }
+  *key= strdup(buffer + 6);
+  verify(*key != NULL);
+  char *ptr= end + 1;
+
+  errno= 0;
+  unsigned long val= strtoul(ptr, &end, 10); /* flags */
+  verify(errno == 0);
+  verify(ptr != end);
+  verify(val == 0);
+  verify(end != NULL);
+  errno= 0;
+  *ndata = (ssize_t)strtoul(end, &end, 10); /* size */
+  verify(errno == 0);
+  verify(ptr != end);
+  verify(end != NULL);
+  while (end and *end != '\n' and isspace(*end))
+    ++end;
+  verify(end and *end == '\n');
+
+  *value= static_cast<char*>(malloc((size_t)*ndata));
+  verify(*value != NULL);
+
+  execute(retry_read(*value, (size_t)*ndata));
+
+  execute(retry_read(buffer, 2));
+  verify(memcmp(buffer, "\r\n", 2) == 0);
+
+  return TEST_PASS;
+}
+
+static enum test_return ascii_get_value(const char *key, const char *value)
+{
+
+  char buffer[1024];
+  size_t datasize= strlen(value);
+
+  verify(datasize < sizeof(buffer));
+  execute(receive_line(buffer, sizeof(buffer)));
+  verify(strncmp(buffer, "VALUE ", 6) == 0);
+  verify(strncmp(buffer + 6, key, strlen(key)) == 0);
+  char *ptr= buffer + 6 + strlen(key) + 1;
+  char *end;
+
+  errno= 0;
+  unsigned long val= strtoul(ptr, &end, 10); /* flags */
+  verify(errno == 0);
+  verify(ptr != end);
+  verify(val == 0);
+  verify(end != NULL);
+
+  errno= 0;
+  val= strtoul(end, &end, 10); /* size */
+  verify(errno == 0);
+  verify(ptr != end);
+  verify(val == datasize);
+  verify(end != NULL);
+  while (end and *end != '\n' and isspace(*end))
+  {
+    ++end;
+  }
+  verify(end and *end == '\n');
+
+  execute(retry_read(buffer, datasize));
+  verify(memcmp(buffer, value, datasize) == 0);
+
+  execute(retry_read(buffer, 2));
+  verify(memcmp(buffer, "\r\n", 2) == 0);
+
+  return TEST_PASS;
+}
+
+static enum test_return ascii_get_item(const char *key, const char *value,
+                                       bool exist)
+{
+  char buffer[1024];
+  size_t datasize= 0;
+  if (value != NULL)
+  {
+    datasize= strlen(value);
+  }
+
+  verify(datasize < sizeof(buffer));
+  snprintf(buffer, sizeof(buffer), "get %s\r\n", key);
+  execute(send_string(buffer));
+
+  if (exist)
+  {
+    execute(ascii_get_value(key, value));
+  }
+
+  execute(retry_read(buffer, 5));
+  verify(memcmp(buffer, "END\r\n", 5) == 0);
+
+  return TEST_PASS;
+}
+
+static enum test_return ascii_gets_value(const char *key, const char *value,
+                                         unsigned long *cas)
+{
+
+  char buffer[1024];
+  size_t datasize= strlen(value);
+
+  verify(datasize < sizeof(buffer));
+  execute(receive_line(buffer, sizeof(buffer)));
+  verify(strncmp(buffer, "VALUE ", 6) == 0);
+  verify(strncmp(buffer + 6, key, strlen(key)) == 0);
+  char *ptr= buffer + 6 + strlen(key) + 1;
+  char *end;
+
+  errno= 0;
+  unsigned long val= strtoul(ptr, &end, 10); /* flags */
+  verify(errno == 0);
+  verify(ptr != end);
+  verify(val == 0);
+  verify(end != NULL);
+
+  errno= 0;
+  val= strtoul(end, &end, 10); /* size */
+  verify(errno == 0);
+  verify(ptr != end);
+  verify(val == datasize);
+  verify(end != NULL);
+
+  errno= 0;
+  *cas= strtoul(end, &end, 10); /* cas */
+  verify(errno == 0);
+  verify(ptr != end);
+  verify(val == datasize);
+  verify(end != NULL);
+
+  while (end and *end != '\n' and isspace(*end))
+  {
+    ++end;
+  }
+  verify(end and *end == '\n');
+
+  execute(retry_read(buffer, datasize));
+  verify(memcmp(buffer, value, datasize) == 0);
+
+  execute(retry_read(buffer, 2));
+  verify(memcmp(buffer, "\r\n", 2) == 0);
+
+  return TEST_PASS;
+}
+
+static enum test_return ascii_gets_item(const char *key, const char *value,
+                                        bool exist, unsigned long *cas)
+{
+  char buffer[1024];
+  size_t datasize= 0;
+  if (value != NULL)
+  {
+    datasize= strlen(value);
+  }
+
+  verify(datasize < sizeof(buffer));
+  snprintf(buffer, sizeof(buffer), "gets %s\r\n", key);
+  execute(send_string(buffer));
+
+  if (exist)
+    execute(ascii_gets_value(key, value, cas));
+
+  execute(retry_read(buffer, 5));
+  verify(memcmp(buffer, "END\r\n", 5) == 0);
+
+  return TEST_PASS;
+}
+
+static enum test_return ascii_set_item(const char *key, const char *value)
+{
+  char buffer[300];
+  size_t len= strlen(value);
+  snprintf(buffer, sizeof(buffer), "set %s 0 0 %u\r\n", key, (unsigned int)len);
+  execute(send_string(buffer));
+  execute(retry_write(value, len));
+  execute(send_string("\r\n"));
+  execute(receive_response("STORED\r\n"));
+  return TEST_PASS;
+}
+
+static enum test_return test_ascii_replace_impl(const char* key, bool noreply)
+{
+  char buffer[1024];
+  snprintf(buffer, sizeof(buffer), "replace %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : "");
+  execute(send_string(buffer));
+
+  if (noreply)
+  {
+    execute(test_ascii_version());
+  }
+  else
+  {
+    execute(receive_response("NOT_STORED\r\n"));
+  }
+
+  execute(ascii_set_item(key, "value"));
+  execute(ascii_get_item(key, "value", true));
+
+
+  execute(send_string(buffer));
+
+  if (noreply)
+    execute(test_ascii_version());
+  else
+    execute(receive_response("STORED\r\n"));
+
+  return test_ascii_version();
+}
+
+static enum test_return test_ascii_replace(void)
+{
+  return test_ascii_replace_impl("test_ascii_replace", false);
+}
+
+static enum test_return test_ascii_replace_noreply(void)
+{
+  return test_ascii_replace_impl("test_ascii_replace_noreply", true);
+}
+
+static enum test_return test_ascii_cas_impl(const char* key, bool noreply)
+{
+  char buffer[1024];
+  unsigned long cas;
+
+  execute(ascii_set_item(key, "value"));
+  execute(ascii_gets_item(key, "value", true, &cas));
+
+  snprintf(buffer, sizeof(buffer), "cas %s 0 0 6 %lu%s\r\nvalue2\r\n", key, cas, noreply ? " noreply" : "");
+  execute(send_string(buffer));
+
+  if (noreply)
+  {
+    execute(test_ascii_version());
+  }
+  else
+  {
+    execute(receive_response("STORED\r\n"));
+  }
+
+  /* reexecute the same command should fail due to illegal cas */
+  execute(send_string(buffer));
+
+  if (noreply)
+  {
+    execute(test_ascii_version());
+  }
+  else
+  {
+    execute(receive_response("EXISTS\r\n"));
+  }
+
+  return test_ascii_version();
+}
+
+static enum test_return test_ascii_cas(void)
+{
+  return test_ascii_cas_impl("test_ascii_cas", false);
+}
+
+static enum test_return test_ascii_cas_noreply(void)
+{
+  return test_ascii_cas_impl("test_ascii_cas_noreply", true);
+}
+
+static enum test_return test_ascii_delete_impl(const char *key, bool noreply)
+{
+  execute(ascii_set_item(key, "value"));
+
+  execute(send_string("delete\r\n"));
+  execute(receive_error_response());
+  /* BUG: the server accepts delete a b */
+  execute(send_string("delete a b c d e\r\n"));
+  execute(receive_error_response());
+
+  char buffer[1024];
+  snprintf(buffer, sizeof(buffer), "delete %s%s\r\n", key, noreply ? " noreply" : "");
+  execute(send_string(buffer));
+
+  if (noreply)
+    execute(test_ascii_version());
+  else
+    execute(receive_response("DELETED\r\n"));
+
+  execute(ascii_get_item(key, "value", false));
+  execute(send_string(buffer));
+  if (noreply)
+    execute(test_ascii_version());
+  else
+    execute(receive_response("NOT_FOUND\r\n"));
+
+  return TEST_PASS;
+}
+
+static enum test_return test_ascii_delete(void)
+{
+  return test_ascii_delete_impl("test_ascii_delete", false);
+}
+
+static enum test_return test_ascii_delete_noreply(void)
+{
+  return test_ascii_delete_impl("test_ascii_delete_noreply", true);
+}
+
+static enum test_return test_ascii_get(void)
+{
+  execute(ascii_set_item("test_ascii_get", "value"));
+
+  execute(send_string("get\r\n"));
+  execute(receive_error_response());
+  execute(ascii_get_item("test_ascii_get", "value", true));
+  execute(ascii_get_item("test_ascii_get_notfound", "value", false));
+
+  return TEST_PASS;
+}
+
+static enum test_return test_ascii_gets(void)
+{
+  execute(ascii_set_item("test_ascii_gets", "value"));
+
+  execute(send_string("gets\r\n"));
+  execute(receive_error_response());
+  unsigned long cas;
+  execute(ascii_gets_item("test_ascii_gets", "value", true, &cas));
+  execute(ascii_gets_item("test_ascii_gets_notfound", "value", false, &cas));
+
+  return TEST_PASS;
+}
+
+static enum test_return test_ascii_mget(void)
+{
+  const uint32_t nkeys= 5;
+  const char * const keys[]= {
+    "test_ascii_mget1",
+    "test_ascii_mget2",
+    /* test_ascii_mget_3 does not exist :) */
+    "test_ascii_mget4",
+    "test_ascii_mget5",
+    "test_ascii_mget6"
+  };
+
+  for (uint32_t x= 0; x < nkeys; ++x)
+  {
+    execute(ascii_set_item(keys[x], "value"));
+  }
+
+  /* Ask for a key that doesn't exist as well */
+  execute(send_string("get test_ascii_mget1 test_ascii_mget2 test_ascii_mget3 "
+                      "test_ascii_mget4 test_ascii_mget5 "
+                      "test_ascii_mget6\r\n"));
+
+  std::vector<char *> returned;
+  returned.resize(nkeys);
+
+  for (uint32_t x= 0; x < nkeys; ++x)
+  {
+    ssize_t nbytes = 0;
+    char *v= NULL;
+    execute(ascii_get_unknown_value(&returned[x], &v, &nbytes));
+    verify(nbytes == 5);
+    verify(memcmp(v, "value", 5) == 0);
+    free(v);
+  }
+
+  char buffer[5];
+  execute(retry_read(buffer, 5));
+  verify(memcmp(buffer, "END\r\n", 5) == 0);
+
+  /* verify that we got all the keys we expected */
+  for (uint32_t x= 0; x < nkeys; ++x)
+  {
+    bool found= false;
+    for (uint32_t y= 0; y < nkeys; ++y)
+    {
+      if (strcmp(keys[x], returned[y]) == 0)
+      {
+        found = true;
+        break;
+      }
+    }
+    verify(found);
+  }
+
+  for (uint32_t x= 0; x < nkeys; ++x)
+  {
+    free(returned[x]);
+  }
+
+  return TEST_PASS;
+}
+
+static enum test_return test_ascii_incr_impl(const char* key, bool noreply)
+{
+  char cmd[300];
+  snprintf(cmd, sizeof(cmd), "incr %s 1%s\r\n", key, noreply ? " noreply" : "");
+
+  execute(ascii_set_item(key, "0"));
+  for (int x= 1; x < 11; ++x)
+  {
+    execute(send_string(cmd));
+
+    if (noreply)
+      execute(test_ascii_version());
+    else
+    {
+      char buffer[80];
+      execute(receive_line(buffer, sizeof(buffer)));
+      int val= atoi(buffer);
+      verify(val == x);
+    }
+  }
+
+  execute(ascii_get_item(key, "10", true));
+
+  return TEST_PASS;
+}
+
+static enum test_return test_ascii_incr(void)
+{
+  return test_ascii_incr_impl("test_ascii_incr", false);
+}
+
+static enum test_return test_ascii_incr_noreply(void)
+{
+  return test_ascii_incr_impl("test_ascii_incr_noreply", true);
+}
+
+static enum test_return test_ascii_decr_impl(const char* key, bool noreply)
+{
+  char cmd[300];
+  snprintf(cmd, sizeof(cmd), "decr %s 1%s\r\n", key, noreply ? " noreply" : "");
+
+  execute(ascii_set_item(key, "9"));
+  for (int x= 8; x > -1; --x)
+  {
+    execute(send_string(cmd));
+
+    if (noreply)
+    {
+      execute(test_ascii_version());
+    }
+    else
+    {
+      char buffer[80];
+      execute(receive_line(buffer, sizeof(buffer)));
+      int val= atoi(buffer);
+      verify(val == x);
+    }
+  }
+
+  execute(ascii_get_item(key, "0", true));
+
+  /* verify that it doesn't wrap */
+  execute(send_string(cmd));
+  if (noreply)
+  {
+    execute(test_ascii_version());
+  }
+  else
+  {
+    char buffer[80];
+    execute(receive_line(buffer, sizeof(buffer)));
+  }
+  execute(ascii_get_item(key, "0", true));
+
+  return TEST_PASS;
+}
+
+static enum test_return test_ascii_decr(void)
+{
+  return test_ascii_decr_impl("test_ascii_decr", false);
+}
+
+static enum test_return test_ascii_decr_noreply(void)
+{
+  return test_ascii_decr_impl("test_ascii_decr_noreply", true);
+}
+
+
+static enum test_return test_ascii_flush_impl(const char *key, bool noreply)
+{
+#if 0
+  /* Verify that the flush_all command handles unknown options */
+  /* Bug in the current memcached server! */
+  execute(send_string("flush_all foo bar\r\n"));
+  execute(receive_error_response());
+#endif
+
+  execute(ascii_set_item(key, key));
+  execute(ascii_get_item(key, key, true));
+
+  if (noreply)
+  {
+    execute(send_string("flush_all noreply\r\n"));
+    execute(test_ascii_version());
+  }
+  else
+  {
+    execute(send_string("flush_all\r\n"));
+    execute(receive_response("OK\r\n"));
+  }
+
+  execute(ascii_get_item(key, key, false));
+
+  return TEST_PASS;
+}
+
+static enum test_return test_ascii_flush(void)
+{
+  return test_ascii_flush_impl("test_ascii_flush", false);
+}
+
+static enum test_return test_ascii_flush_noreply(void)
+{
+  return test_ascii_flush_impl("test_ascii_flush_noreply", true);
+}
+
+static enum test_return test_ascii_concat_impl(const char *key,
+                                               bool append,
+                                               bool noreply)
+{
+  const char *value;
+
+  if (append)
+    value="hello";
+  else
+    value=" world";
+
+  execute(ascii_set_item(key, value));
+
+  if (append)
+  {
+    value=" world";
+  }
+  else
+  {
+    value="hello";
+  }
+
+  char cmd[400];
+  snprintf(cmd, sizeof(cmd), "%s %s 0 0 %u%s\r\n%s\r\n",
+           append ? "append" : "prepend",
+           key, (unsigned int)strlen(value), noreply ? " noreply" : "",
+           value);
+  execute(send_string(cmd));
+
+  if (noreply)
+  {
+    execute(test_ascii_version());
+  }
+  else
+  {
+    execute(receive_response("STORED\r\n"));
+  }
+
+  execute(ascii_get_item(key, "hello world", true));
+
+  snprintf(cmd, sizeof(cmd), "%s %s_notfound 0 0 %u%s\r\n%s\r\n",
+           append ? "append" : "prepend",
+           key, (unsigned int)strlen(value), noreply ? " noreply" : "",
+           value);
+  execute(send_string(cmd));
+
+  if (noreply)
+  {
+    execute(test_ascii_version());
+  }
+  else
+  {
+    execute(receive_response("NOT_STORED\r\n"));
+  }
+
+  return TEST_PASS;
+}
+
+static enum test_return test_ascii_append(void)
+{
+  return test_ascii_concat_impl("test_ascii_append", true, false);
+}
+
+static enum test_return test_ascii_prepend(void)
+{
+  return test_ascii_concat_impl("test_ascii_prepend", false, false);
+}
+
+static enum test_return test_ascii_append_noreply(void)
+{
+  return test_ascii_concat_impl("test_ascii_append_noreply", true, true);
+}
+
+static enum test_return test_ascii_prepend_noreply(void)
+{
+  return test_ascii_concat_impl("test_ascii_prepend_noreply", false, true);
+}
+
+static enum test_return test_ascii_stat(void)
+{
+  execute(send_string("stats noreply\r\n"));
+  execute(receive_error_response());
+  execute(send_string("stats\r\n"));
+  char buffer[1024];
+  do {
+    execute(receive_line(buffer, sizeof(buffer)));
+  } while (strcmp(buffer, "END\r\n") != 0);
+
+  return TEST_PASS_RECONNECT;
+}
+
+typedef enum test_return(*TEST_FUNC)(void);
+
+struct testcase
+{
+  const char *description;
+  TEST_FUNC function;
+};
+
+struct testcase testcases[]= {
+  { "ascii quit", test_ascii_quit },
+  { "ascii version", test_ascii_version },
+  { "ascii verbosity", test_ascii_verbosity },
+  { "ascii set", test_ascii_set },
+  { "ascii set noreply", test_ascii_set_noreply },
+  { "ascii get", test_ascii_get },
+  { "ascii gets", test_ascii_gets },
+  { "ascii mget", test_ascii_mget },
+  { "ascii flush", test_ascii_flush },
+  { "ascii flush noreply", test_ascii_flush_noreply },
+  { "ascii add", test_ascii_add },
+  { "ascii add noreply", test_ascii_add_noreply },
+  { "ascii replace", test_ascii_replace },
+  { "ascii replace noreply", test_ascii_replace_noreply },
+  { "ascii cas", test_ascii_cas },
+  { "ascii cas noreply", test_ascii_cas_noreply },
+  { "ascii delete", test_ascii_delete },
+  { "ascii delete noreply", test_ascii_delete_noreply },
+  { "ascii incr", test_ascii_incr },
+  { "ascii incr noreply", test_ascii_incr_noreply },
+  { "ascii decr", test_ascii_decr },
+  { "ascii decr noreply", test_ascii_decr_noreply },
+  { "ascii append", test_ascii_append },
+  { "ascii append noreply", test_ascii_append_noreply },
+  { "ascii prepend", test_ascii_prepend },
+  { "ascii prepend noreply", test_ascii_prepend_noreply },
+  { "ascii stat", test_ascii_stat },
+  { "binary noop", test_binary_noop },
+  { "binary quit", test_binary_quit },
+  { "binary quitq", test_binary_quitq },
+  { "binary set", test_binary_set },
+  { "binary setq", test_binary_setq },
+  { "binary flush", test_binary_flush },
+  { "binary flushq", test_binary_flushq },
+  { "binary add", test_binary_add },
+  { "binary addq", test_binary_addq },
+  { "binary replace", test_binary_replace },
+  { "binary replaceq", test_binary_replaceq },
+  { "binary delete", test_binary_delete },
+  { "binary deleteq", test_binary_deleteq },
+  { "binary get", test_binary_get },
+  { "binary getq", test_binary_getq },
+  { "binary getk", test_binary_getk },
+  { "binary getkq", test_binary_getkq },
+  { "binary incr", test_binary_incr },
+  { "binary incrq", test_binary_incrq },
+  { "binary decr", test_binary_decr },
+  { "binary decrq", test_binary_decrq },
+  { "binary version", test_binary_version },
+  { "binary append", test_binary_append },
+  { "binary appendq", test_binary_appendq },
+  { "binary prepend", test_binary_prepend },
+  { "binary prependq", test_binary_prependq },
+  { "binary stat", test_binary_stat },
+  { NULL, NULL}
+};
+
+const int ascii_tests = 1;
+const int binary_tests = 2;
+
+struct test_type_st
+{
+  bool ascii;
+  bool binary;
+};
+
+int main(int argc, char **argv)
+{
+  static const char * const status_msg[]= {"[skip]", "[pass]", "[pass]", "[FAIL]"};
+  struct test_type_st tests= { true, true };
+  int total= 0;
+  int failed= 0;
+  const char *hostname= NULL;
+  const char *port= MEMCACHED_DEFAULT_PORT_STRING;
+  int cmd;
+  bool prompt= false;
+  const char *testname= NULL;
+
+
+
+  while ((cmd= getopt(argc, argv, "qt:vch:p:PT:?ab")) != EOF)
+  {
+    switch (cmd) {
+    case 'a':
+      tests.ascii= true;
+      tests.binary= false;
+      break;
+
+    case 'b':
+      tests.ascii= false;
+      tests.binary= true;
+      break;
+
+    case 't':
+      timeout= atoi(optarg);
+      if (timeout == 0)
+      {
+        fprintf(stderr, "Invalid timeout. Please specify a number for -t\n");
+        return EXIT_FAILURE;
+      }
+      break;
+
+    case 'v': verbose= true;
+      break;
+
+    case 'c': do_core= true;
+      break;
+
+    case 'h': hostname= optarg;
+      break;
+
+    case 'p': port= optarg;
+      break;
+
+    case 'q':
+      close_stdio();
+      break;
+
+    case 'P': prompt= true;
+      break;
+
+    case 'T': testname= optarg;
+       break;
+
+    default:
+      fprintf(stderr, "Usage: %s [-h hostname] [-p port] [-c] [-v] [-t n] [-P] [-T testname]'\n"
+              "\t-c\tGenerate coredump if a test fails\n"
+              "\t-v\tVerbose test output (print out the assertion)\n"
+              "\t-t n\tSet the timeout for io-operations to n seconds\n"
+              "\t-P\tPrompt the user before starting a test.\n"
+              "\t\t\t\"skip\" will skip the test\n"
+              "\t\t\t\"quit\" will terminate memcapable\n"
+              "\t\t\tEverything else will start the test\n"
+              "\t-T n\tJust run the test named n\n"
+              "\t-a\tOnly test the ascii protocol\n"
+              "\t-b\tOnly test the binary protocol\n",
+              argv[0]);
+      return EXIT_SUCCESS;
+    }
+  }
+
+  if (!hostname)
+  {
+    fprintf(stderr, "No hostname was provided.\n");
+    return EXIT_FAILURE;
+  }
+
+  initialize_sockets();
+  sock= connect_server(hostname, port);
+  if (sock == INVALID_SOCKET)
+  {
+    fprintf(stderr, "Failed to connect to <%s:%s>: %s\n",
+            hostname?:"(null)", port?:"(null)", strerror(get_socket_errno()));
+    return EXIT_FAILURE;
+  }
+
+  for (int ii= 0; testcases[ii].description != NULL; ++ii)
+  {
+    if (testname != NULL && strcmp(testcases[ii].description, testname) != 0)
+    {
+      continue;
+    }
+
+    if ((testcases[ii].description[0] == 'a' && (tests.ascii) == 0) ||
+        (testcases[ii].description[0] == 'b' && (tests.binary) == 0))
+    {
+      continue;
+    }
+    ++total;
+    fprintf(stdout, "%-40s", testcases[ii].description);
+    fflush(stdout);
+
+    if (prompt)
+    {
+      fprintf(stdout, "\nPress <return> when you are ready? ");
+      char buffer[80] = {0};
+      if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
+        if (strncmp(buffer, "skip", 4) == 0)
+        {
+          fprintf(stdout, "%-40s%s\n", testcases[ii].description,
+                  status_msg[TEST_SKIP]);
+          fflush(stdout);
+          continue;
+        }
+        if (strncmp(buffer, "quit", 4) == 0)
+        {
+          exit(EXIT_SUCCESS);
+        }
+      }
+
+      fprintf(stdout, "%-40s", testcases[ii].description);
+      fflush(stdout);
+    }
+
+    bool reconnect= false;
+    enum test_return ret= testcases[ii].function();
+    if (ret == TEST_FAIL)
+    {
+      reconnect= true;
+      ++failed;
+      if (verbose)
+      {
+        fprintf(stderr, "\n");
+      }
+    }
+    else if (ret == TEST_PASS_RECONNECT)
+    {
+      reconnect= true;
+    }
+
+    if (ret == TEST_FAIL)
+    {
+      fprintf(stderr, "%s\n", status_msg[ret]);
+    }
+    else
+    {
+      fprintf(stdout, "%s\n", status_msg[ret]);
+    }
+
+    if (reconnect)
+    {
+      closesocket(sock);
+      if ((sock= connect_server(hostname, port)) == INVALID_SOCKET)
+      {
+        fprintf(stderr, "Failed to connect to <%s:%s>: %s\n", hostname?:"(null)", port?:"(null)", strerror(get_socket_errno()));
+        fprintf(stderr, "%d of %d tests failed\n", failed, total);
+        return EXIT_FAILURE;
+      }
+    }
+  }
+
+  closesocket(sock);
+  if (failed == 0)
+  {
+    fprintf(stdout, "All tests passed\n");
+  }
+  else
+  {
+    fprintf(stderr, "%d of %d tests failed\n", failed, total);
+  }
+
+  return (failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/bin/memcapable.sh b/src/bin/memcapable.sh
new file mode 100755 (executable)
index 0000000..78fe1b4
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+src/bin/memcapable -vh localhost
diff --git a/src/bin/memcat.cc b/src/bin/memcat.cc
new file mode 100644 (file)
index 0000000..8653512
--- /dev/null
@@ -0,0 +1,265 @@
+/* LibMemcached
+ * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+#include <mem_config.h>
+
+#include <cstdio>
+#include <cstring>
+#include <getopt.h>
+#include <iostream>
+#include <unistd.h>
+#include <libmemcached-1.0/memcached.h>
+
+#include "utilities.h"
+
+#define PROGRAM_NAME "memcat"
+#define PROGRAM_DESCRIPTION "Cat a set of key values to stdout."
+
+
+/* Prototypes */
+void options_parse(int argc, char *argv[]);
+
+static int opt_binary= 0;
+static int opt_verbose= 0;
+static int opt_displayflag= 0;
+static char *opt_servers= NULL;
+static char *opt_hash= NULL;
+static char *opt_username;
+static char *opt_passwd;
+static char *opt_file;
+
+int main(int argc, char *argv[])
+{
+  char *string;
+  size_t string_length;
+  uint32_t flags;
+  memcached_return_t rc;
+
+  int return_code= EXIT_SUCCESS;
+
+  options_parse(argc, argv);
+  initialize_sockets();
+
+  if (opt_servers == NULL)
+  {
+    char *temp;
+
+    if ((temp= getenv("MEMCACHED_SERVERS")))
+    {
+      opt_servers= strdup(temp);
+    }
+
+    if (opt_servers == NULL)
+    {
+      std::cerr << "No servers provided" << std::endl;
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  memcached_server_st* servers= memcached_servers_parse(opt_servers);
+  if (servers == NULL or memcached_server_list_count(servers) == 0)
+  {
+    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  memcached_st* memc= memcached_create(NULL);
+  process_hash_option(memc, opt_hash);
+
+  memcached_server_push(memc, servers);
+  memcached_server_list_free(servers);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
+                         (uint64_t)opt_binary);
+
+  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    memcached_free(memc);
+    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  if (opt_username)
+  {
+    memcached_return_t ret;
+    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
+    {
+      std::cerr << memcached_last_error_message(memc) << std::endl;
+      memcached_free(memc);
+      return EXIT_FAILURE;
+    }
+  }
+
+  while (optind < argc)
+  {
+    string= memcached_get(memc, argv[optind], strlen(argv[optind]),
+                          &string_length, &flags, &rc);
+    if (rc == MEMCACHED_SUCCESS)
+    {
+      if (opt_displayflag)
+      {
+        if (opt_verbose)
+        {
+          std::cout << "key: " << argv[optind] << std::endl << "flags: " << flags << std::endl;
+        }
+      }
+      else
+      {
+        if (opt_verbose)
+        {
+          std::cout << "key: " << argv[optind] << std::endl << "flags: " << flags << std::endl << "length: " << string_length << std::endl << "value: ";
+        }
+
+        if (opt_file)
+        {
+          FILE *fp= fopen(opt_file, "w");
+          if (fp == NULL)
+          {
+            perror("fopen");
+            return_code= EXIT_FAILURE;
+            break;
+          }
+
+          size_t written= fwrite(string, 1, string_length, fp);
+          if (written != string_length) 
+          {
+            std::cerr << "error writing file to file " << opt_file << " wrote " << written << ", should have written" << string_length << std::endl;
+            return_code= EXIT_FAILURE;
+            break;
+          }
+
+          if (fclose(fp))
+          {
+            std::cerr << "error closing " << opt_file << std::endl;
+            return_code= EXIT_FAILURE;
+            break;
+          }
+        }
+        else
+        {
+          std::cout.write(string, string_length);
+          std::cout << std::endl;
+        }
+        free(string);
+      }
+    }
+    else if (rc != MEMCACHED_NOTFOUND)
+    {
+      std::cerr << "error on " << argv[optind] << "(" <<  memcached_strerror(memc, rc) << ")";
+      if (memcached_last_error_errno(memc))
+      {
+        std::cerr << " system error (" << strerror(memcached_last_error_errno(memc)) << ")" << std::endl;
+      }
+      std::cerr << std::endl;
+
+      return_code= EXIT_FAILURE;
+      break;
+    }
+    else // Unknown Issue
+    {
+      std::cerr << "error on " << argv[optind] << "("<< memcached_strerror(NULL, rc) << ")" << std::endl;
+      return_code= EXIT_FAILURE;
+    }
+    optind++;
+  }
+
+  memcached_free(memc);
+
+  if (opt_servers)
+  {
+    free(opt_servers);
+  }
+  if (opt_hash)
+  {
+    free(opt_hash);
+  }
+
+  return return_code;
+}
+
+
+void options_parse(int argc, char *argv[])
+{
+  int option_index= 0;
+
+  memcached_programs_help_st help_options[]=
+  {
+    {0},
+  };
+
+  static struct option long_options[]=
+    {
+      {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+      {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+      {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+      {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
+      {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+      {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
+      {(OPTIONSTRING)"flag", no_argument, &opt_displayflag, OPT_FLAG},
+      {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
+      {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+      {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
+      {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
+      {(OPTIONSTRING)"file", required_argument, NULL, OPT_FILE},
+      {0, 0, 0, 0},
+    };
+
+  while (1)
+  {
+    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+    if (option_rv == -1) break;
+    switch (option_rv)
+    {
+    case 0:
+      break;
+    case OPT_BINARY:
+      opt_binary = 1;
+      break;
+    case OPT_VERBOSE: /* --verbose or -v */
+      opt_verbose = OPT_VERBOSE;
+      break;
+    case OPT_DEBUG: /* --debug or -d */
+      opt_verbose = OPT_DEBUG;
+      break;
+    case OPT_VERSION: /* --version or -V */
+      version_command(PROGRAM_NAME);
+      break;
+    case OPT_HELP: /* --help or -h */
+      help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
+      break;
+    case OPT_SERVERS: /* --servers or -s */
+      opt_servers= strdup(optarg);
+      break;
+    case OPT_HASH:
+      opt_hash= strdup(optarg);
+      break;
+    case OPT_USERNAME:
+      opt_username= optarg;
+      break;
+    case OPT_PASSWD:
+      opt_passwd= optarg;
+      break;
+    case OPT_FILE:
+      opt_file= optarg;
+      break;
+
+    case OPT_QUIET:
+      close_stdio();
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(EXIT_FAILURE);
+    default:
+      abort();
+    }
+  }
+}
diff --git a/src/bin/memcat.sh b/src/bin/memcat.sh
new file mode 100755 (executable)
index 0000000..fbdc212
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+src/bin/memcp.sh
+src/bin/memcat --servers=localhost -v mem.testdata
diff --git a/src/bin/memcp.cc b/src/bin/memcp.cc
new file mode 100644 (file)
index 0000000..d87e0ca
--- /dev/null
@@ -0,0 +1,449 @@
+/* LibMemcached
+ * Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+#include "mem_config.h"
+
+#include <cerrno>
+#include <climits>
+#include <cstdio>
+#include <cstdlib>
+#include <cstdlib>
+#include <cstring>
+#include <fcntl.h>
+#include <getopt.h>
+#include <iostream>
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/types.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+
+#include <libmemcached-1.0/memcached.h>
+
+#include "client_options.h"
+#include "utilities.h"
+
+#define PROGRAM_NAME "memcp"
+#define PROGRAM_DESCRIPTION "Copy a set of files to a memcached cluster."
+
+/* Prototypes */
+static void options_parse(int argc, char *argv[]);
+
+static bool opt_binary= false;
+static bool opt_udp= false;
+static bool opt_buffer= false;
+static int opt_verbose= 0;
+static char *opt_servers= NULL;
+static char *opt_hash= NULL;
+static int opt_method= OPT_SET;
+static uint32_t opt_flags= 0;
+static time_t opt_expires= 0;
+static char *opt_username;
+static char *opt_passwd;
+
+static long strtol_wrapper(const char *nptr, int base, bool *error)
+{
+  long val;
+  char *endptr;
+
+  errno= 0;    /* To distinguish success/failure after call */
+  val= strtol(nptr, &endptr, base);
+
+  /* Check for various possible errors */
+
+  if ((errno == ERANGE and (val == LONG_MAX or val == LONG_MIN))
+      or (errno != 0 && val == 0))
+  {
+    *error= true;
+    return 0;
+  }
+
+  if (endptr == nptr)
+  {
+    *error= true;
+    return 0;
+  }
+
+  *error= false;
+  return val;
+}
+
+int main(int argc, char *argv[])
+{
+
+  options_parse(argc, argv);
+
+  if (optind >= argc)
+  {
+    fprintf(stderr, "Expected argument after options\n");
+    exit(EXIT_FAILURE);
+  }
+
+  initialize_sockets();
+
+  memcached_st *memc= memcached_create(NULL);
+
+  if (opt_udp)
+  {
+    if (opt_verbose)
+    {
+      std::cout << "Enabling UDP" << std::endl;
+    }
+
+    if (memcached_failed(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, opt_udp)))
+    {
+      memcached_free(memc);
+      std::cerr << "Could not enable UDP protocol." << std::endl;
+      return EXIT_FAILURE;
+    }
+  }
+
+  if (opt_buffer)
+  {
+    if (opt_verbose)
+    {
+      std::cout << "Enabling MEMCACHED_BEHAVIOR_BUFFER_REQUESTS" << std::endl;
+    }
+
+    if (memcached_failed(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, opt_buffer)))
+    {
+      memcached_free(memc);
+      std::cerr << "Could not enable MEMCACHED_BEHAVIOR_BUFFER_REQUESTS." << std::endl;
+      return EXIT_FAILURE;
+    }
+  }
+
+  process_hash_option(memc, opt_hash);
+
+  if (opt_servers == NULL)
+  {
+    char *temp;
+
+    if ((temp= getenv("MEMCACHED_SERVERS")))
+    {
+      opt_servers= strdup(temp);
+    }
+#if 0
+    else if (argc >= 1 and argv[--argc])
+    {
+      opt_servers= strdup(argv[argc]);
+    }
+#endif
+
+    if (opt_servers == NULL)
+    {
+      std::cerr << "No Servers provided" << std::endl;
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  memcached_server_st* servers= memcached_servers_parse(opt_servers);
+  if (servers == NULL or memcached_server_list_count(servers) == 0)
+  {
+    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  memcached_server_push(memc, servers);
+  memcached_server_list_free(servers);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, opt_binary);
+  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    memcached_free(memc);
+    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  if (opt_username)
+  {
+    memcached_return_t ret;
+    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
+    {
+      std::cerr << memcached_last_error_message(memc) << std::endl;
+      memcached_free(memc);
+      return EXIT_FAILURE;
+    }
+  }
+
+  int exit_code= EXIT_SUCCESS;
+  while (optind < argc)
+  {
+    int fd= open(argv[optind], O_RDONLY);
+    if (fd < 0)
+    {
+      std::cerr << "memcp " << argv[optind] << " " << strerror(errno) << std::endl;
+      optind++;
+      exit_code= EXIT_FAILURE;
+      continue;
+    }
+
+    struct stat sbuf;
+    if (fstat(fd, &sbuf) == -1)
+    {
+      std::cerr << "memcp " << argv[optind] << " " << strerror(errno) << std::endl;
+      optind++;
+      exit_code= EXIT_FAILURE;
+      continue;
+    }
+
+    char *ptr= rindex(argv[optind], '/');
+    if (ptr)
+    {
+      ptr++;
+    }
+    else
+    {
+      ptr= argv[optind];
+    }
+
+    if (opt_verbose)
+    {
+      static const char *opstr[] = { "set", "add", "replace" };
+      printf("op: %s\nsource file: %s\nlength: %lu\n"
+            "key: %s\nflags: %x\nexpires: %lu\n",
+            opstr[opt_method - OPT_SET], argv[optind], (unsigned long)sbuf.st_size,
+            ptr, opt_flags, (unsigned long)opt_expires);
+    }
+
+    // The file may be empty
+    char *file_buffer_ptr= NULL;
+    if (sbuf.st_size > 0)
+    {
+      if ((file_buffer_ptr= (char *)malloc(sizeof(char) * (size_t)sbuf.st_size)) == NULL)
+      {
+        std::cerr << "Error allocating file buffer(" << strerror(errno) << ")" << std::endl;
+        close(fd);
+        exit(EXIT_FAILURE);
+      }
+
+      ssize_t read_length;
+      if ((read_length= ::read(fd, file_buffer_ptr, (size_t)sbuf.st_size)) == -1)
+      {
+        std::cerr << "Error while reading file " << file_buffer_ptr << " (" << strerror(errno) << ")" << std::endl;
+        close(fd);
+        free(file_buffer_ptr);
+        exit(EXIT_FAILURE);
+      }
+
+      if (read_length != sbuf.st_size)
+      {
+        std::cerr << "Failure while reading file. Read length was not equal to stat() length" << std::endl;
+        close(fd);
+        free(file_buffer_ptr);
+        exit(EXIT_FAILURE);
+      }
+    }
+
+    memcached_return_t rc;
+    if (opt_method == OPT_ADD)
+    {
+      rc= memcached_add(memc, ptr, strlen(ptr),
+                        file_buffer_ptr, (size_t)sbuf.st_size,
+                       opt_expires, opt_flags);
+    }
+    else if (opt_method == OPT_REPLACE)
+    {
+      rc= memcached_replace(memc, ptr, strlen(ptr),
+                           file_buffer_ptr, (size_t)sbuf.st_size,
+                           opt_expires, opt_flags);
+    }
+    else
+    {
+      rc= memcached_set(memc, ptr, strlen(ptr),
+                        file_buffer_ptr, (size_t)sbuf.st_size,
+                        opt_expires, opt_flags);
+    }
+
+    if (memcached_failed(rc))
+    {
+      std::cerr << "Error occrrured during memcached_set(): " << memcached_last_error_message(memc) << std::endl;
+      exit_code= EXIT_FAILURE;
+    }
+
+    ::free(file_buffer_ptr);
+    ::close(fd);
+    optind++;
+  }
+
+  if (opt_verbose)
+  {
+    std::cout << "Calling memcached_free()" << std::endl;
+  }
+
+  memcached_free(memc);
+
+  if (opt_servers)
+  {
+    free(opt_servers);
+  }
+
+  if (opt_hash)
+  {
+    free(opt_hash);
+  }
+
+  return exit_code;
+}
+
+static void options_parse(int argc, char *argv[])
+{
+  memcached_programs_help_st help_options[]=
+  {
+    {0},
+  };
+
+  static struct option long_options[]=
+    {
+      {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+      {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+      {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+      {(OPTIONSTRING)"udp", no_argument, NULL, OPT_UDP},
+      {(OPTIONSTRING)"buffer", no_argument, NULL, OPT_BUFFER},
+      {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
+      {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+      {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
+      {(OPTIONSTRING)"flag", required_argument, NULL, OPT_FLAG},
+      {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
+      {(OPTIONSTRING)"set",  no_argument, NULL, OPT_SET},
+      {(OPTIONSTRING)"add",  no_argument, NULL, OPT_ADD},
+      {(OPTIONSTRING)"replace",  no_argument, NULL, OPT_REPLACE},
+      {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
+      {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+      {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
+      {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
+      {0, 0, 0, 0},
+    };
+
+  bool opt_version= false;
+  bool opt_help= false;
+  int option_index= 0;
+
+  while (1)
+  {
+    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+
+    if (option_rv == -1)
+      break;
+
+    switch (option_rv)
+    {
+    case 0:
+      break;
+
+    case OPT_BINARY:
+      opt_binary= true;
+      break;
+
+    case OPT_VERBOSE: /* --verbose or -v */
+      opt_verbose= OPT_VERBOSE;
+      break;
+
+    case OPT_DEBUG: /* --debug or -d */
+      opt_verbose= OPT_DEBUG;
+      break;
+
+    case OPT_VERSION: /* --version or -V */
+      opt_version= true;
+      break;
+
+    case OPT_HELP: /* --help or -h */
+      opt_help= true;
+      break;
+
+    case OPT_SERVERS: /* --servers or -s */
+      opt_servers= strdup(optarg);
+      break;
+
+    case OPT_FLAG: /* --flag */
+      {
+        bool strtol_error;
+        opt_flags= (uint32_t)strtol_wrapper(optarg, 16, &strtol_error);
+        if (strtol_error == true)
+        {
+          fprintf(stderr, "Bad value passed via --flag\n");
+          exit(1);
+        }
+      }
+      break;
+
+    case OPT_EXPIRE: /* --expire */
+      {
+        bool strtol_error;
+        opt_expires= (time_t)strtol_wrapper(optarg, 10, &strtol_error);
+        if (strtol_error == true)
+        {
+          fprintf(stderr, "Bad value passed via --expire\n");
+          exit(1);
+        }
+      }
+      break;
+
+    case OPT_SET:
+      opt_method= OPT_SET;
+      break;
+
+    case OPT_REPLACE:
+      opt_method= OPT_REPLACE;
+      break;
+
+    case OPT_ADD:
+      opt_method= OPT_ADD;
+      break;
+
+    case OPT_HASH:
+      opt_hash= strdup(optarg);
+      break;
+
+    case OPT_USERNAME:
+      opt_username= optarg;
+      break;
+
+    case OPT_PASSWD:
+      opt_passwd= optarg;
+      break;
+
+    case OPT_QUIET:
+      close_stdio();
+      break;
+
+    case OPT_UDP:
+      opt_udp= true;
+      break;
+
+    case OPT_BUFFER:
+      opt_buffer= true;
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(1);
+    default:
+      abort();
+    }
+  }
+
+  if (opt_version)
+  {
+    version_command(PROGRAM_NAME);
+    exit(EXIT_SUCCESS);
+  }
+
+  if (opt_help)
+  {
+    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
+    exit(EXIT_SUCCESS);
+  }
+}
diff --git a/src/bin/memcp.sh b/src/bin/memcp.sh
new file mode 100755 (executable)
index 0000000..c173d46
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+src/bin/memcp -v --servers localhost mem.testdata
diff --git a/src/bin/memdump.cc b/src/bin/memdump.cc
new file mode 100644 (file)
index 0000000..48c35d3
--- /dev/null
@@ -0,0 +1,239 @@
+/* LibMemcached
+ * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+#include "mem_config.h"
+
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <fcntl.h>
+#include <getopt.h>
+#include <inttypes.h>
+#include <iostream>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <libmemcached-1.0/memcached.h>
+
+#include "client_options.h"
+#include "utilities.h"
+
+#define PROGRAM_NAME "memdump"
+#define PROGRAM_DESCRIPTION "Dump all values from one or many servers."
+
+/* Prototypes */
+static void options_parse(int argc, char *argv[]);
+
+static bool opt_binary=0;
+static int opt_verbose= 0;
+static char *opt_servers= NULL;
+static char *opt_hash= NULL;
+static char *opt_username;
+static char *opt_passwd;
+
+/* Print the keys and counter how many were found */
+static memcached_return_t key_printer(const memcached_st *,
+                                      const char *key, size_t key_length,
+                                      void *)
+{
+  std::cout.write(key, key_length);
+  std::cout << std::endl;
+
+  return MEMCACHED_SUCCESS;
+}
+
+int main(int argc, char *argv[])
+{
+  memcached_dump_fn callbacks[1];
+
+  callbacks[0]= &key_printer;
+
+  options_parse(argc, argv);
+
+  if (opt_servers == NULL)
+  {
+    char *temp;
+
+    if ((temp= getenv("MEMCACHED_SERVERS")))
+    {
+      opt_servers= strdup(temp);
+    }
+    else if (argc >= 1 and argv[--argc])
+    {
+      opt_servers= strdup(argv[argc]);
+    }
+
+    if (opt_servers == NULL)
+    {
+      std::cerr << "No Servers provided" << std::endl;
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  memcached_server_st* servers= memcached_servers_parse(opt_servers);
+  if (servers == NULL or memcached_server_list_count(servers) == 0)
+  {
+    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  memcached_st *memc= memcached_create(NULL);
+  if (memc == NULL)
+  {
+    std::cerr << "Could not allocate a memcached_st structure.\n" << std::endl;
+    return EXIT_FAILURE;
+  }
+  process_hash_option(memc, opt_hash);
+
+  memcached_server_push(memc, servers);
+  memcached_server_list_free(servers);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
+                         (uint64_t)opt_binary);
+
+  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    memcached_free(memc);
+    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  if (opt_username)
+  {
+    memcached_return_t ret;
+    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
+    {
+      std::cerr << memcached_last_error_message(memc) << std::endl;
+      memcached_free(memc);
+      return EXIT_FAILURE;
+    }
+  }
+
+  memcached_return_t rc= memcached_dump(memc, callbacks, NULL, 1);
+
+  int exit_code= EXIT_SUCCESS;
+  if (memcached_failed(rc))
+  {
+    if (opt_verbose)
+    {
+      std::cerr << "Failed to dump keys: " << memcached_last_error_message(memc) << std::endl;
+    }
+    exit_code= EXIT_FAILURE;
+  }
+
+  memcached_free(memc);
+
+  if (opt_servers)
+  {
+    free(opt_servers);
+  }
+  if (opt_hash)
+  {
+    free(opt_hash);
+  }
+
+  return exit_code;
+}
+
+static void options_parse(int argc, char *argv[])
+{
+  static struct option long_options[]=
+    {
+      {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+      {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+      {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+      {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
+      {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+      {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
+      {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
+      {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+      {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
+      {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
+      {0, 0, 0, 0}
+    };
+
+  int option_index= 0;
+  bool opt_version= false;
+  bool opt_help= false;
+  while (1)
+  {
+    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+
+    if (option_rv == -1) break;
+
+    switch (option_rv)
+    {
+    case 0:
+      break;
+
+    case OPT_BINARY:
+      opt_binary= true;
+      break;
+
+    case OPT_VERBOSE: /* --verbose or -v */
+      opt_verbose= OPT_VERBOSE;
+      break;
+
+    case OPT_DEBUG: /* --debug or -d */
+      opt_verbose= OPT_DEBUG;
+      break;
+
+    case OPT_VERSION: /* --version or -V */
+      opt_verbose= true;
+      break;
+
+    case OPT_HELP: /* --help or -h */
+      opt_help= true;
+      break;
+
+    case OPT_SERVERS: /* --servers or -s */
+      opt_servers= strdup(optarg);
+      break;
+
+    case OPT_HASH:
+      opt_hash= strdup(optarg);
+      break;
+
+    case OPT_USERNAME:
+       opt_username= optarg;
+       break;
+
+    case OPT_PASSWD:
+       opt_passwd= optarg;
+       break;
+
+    case OPT_QUIET:
+      close_stdio();
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(1);
+    default:
+      abort();
+    }
+  }
+
+  if (opt_version)
+  {
+    version_command(PROGRAM_NAME);
+    exit(EXIT_SUCCESS);
+  }
+
+  if (opt_help)
+  {
+    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, NULL);
+    exit(EXIT_SUCCESS);
+  }
+}
diff --git a/src/bin/memdump.sh b/src/bin/memdump.sh
new file mode 100755 (executable)
index 0000000..ee71c55
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/bash
+src/bin/memdump -v --servers localhost
diff --git a/src/bin/memerror.cc b/src/bin/memerror.cc
new file mode 100644 (file)
index 0000000..3cee64c
--- /dev/null
@@ -0,0 +1,129 @@
+/* LibMemcached
+ * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+#include "mem_config.h"
+
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <climits>
+
+#include <getopt.h>
+#include <iostream>
+#include <unistd.h>
+
+#include <libmemcached-1.0/memcached.h>
+
+#include "utilities.h"
+
+#define PROGRAM_NAME "memerror"
+#define PROGRAM_DESCRIPTION "Translate a memcached errror code into a string."
+
+
+/* Prototypes */
+void options_parse(int argc, char *argv[]);
+
+int main(int argc, char *argv[])
+{
+  options_parse(argc, argv);
+
+  if (argc < 2)
+  {
+    return EXIT_FAILURE;
+  }
+
+  while (optind < argc)
+  {
+    errno= 0;
+    char *nptr;
+    unsigned long value= strtoul(argv[optind], &nptr, 10);
+
+    if ((errno != 0) or
+        (nptr == argv[optind] and value == 0) or
+        (value == ULONG_MAX and errno == ERANGE) or
+        (value == 0 and errno == EINVAL))
+    {
+      std::cerr << "strtoul() was unable to parse given value" << std::endl;
+      return EXIT_FAILURE;
+    }
+
+    if (value < MEMCACHED_MAXIMUM_RETURN)
+    {
+      std::cout << memcached_strerror(NULL, (memcached_return_t)value) << std::endl;
+    }
+    else
+    {
+      std::cerr << memcached_strerror(NULL, MEMCACHED_MAXIMUM_RETURN) << std::endl;
+      return EXIT_FAILURE;
+    }
+
+    optind++;
+  }
+
+  return EXIT_SUCCESS;
+}
+
+
+void options_parse(int argc, char *argv[])
+{
+  static struct option long_options[]=
+    {
+      {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+      {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+      {0, 0, 0, 0},
+    };
+
+  bool opt_version= false;
+  bool opt_help= false;
+  int option_index= 0;
+  while (1) 
+  {
+    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+    if (option_rv == -1)
+    {
+      break;
+    }
+
+    switch (option_rv)
+    {
+    case 0:
+      break;
+
+    case OPT_VERSION: /* --version or -V */
+      opt_version= true;
+      break;
+
+    case OPT_HELP: /* --help or -h */
+      opt_help= true;
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(EXIT_FAILURE);
+
+    default:
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  if (opt_version)
+  {
+    version_command(PROGRAM_NAME);
+    exit(EXIT_SUCCESS);
+  }
+
+  if (opt_help)
+  {
+    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, NULL);
+    exit(EXIT_SUCCESS);
+  }
+}
diff --git a/src/bin/memerror.sh b/src/bin/memerror.sh
new file mode 100755 (executable)
index 0000000..70bf7ce
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+src/bin/memerror 0 1 2 3
diff --git a/src/bin/memexist.cc b/src/bin/memexist.cc
new file mode 100644 (file)
index 0000000..505f538
--- /dev/null
@@ -0,0 +1,241 @@
+/* LibMemcached
+ * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+#include "mem_config.h"
+
+#include <cstdio>
+#include <cstring>
+#include <getopt.h>
+#include <iostream>
+#include <unistd.h>
+
+#include <libmemcached-1.0/memcached.h>
+#include "client_options.h"
+#include "utilities.h"
+
+static int opt_binary= 0;
+static int opt_verbose= 0;
+static char *opt_servers= NULL;
+static char *opt_hash= NULL;
+static char *opt_username;
+static char *opt_passwd;
+
+#define PROGRAM_NAME "memexist"
+#define PROGRAM_DESCRIPTION "Check for the existance of a key within a cluster."
+
+/* Prototypes */
+static void options_parse(int argc, char *argv[]);
+
+int main(int argc, char *argv[])
+{
+  options_parse(argc, argv);
+  initialize_sockets();
+
+  if (opt_servers == NULL)
+  {
+    char *temp;
+
+    if ((temp= getenv("MEMCACHED_SERVERS")))
+    {
+      opt_servers= strdup(temp);
+    }
+
+    if (opt_servers == NULL)
+    {
+      std::cerr << "No Servers provided" << std::endl;
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  memcached_server_st* servers= memcached_servers_parse(opt_servers);
+  if (servers == NULL or memcached_server_list_count(servers) == 0)
+  {
+    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  memcached_st* memc= memcached_create(NULL);
+  process_hash_option(memc, opt_hash);
+
+  memcached_server_push(memc, servers);
+  memcached_server_list_free(servers);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
+                         (uint64_t) opt_binary);
+
+  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    memcached_free(memc);
+    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  if (opt_username)
+  {
+    memcached_return_t ret;
+    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
+    {
+      std::cerr << memcached_last_error_message(memc) << std::endl;
+      memcached_free(memc);
+      return EXIT_FAILURE;
+    }
+  }
+
+  int return_code= EXIT_SUCCESS;
+
+  while (optind < argc)
+  {
+    memcached_return_t rc= memcached_exist(memc, argv[optind], strlen(argv[optind]));
+
+    if (rc == MEMCACHED_NOTFOUND)
+    {
+      if (opt_verbose)
+      {
+        std::cout << "Could not find key \"" << argv[optind] << "\"" << std::endl;
+      }
+
+      return_code= EXIT_FAILURE;
+    }
+    else if (memcached_failed(rc))
+    {
+      if (opt_verbose)
+      {
+        std::cerr << "Fatal error for key \"" << argv[optind] << "\" :" <<  memcached_last_error_message(memc) << std::endl;
+      }
+
+      return_code= EXIT_FAILURE;
+    }
+    else // success
+    {
+      if (opt_verbose)
+      {
+        std::cout << "Found key " << argv[optind] << std::endl;
+      }
+    }
+
+    optind++;
+  }
+
+  memcached_free(memc);
+
+  if (opt_servers)
+  {
+    free(opt_servers);
+  }
+
+  if (opt_hash)
+  {
+    free(opt_hash);
+  }
+
+  return return_code;
+}
+
+
+static void options_parse(int argc, char *argv[])
+{
+  memcached_programs_help_st help_options[]=
+  {
+    {0},
+  };
+
+  static struct option long_options[]=
+  {
+    {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+    {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+    {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+    {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
+    {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+    {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
+    {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
+    {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+    {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
+    {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
+    {0, 0, 0, 0},
+  };
+
+  bool opt_version= false;
+  bool opt_help= false;
+  int option_index= 0;
+
+  while (1)
+  {
+    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+    if (option_rv == -1) 
+    {
+      break;
+    }
+
+    switch (option_rv)
+    {
+    case 0:
+      break;
+
+    case OPT_BINARY:
+      opt_binary = 1;
+      break;
+
+    case OPT_VERBOSE: /* --verbose or -v */
+      opt_verbose = OPT_VERBOSE;
+      break;
+
+    case OPT_DEBUG: /* --debug or -d */
+      opt_verbose = OPT_DEBUG;
+      break;
+
+    case OPT_VERSION: /* --version or -V */
+      opt_version= true;
+      break;
+
+    case OPT_HELP: /* --help or -h */
+      opt_help= true;
+      break;
+
+    case OPT_SERVERS: /* --servers or -s */
+      opt_servers= strdup(optarg);
+      break;
+
+    case OPT_HASH:
+      opt_hash= strdup(optarg);
+      break;
+
+    case OPT_USERNAME:
+      opt_username= optarg;
+      break;
+
+    case OPT_PASSWD:
+      opt_passwd= optarg;
+      break;
+
+    case OPT_QUIET:
+      close_stdio();
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(EXIT_SUCCESS);
+
+    default:
+      abort();
+    }
+  }
+
+  if (opt_version)
+  {
+    version_command(PROGRAM_NAME);
+    exit(EXIT_SUCCESS);
+  }
+
+  if (opt_help)
+  {
+    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
+    exit(EXIT_SUCCESS);
+  }
+}
diff --git a/src/bin/memexist.sh b/src/bin/memexist.sh
new file mode 100755 (executable)
index 0000000..9cbaf75
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/bash
+src/bin/memcp.sh
+src/bin/memexist -v --servers localhost mem.testdata
diff --git a/src/bin/memflush.cc b/src/bin/memflush.cc
new file mode 100644 (file)
index 0000000..71545ea
--- /dev/null
@@ -0,0 +1,198 @@
+/* LibMemcached
+ * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+#include "mem_config.h"
+
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <getopt.h>
+#include <iostream>
+#include <unistd.h>
+
+#include <libmemcached-1.0/memcached.h>
+#include "client_options.h"
+#include "utilities.h"
+
+static int opt_binary= 0;
+static int opt_verbose= 0;
+static time_t opt_expire= 0;
+static char *opt_servers= NULL;
+static char *opt_username;
+static char *opt_passwd;
+
+#define PROGRAM_NAME "memflush"
+#define PROGRAM_DESCRIPTION "Erase all data in a server of memcached servers."
+
+/* Prototypes */
+void options_parse(int argc, char *argv[]);
+
+int main(int argc, char *argv[])
+{
+  options_parse(argc, argv);
+
+  if (opt_servers == NULL)
+  {
+    char *temp;
+
+    if ((temp= getenv("MEMCACHED_SERVERS")))
+    {
+      opt_servers= strdup(temp);
+    }
+
+    if (opt_servers == NULL)
+    {
+      std::cerr << "No Servers provided" << std::endl;
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  memcached_server_st* servers= memcached_servers_parse(opt_servers);
+  if (servers == NULL or memcached_server_list_count(servers) == 0)
+  {
+    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  memcached_st *memc= memcached_create(NULL);
+  memcached_server_push(memc, servers);
+  memcached_server_list_free(servers);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
+                         (uint64_t) opt_binary);
+
+  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    memcached_free(memc);
+    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  if (opt_username)
+  {
+    memcached_return_t ret;
+    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
+    {
+      std::cerr << memcached_last_error_message(memc) << std::endl;
+      memcached_free(memc);
+      return EXIT_FAILURE;
+    }
+  }
+
+  memcached_return_t rc = memcached_flush(memc, opt_expire);
+  if (rc != MEMCACHED_SUCCESS)
+  {
+    std::cerr << memcached_last_error_message(memc) << std::endl;
+  }
+
+  memcached_free(memc);
+
+  free(opt_servers);
+
+  return EXIT_SUCCESS;
+}
+
+
+void options_parse(int argc, char *argv[])
+{
+  static struct option long_options[]=
+  {
+    {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+    {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+    {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+    {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
+    {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+    {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
+    {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
+    {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+    {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
+    {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
+    {0, 0, 0, 0},
+  };
+
+  bool opt_version= false;
+  bool opt_help= false;
+  int option_index= 0;
+  while (1)
+  {
+    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+    if (option_rv == -1) break;
+    switch (option_rv)
+    {
+    case 0:
+      break;
+
+    case OPT_BINARY:
+      opt_binary= true;
+      break;
+
+    case OPT_VERBOSE: /* --verbose or -v */
+      opt_verbose= OPT_VERBOSE;
+      break;
+
+    case OPT_DEBUG: /* --debug or -d */
+      opt_verbose= OPT_DEBUG;
+      break;
+
+    case OPT_VERSION: /* --version or -V */
+      opt_version= true;
+      break;
+
+    case OPT_HELP: /* --help or -h */
+      opt_help= true;
+      break;
+
+    case OPT_SERVERS: /* --servers or -s */
+      opt_servers= strdup(optarg);
+      break;
+
+    case OPT_EXPIRE: /* --expire */
+      errno= 0;
+      opt_expire= (time_t)strtoll(optarg, (char **)NULL, 10);
+      if (errno != 0)
+      {
+        std::cerr << "Incorrect value passed to --expire: `" << optarg << "`" << std::endl;
+        exit(EXIT_FAILURE);
+      }
+      break;
+
+    case OPT_USERNAME:
+      opt_username= optarg;
+      break;
+
+    case OPT_PASSWD:
+      opt_passwd= optarg;
+      break;
+
+    case OPT_QUIET:
+      close_stdio();
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(EXIT_FAILURE);
+
+    default:
+      abort();
+    }
+  }
+
+  if (opt_version)
+  {
+    version_command(PROGRAM_NAME);
+    exit(EXIT_SUCCESS);
+  }
+
+  if (opt_help)
+  {
+    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, NULL);
+    exit(EXIT_SUCCESS);
+  }
+}
diff --git a/src/bin/memflush.sh b/src/bin/memflush.sh
new file mode 100755 (executable)
index 0000000..770d844
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+src/bin/memflush -v --servers localhost
diff --git a/src/bin/memparse.cc b/src/bin/memparse.cc
new file mode 100644 (file)
index 0000000..fc2cb0c
--- /dev/null
@@ -0,0 +1,70 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <mem_config.h>
+
+#include <cstdio>
+#include <cstring>
+#include <iostream>
+
+#include <libmemcached-1.0/memcached.h>
+
+int main(int argc, char *argv[])
+{
+
+  if (argc < 2)
+  {
+    std::cerr << "No arguments provided." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  for (int x= 1; x < argc; x++)
+  {
+    char buffer[BUFSIZ];
+    memcached_return_t rc;
+    rc= libmemcached_check_configuration(argv[x], strlen(argv[x]), buffer, sizeof(buffer));
+
+    if (rc != MEMCACHED_SUCCESS)
+    {
+      std::cerr << "Failed to parse argument #" << x << " " << argv[x] << std::endl;
+      std::cerr << buffer << std::endl;
+      return EXIT_FAILURE;
+    }
+  }
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/bin/memparse.sh b/src/bin/memparse.sh
new file mode 100755 (executable)
index 0000000..8d7433e
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+src/bin/memparse --server=localhost:11211/?1 --server=127.0.0.1:11211/?2
diff --git a/src/bin/memping.cc b/src/bin/memping.cc
new file mode 100644 (file)
index 0000000..180d6a2
--- /dev/null
@@ -0,0 +1,197 @@
+/* LibMemcached
+ * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+#include "mem_config.h"
+
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <libmemcached-1.0/memcached.h>
+#include <libmemcachedutil-1.0/util.h>
+#include "client_options.h"
+#include "utilities.h"
+
+#include <iostream>
+
+static bool opt_binary= false;
+static int opt_verbose= 0;
+static time_t opt_expire= 0;
+static char *opt_servers= NULL;
+static char *opt_username;
+static char *opt_passwd;
+
+#define PROGRAM_NAME "memping"
+#define PROGRAM_DESCRIPTION "Ping a server to see if it is alive"
+
+/* Prototypes */
+void options_parse(int argc, char *argv[]);
+
+int main(int argc, char *argv[])
+{
+  options_parse(argc, argv);
+
+  if (opt_servers == NULL)
+  {
+    char *temp;
+
+    if ((temp= getenv("MEMCACHED_SERVERS")))
+    {
+      opt_servers= strdup(temp);
+    }
+    
+    if (opt_servers == NULL)
+    {
+      std::cerr << "No Servers provided" << std::endl;
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  int exit_code= EXIT_SUCCESS;
+  memcached_server_st *servers= memcached_servers_parse(opt_servers);
+  if (servers == NULL or memcached_server_list_count(servers) == 0)
+  {
+    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
+    exit_code= EXIT_FAILURE;
+  }
+  else
+  {
+    for (uint32_t x= 0; x < memcached_server_list_count(servers); x++)
+    {
+      memcached_return_t instance_rc;
+      const char *hostname= servers[x].hostname;
+      in_port_t port= servers[x].port;
+
+      if (opt_verbose)
+      {
+        std::cout << "Trying to ping " << hostname << ":" << port << std::endl;
+      }
+
+      if (libmemcached_util_ping2(hostname, port, opt_username, opt_passwd, &instance_rc) == false)
+      {
+        std::cerr << "Failed to ping " << hostname << ":" << port << " " << memcached_strerror(NULL, instance_rc) <<  std::endl;
+        exit_code= EXIT_FAILURE;
+      }
+    }
+  }
+  memcached_server_list_free(servers);
+
+  free(opt_servers);
+
+  return exit_code;
+}
+
+
+void options_parse(int argc, char *argv[])
+{
+  memcached_programs_help_st help_options[]=
+  {
+    {0},
+  };
+
+  static struct option long_options[]=
+  {
+    {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+    {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+    {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+    {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
+    {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+    {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
+    {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
+    {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+    {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
+    {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
+    {0, 0, 0, 0},
+  };
+
+  bool opt_version= false;
+  bool opt_help= false;
+  int option_index= 0;
+  while (1)
+  {
+    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+
+    if (option_rv == -1) break;
+
+    switch (option_rv)
+    {
+    case 0:
+      break;
+
+    case OPT_BINARY:
+      opt_binary= true;
+      break;
+
+    case OPT_VERBOSE: /* --verbose or -v */
+      opt_verbose = OPT_VERBOSE;
+      break;
+
+    case OPT_DEBUG: /* --debug or -d */
+      opt_verbose = OPT_DEBUG;
+      break;
+
+    case OPT_VERSION: /* --version or -V */
+      version_command(PROGRAM_NAME);
+      break;
+
+    case OPT_HELP: /* --help or -h */
+      help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
+      break;
+
+    case OPT_SERVERS: /* --servers or -s */
+      opt_servers= strdup(optarg);
+      break;
+
+    case OPT_EXPIRE: /* --expire */
+      errno= 0;
+      opt_expire= time_t(strtoll(optarg, (char **)NULL, 10));
+      if (errno != 0)
+      {
+        std::cerr << "Incorrect value passed to --expire: `" << optarg << "`" << std::endl;
+        exit(EXIT_FAILURE);
+      }
+      break;
+
+    case OPT_USERNAME:
+      opt_username= optarg;
+      opt_binary= true;
+      break;
+
+    case OPT_PASSWD:
+      opt_passwd= optarg;
+      break;
+
+    case OPT_QUIET:
+      close_stdio();
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(1);
+    default:
+      abort();
+    }
+  }
+
+  if (opt_version)
+  {
+    version_command(PROGRAM_NAME);
+    exit(EXIT_SUCCESS);
+  }
+
+  if (opt_help)
+  {
+    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
+    exit(EXIT_SUCCESS);
+  }
+}
diff --git a/src/bin/memping.sh b/src/bin/memping.sh
new file mode 100755 (executable)
index 0000000..09f09b8
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+src/bin/memping -v --servers localhost
diff --git a/src/bin/memrm.cc b/src/bin/memrm.cc
new file mode 100644 (file)
index 0000000..50ead7a
--- /dev/null
@@ -0,0 +1,257 @@
+/* LibMemcached
+ * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+#include "mem_config.h"
+
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <getopt.h>
+#include <iostream>
+#include <unistd.h>
+
+#include <libmemcached-1.0/memcached.h>
+#include "client_options.h"
+#include "utilities.h"
+
+static int opt_binary= 0;
+static int opt_verbose= 0;
+static time_t opt_expire= 0;
+static char *opt_servers= NULL;
+static char *opt_hash= NULL;
+static char *opt_username;
+static char *opt_passwd;
+
+#define PROGRAM_NAME "memrm"
+#define PROGRAM_DESCRIPTION "Erase a key or set of keys from a memcached cluster."
+
+/* Prototypes */
+static void options_parse(int argc, char *argv[]);
+
+int main(int argc, char *argv[])
+{
+  options_parse(argc, argv);
+  initialize_sockets();
+
+  if (opt_servers == NULL)
+  {
+    char *temp;
+
+    if ((temp= getenv("MEMCACHED_SERVERS")))
+    {
+      opt_servers= strdup(temp);
+    }
+
+    if (opt_servers == NULL)
+    {
+      std::cerr << "No Servers provided" << std::endl;
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  memcached_server_st* servers= memcached_servers_parse(opt_servers);
+  if (servers == NULL or memcached_server_list_count(servers) == 0)
+  {
+    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  memcached_st* memc= memcached_create(NULL);
+  process_hash_option(memc, opt_hash);
+
+  memcached_server_push(memc, servers);
+  memcached_server_list_free(servers);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
+                         (uint64_t) opt_binary);
+
+  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    memcached_free(memc);
+    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  if (opt_username)
+  {
+    memcached_return_t ret;
+    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
+    {
+      std::cerr << memcached_last_error_message(memc) << std::endl;
+      memcached_free(memc);
+      return EXIT_FAILURE;
+    }
+  }
+
+  int return_code= EXIT_SUCCESS;
+
+  while (optind < argc)
+  {
+    memcached_return_t rc= memcached_delete(memc, argv[optind], strlen(argv[optind]), opt_expire);
+
+    if (rc == MEMCACHED_NOTFOUND)
+    {
+      if (opt_verbose)
+      {
+        std::cerr << "Could not find key \"" << argv[optind] << "\"" << std::endl;
+      }
+    }
+    else if (memcached_fatal(rc))
+    {
+      if (opt_verbose)
+      {
+        std::cerr << "Failed to delete key \"" << argv[optind] << "\" :" <<  memcached_last_error_message(memc) << std::endl;
+      }
+
+      return_code= EXIT_FAILURE;
+    }
+    else // success
+    {
+      if (opt_verbose)
+      {
+        std::cout << "Deleted key " << argv[optind];
+        if (opt_expire)
+        {
+          std::cout << " expires: " << opt_expire << std::endl;
+        }
+        std::cout << std::endl;
+      }
+    }
+
+    optind++;
+  }
+
+  memcached_free(memc);
+
+  if (opt_servers)
+  {
+    free(opt_servers);
+  }
+
+  if (opt_hash)
+  {
+    free(opt_hash);
+  }
+
+  return return_code;
+}
+
+
+static void options_parse(int argc, char *argv[])
+{
+  memcached_programs_help_st help_options[]=
+  {
+    {0},
+  };
+
+  static struct option long_options[]=
+  {
+    {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+    {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+    {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+    {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
+    {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+    {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
+    {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
+    {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
+    {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+    {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
+    {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
+    {0, 0, 0, 0},
+  };
+
+  bool opt_version= false;
+  bool opt_help= false;
+  int option_index= 0;
+
+  while (1)
+  {
+    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+    if (option_rv == -1) 
+    {
+      break;
+    }
+
+    switch (option_rv)
+    {
+    case 0:
+      break;
+
+    case OPT_BINARY:
+      opt_binary = 1;
+      break;
+
+    case OPT_VERBOSE: /* --verbose or -v */
+      opt_verbose = OPT_VERBOSE;
+      break;
+
+    case OPT_DEBUG: /* --debug or -d */
+      opt_verbose = OPT_DEBUG;
+      break;
+
+    case OPT_VERSION: /* --version or -V */
+      opt_version= true;
+      break;
+
+    case OPT_HELP: /* --help or -h */
+      opt_help= true;
+      break;
+
+    case OPT_SERVERS: /* --servers or -s */
+      opt_servers= strdup(optarg);
+      break;
+
+    case OPT_EXPIRE: /* --expire */
+      errno= 0;
+      opt_expire= (time_t)strtoll(optarg, (char **)NULL, 10);
+      if (errno != 0)
+      {
+        std::cerr << "Incorrect value passed to --expire: `" << optarg << "`" << std::endl;
+        exit(EXIT_FAILURE);
+      }
+      break;
+
+    case OPT_HASH:
+      opt_hash= strdup(optarg);
+      break;
+
+    case OPT_USERNAME:
+      opt_username= optarg;
+      break;
+
+    case OPT_PASSWD:
+      opt_passwd= optarg;
+      break;
+
+    case OPT_QUIET:
+      close_stdio();
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(EXIT_SUCCESS);
+
+    default:
+      abort();
+    }
+  }
+
+  if (opt_version)
+  {
+    version_command(PROGRAM_NAME);
+    exit(EXIT_SUCCESS);
+  }
+
+  if (opt_help)
+  {
+    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
+    exit(EXIT_SUCCESS);
+  }
+}
diff --git a/src/bin/memrm.sh b/src/bin/memrm.sh
new file mode 100755 (executable)
index 0000000..40b63d9
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+src/bin/memcp.sh
+src/bin/memrm -v --servers localhost mem.testdata
diff --git a/src/bin/memslap.cc b/src/bin/memslap.cc
new file mode 100644 (file)
index 0000000..9bc4f23
--- /dev/null
@@ -0,0 +1,577 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <mem_config.h>
+
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <fcntl.h>
+#include <getopt.h>
+#include <memory>
+#include <pthread.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <iostream>
+
+#include <libmemcached-1.0/memcached.h>
+
+#include "client_options.h"
+#include "utilities.h"
+#include "generator.h"
+#include "execute.h"
+
+#define DEFAULT_INITIAL_LOAD 10000
+#define DEFAULT_EXECUTE_NUMBER 10000
+#define DEFAULT_CONCURRENCY 1
+
+#define VALUE_BYTES 4096
+
+#define PROGRAM_NAME "memslap"
+#define PROGRAM_DESCRIPTION "Generates a load against a memcached custer of servers."
+
+/* Global Thread counter */
+volatile unsigned int master_wakeup;
+pthread_mutex_t sleeper_mutex;
+pthread_cond_t sleep_threshhold;
+
+/* Types */
+enum test_t {
+  SET_TEST,
+  GET_TEST,
+  MGET_TEST
+};
+
+struct thread_context_st {
+  unsigned int key_count;
+  pairs_st *initial_pairs;
+  unsigned int initial_number;
+  pairs_st *execute_pairs;
+  unsigned int execute_number;
+  char **keys;
+  size_t *key_lengths;
+  test_t test;
+  memcached_st *memc;
+  const memcached_st* root;
+
+  thread_context_st(const memcached_st* memc_arg, test_t test_arg) :
+    key_count(0),
+    initial_pairs(NULL),
+    initial_number(0),
+    execute_pairs(NULL),
+    execute_number(0),
+    keys(0),
+    key_lengths(NULL),
+    test(test_arg),
+    memc(NULL),
+    root(memc_arg)
+  {
+  }
+
+  void init()
+  {
+    memc= memcached_clone(NULL, root);
+  }
+
+  ~thread_context_st()
+  {
+    if (execute_pairs)
+    {
+      pairs_free(execute_pairs);
+    }
+    memcached_free(memc);
+  }
+};
+
+struct conclusions_st {
+  long int load_time;
+  long int read_time;
+  unsigned int rows_loaded;
+  unsigned int rows_read;
+
+  conclusions_st() :
+    load_time(0),
+    read_time(0),
+    rows_loaded(0),
+    rows_read()
+  { }
+};
+
+/* Prototypes */
+void options_parse(int argc, char *argv[]);
+void conclusions_print(conclusions_st *conclusion);
+void scheduler(memcached_server_st *servers, conclusions_st *conclusion);
+pairs_st *load_create_data(memcached_st *memc, unsigned int number_of,
+                           unsigned int *actual_loaded);
+void flush_all(memcached_st *memc);
+
+static bool opt_binary= 0;
+static int opt_verbose= 0;
+static int opt_flush= 0;
+static int opt_non_blocking_io= 0;
+static int opt_tcp_nodelay= 0;
+static unsigned int opt_execute_number= 0;
+static unsigned int opt_createial_load= 0;
+static unsigned int opt_concurrency= 0;
+static int opt_displayflag= 0;
+static char *opt_servers= NULL;
+static bool opt_udp_io= false;
+test_t opt_test= SET_TEST;
+
+extern "C" {
+
+static __attribute__((noreturn)) void *run_task(void *p)
+{
+  thread_context_st *context= (thread_context_st *)p;
+
+  context->init();
+
+  pthread_mutex_lock(&sleeper_mutex);
+  while (master_wakeup)
+  {
+    pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
+  }
+  pthread_mutex_unlock(&sleeper_mutex);
+
+  /* Do Stuff */
+  switch (context->test)
+  {
+  case SET_TEST:
+    assert(context->execute_pairs);
+    execute_set(context->memc, context->execute_pairs, context->execute_number);
+    break;
+
+  case GET_TEST:
+    execute_get(context->memc, context->initial_pairs, context->initial_number);
+    break;
+
+  case MGET_TEST:
+    execute_mget(context->memc, (const char*const*)context->keys, context->key_lengths, context->initial_number);
+    break;
+  }
+
+  delete context;
+
+  pthread_exit(0);
+}
+
+}
+
+
+int main(int argc, char *argv[])
+{
+  conclusions_st conclusion;
+
+  srandom((unsigned int)time(NULL));
+  options_parse(argc, argv);
+
+  if (opt_servers == NULL)
+  {
+    char *temp;
+
+    if ((temp= getenv("MEMCACHED_SERVERS")))
+    {
+      opt_servers= strdup(temp);
+    }
+    
+    if (opt_servers == NULL)
+    {
+      std::cerr << "No Servers provided" << std::endl;
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  memcached_server_st *servers= memcached_servers_parse(opt_servers);
+  if (servers == NULL or memcached_server_list_count(servers) == 0)
+  {
+    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  pthread_mutex_init(&sleeper_mutex, NULL);
+  pthread_cond_init(&sleep_threshhold, NULL);
+
+  int error_code= EXIT_SUCCESS;
+  try {
+    scheduler(servers, &conclusion);
+  }
+  catch(std::exception& e)
+  {
+    std::cerr << "Died with exception: " << e.what() << std::endl;
+    error_code= EXIT_FAILURE;
+  }
+
+  free(opt_servers);
+
+  (void)pthread_mutex_destroy(&sleeper_mutex);
+  (void)pthread_cond_destroy(&sleep_threshhold);
+  conclusions_print(&conclusion);
+  memcached_server_list_free(servers);
+
+  return error_code;
+}
+
+void scheduler(memcached_server_st *servers, conclusions_st *conclusion)
+{
+  unsigned int actual_loaded= 0; /* Fix warning */
+
+  struct timeval start_time, end_time;
+  pairs_st *pairs= NULL;
+
+  memcached_st *memc= memcached_create(NULL);
+
+  memcached_server_push(memc, servers);
+
+  /* We need to set udp behavior before adding servers to the client */
+  if (opt_udp_io)
+  {
+    if (memcached_failed(memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, opt_udp_io)))
+    {
+      std::cerr << "Failed to enable UDP." << std::endl;
+      memcached_free(memc);
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
+                         (uint64_t)opt_binary);
+
+  if (opt_flush)
+  {
+    flush_all(memc);
+  }
+
+  if (opt_createial_load)
+  {
+    pairs= load_create_data(memc, opt_createial_load, &actual_loaded);
+  }
+
+  char **keys= static_cast<char **>(calloc(actual_loaded, sizeof(char*)));
+  size_t *key_lengths= static_cast<size_t *>(calloc(actual_loaded, sizeof(size_t)));
+
+  if (keys == NULL or key_lengths == NULL)
+  {
+    free(keys);
+    free(key_lengths);
+    keys= NULL;
+    key_lengths= NULL;
+  }
+  else
+  {
+    for (uint32_t x= 0; x < actual_loaded; ++x)
+    {
+      keys[x]= pairs[x].key;
+      key_lengths[x]= pairs[x].key_length;
+    }
+  }
+
+  /* We set this after we have loaded */
+  {
+    if (opt_non_blocking_io)
+      memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 1);
+
+    if (opt_tcp_nodelay)
+      memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, 1);
+  }
+
+  pthread_mutex_lock(&sleeper_mutex);
+  master_wakeup= 1;
+  pthread_mutex_unlock(&sleeper_mutex);
+
+  pthread_t *threads= new  (std::nothrow) pthread_t[opt_concurrency];
+
+  if (threads == NULL)
+  {
+    exit(EXIT_FAILURE);
+  }
+
+  for (uint32_t x= 0; x < opt_concurrency; x++)
+  {
+    thread_context_st *context= new thread_context_st(memc, opt_test);
+    context->test= opt_test;
+
+    context->initial_pairs= pairs;
+    context->initial_number= actual_loaded;
+    context->keys= keys;
+    context->key_lengths= key_lengths;
+
+    if (opt_test == SET_TEST)
+    {
+      context->execute_pairs= pairs_generate(opt_execute_number, VALUE_BYTES);
+      context->execute_number= opt_execute_number;
+    }
+
+    /* now you create the thread */
+    if (pthread_create(threads +x, NULL, run_task, (void *)context) != 0)
+    {
+      fprintf(stderr,"Could not create thread\n");
+      exit(1);
+    }
+  }
+
+  pthread_mutex_lock(&sleeper_mutex);
+  master_wakeup= 0;
+  pthread_mutex_unlock(&sleeper_mutex);
+  pthread_cond_broadcast(&sleep_threshhold);
+  gettimeofday(&start_time, NULL);
+
+  for (uint32_t x= 0; x < opt_concurrency; x++)
+  {
+    void *retval;
+    pthread_join(threads[x], &retval);
+  }
+  delete [] threads;
+
+  gettimeofday(&end_time, NULL);
+
+  conclusion->load_time= timedif(end_time, start_time);
+  conclusion->read_time= timedif(end_time, start_time);
+  free(keys);
+  free(key_lengths);
+  pairs_free(pairs);
+  memcached_free(memc);
+}
+
+void options_parse(int argc, char *argv[])
+{
+  memcached_programs_help_st help_options[]=
+  {
+    {0},
+  };
+
+  static struct option long_options[]=
+    {
+      {(OPTIONSTRING)"concurrency", required_argument, NULL, OPT_SLAP_CONCURRENCY},
+      {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+      {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+      {(OPTIONSTRING)"execute-number", required_argument, NULL, OPT_SLAP_EXECUTE_NUMBER},
+      {(OPTIONSTRING)"flag", no_argument, &opt_displayflag, OPT_FLAG},
+      {(OPTIONSTRING)"flush", no_argument, &opt_flush, OPT_FLUSH},
+      {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+      {(OPTIONSTRING)"initial-load", required_argument, NULL, OPT_SLAP_INITIAL_LOAD}, /* Number to load initially */
+      {(OPTIONSTRING)"non-blocking", no_argument, &opt_non_blocking_io, OPT_SLAP_NON_BLOCK},
+      {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
+      {(OPTIONSTRING)"tcp-nodelay", no_argument, &opt_tcp_nodelay, OPT_SLAP_TCP_NODELAY},
+      {(OPTIONSTRING)"test", required_argument, NULL, OPT_SLAP_TEST},
+      {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
+      {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+      {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+      {(OPTIONSTRING)"udp", no_argument, NULL, OPT_UDP},
+      {0, 0, 0, 0},
+    };
+
+  bool opt_help= false;
+  bool opt_version= false;
+  int option_index= 0;
+  while (1)
+  {
+    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+
+    if (option_rv == -1) break;
+
+    switch (option_rv)
+    {
+    case 0:
+      break;
+
+    case OPT_UDP:
+      if (opt_test == GET_TEST)
+      {
+        fprintf(stderr, "You can not run a get test in UDP mode. UDP mode "
+                  "does not currently support get ops.\n");
+        exit(1);
+      }
+      opt_udp_io= true;
+      break;
+
+    case OPT_BINARY:
+      opt_binary= true;
+      break;
+
+    case OPT_VERBOSE: /* --verbose or -v */
+      opt_verbose= OPT_VERBOSE;
+      break;
+
+    case OPT_DEBUG: /* --debug or -d */
+      opt_verbose= OPT_DEBUG;
+      break;
+
+    case OPT_VERSION: /* --version or -V */
+      opt_version= true;
+      break;
+
+    case OPT_HELP: /* --help or -h */
+      opt_help= true;
+      break;
+
+    case OPT_SERVERS: /* --servers or -s */
+      opt_servers= strdup(optarg);
+      break;
+
+    case OPT_SLAP_TEST:
+      if (strcmp(optarg, "get") == 0)
+      {
+        if (opt_udp_io == 1)
+        {
+          fprintf(stderr, "You can not run a get test in UDP mode. UDP mode "
+                  "does not currently support get ops.\n");
+          exit(EXIT_FAILURE);
+        }
+        opt_test= GET_TEST ;
+      }
+      else if (strcmp(optarg, "set") == 0)
+      {
+        opt_test= SET_TEST;
+      }
+      else if (strcmp(optarg, "mget") == 0)
+      {
+        opt_test= MGET_TEST;
+      }
+      else
+      {
+        fprintf(stderr, "Your test, %s, is not a known test\n", optarg);
+        exit(EXIT_FAILURE);
+      }
+      break;
+
+    case OPT_SLAP_CONCURRENCY:
+      errno= 0;
+      opt_concurrency= (unsigned int)strtoul(optarg, (char **)NULL, 10);
+      if (errno != 0)
+      {
+        fprintf(stderr, "Invalid value for concurrency: %s\n", optarg);
+        exit(EXIT_FAILURE);
+      }
+      break;
+
+    case OPT_SLAP_EXECUTE_NUMBER:
+      errno= 0;
+      opt_execute_number= (unsigned int)strtoul(optarg, (char **)NULL, 10);
+      if (errno != 0)
+      {
+        fprintf(stderr, "Invalid value for execute: %s\n", optarg);
+        exit(EXIT_FAILURE);
+      }
+      break;
+
+    case OPT_SLAP_INITIAL_LOAD:
+      errno= 0;
+      opt_createial_load= (unsigned int)strtoul(optarg, (char **)NULL, 10);
+      if (errno != 0)
+      {
+        fprintf(stderr, "Invalid value for initial load: %s\n", optarg);
+        exit(EXIT_FAILURE);
+      }
+      break;
+
+    case OPT_QUIET:
+      close_stdio();
+      break;
+
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(EXIT_FAILURE);
+
+    default:
+      abort();
+    }
+  }
+
+  if (opt_version)
+  {
+    version_command(PROGRAM_NAME);
+    exit(EXIT_SUCCESS);
+  }
+
+  if (opt_help)
+  {
+    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
+    exit(EXIT_SUCCESS);
+  }
+
+  if ((opt_test == GET_TEST or opt_test == MGET_TEST) and opt_createial_load == 0)
+    opt_createial_load= DEFAULT_INITIAL_LOAD;
+
+  if (opt_execute_number == 0)
+    opt_execute_number= DEFAULT_EXECUTE_NUMBER;
+
+  if (opt_concurrency == 0)
+    opt_concurrency= DEFAULT_CONCURRENCY;
+}
+
+void conclusions_print(conclusions_st *conclusion)
+{
+  printf("\tThreads connecting to servers %u\n", opt_concurrency);
+#ifdef NOT_FINISHED
+  printf("\tLoaded %u rows\n", conclusion->rows_loaded);
+  printf("\tRead %u rows\n", conclusion->rows_read);
+#endif
+  if (opt_test == SET_TEST)
+    printf("\tTook %ld.%03ld seconds to load data\n", conclusion->load_time / 1000,
+           conclusion->load_time % 1000);
+  else
+    printf("\tTook %ld.%03ld seconds to read data\n", conclusion->read_time / 1000,
+           conclusion->read_time % 1000);
+}
+
+void flush_all(memcached_st *memc)
+{
+  memcached_flush(memc, 0);
+}
+
+pairs_st *load_create_data(memcached_st *memc, unsigned int number_of,
+                           unsigned int *actual_loaded)
+{
+  memcached_st *memc_clone= memcached_clone(NULL, memc);
+  /* We always used non-blocking IO for load since it is faster */
+  memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_NO_BLOCK, 0);
+
+  pairs_st *pairs= pairs_generate(number_of, VALUE_BYTES);
+  *actual_loaded= execute_set(memc_clone, pairs, number_of);
+
+  memcached_free(memc_clone);
+
+  return pairs;
+}
diff --git a/src/bin/memslap.sh b/src/bin/memslap.sh
new file mode 100755 (executable)
index 0000000..e80cc11
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+src/bin/memslap -v --servers localhost
diff --git a/src/bin/memstat.cc b/src/bin/memstat.cc
new file mode 100644 (file)
index 0000000..e5bac91
--- /dev/null
@@ -0,0 +1,465 @@
+/* LibMemcached
+ * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ * Authors: 
+ *          Brian Aker
+ *          Toru Maesaka
+ */
+#include <mem_config.h>
+
+#include <cstdio>
+#include <cstring>
+#include <ctime>
+#include <iostream>
+#include <fcntl.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/types.h>
+
+#include <libmemcached-1.0/memcached.h>
+
+#include "client_options.h"
+#include "utilities.h"
+
+#define PROGRAM_NAME "memstat"
+#define PROGRAM_DESCRIPTION "Output the state of a memcached cluster."
+
+/* Prototypes */
+static void options_parse(int argc, char *argv[]);
+static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat);
+static void print_analysis_report(memcached_st *memc,
+                                  memcached_analysis_st *report);
+
+static bool opt_binary= false;
+static bool opt_verbose= false;
+static bool opt_server_version= false;
+static bool opt_analyze= false;
+static char *opt_servers= NULL;
+static char *stat_args= NULL;
+static char *analyze_mode= NULL;
+static char *opt_username;
+static char *opt_passwd;
+
+static struct option long_options[]=
+{
+  {(OPTIONSTRING)"args", required_argument, NULL, OPT_STAT_ARGS},
+  {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+  {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+  {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+  {(OPTIONSTRING)"verbose", no_argument, NULL, OPT_VERBOSE},
+  {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+  {(OPTIONSTRING)"debug", no_argument, NULL, OPT_DEBUG},
+  {(OPTIONSTRING)"server-version", no_argument, NULL, OPT_SERVER_VERSION},
+  {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
+  {(OPTIONSTRING)"analyze", optional_argument, NULL, OPT_ANALYZE},
+  {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
+  {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
+  {0, 0, 0, 0},
+};
+
+
+static memcached_return_t stat_printer(const memcached_instance_st * instance,
+                                       const char *key, size_t key_length,
+                                       const char *value, size_t value_length,
+                                       void *context)
+{
+  static const memcached_instance_st * last= NULL;
+  (void)context;
+
+  if (last != instance)
+  {
+    printf("Server: %s (%u)\n", memcached_server_name(instance),
+           (uint32_t)memcached_server_port(instance));
+    last= instance;
+  }
+
+  printf("\t %.*s: %.*s\n", (int)key_length, key, (int)value_length, value);
+
+  return MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t server_print_callback(const memcached_st *,
+                                                const memcached_instance_st * instance,
+                                                void *)
+{
+  std::cerr << memcached_server_name(instance) << ":" << memcached_server_port(instance) <<
+    " " << int(memcached_server_major_version(instance)) << 
+    "." << int(memcached_server_minor_version(instance)) << 
+    "." << int(memcached_server_micro_version(instance)) << std::endl;
+
+  return MEMCACHED_SUCCESS;
+}
+
+int main(int argc, char *argv[])
+{
+  options_parse(argc, argv);
+  initialize_sockets();
+
+  if (opt_servers == NULL)
+  {
+    char *temp;
+    if ((temp= getenv("MEMCACHED_SERVERS")))
+    {
+      opt_servers= strdup(temp);
+    }
+
+    if (opt_servers == NULL)
+    {
+      std::cerr << "No Servers provided" << std::endl;
+      return EXIT_FAILURE;
+    }
+  }
+
+  memcached_server_st* servers= memcached_servers_parse(opt_servers);
+  if (servers == NULL or memcached_server_list_count(servers) == 0)
+  {
+    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
+    return EXIT_FAILURE;
+  }
+  
+  if (opt_servers)
+  {
+    free(opt_servers);
+  }
+
+  memcached_st *memc= memcached_create(NULL);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, opt_binary);
+
+  memcached_return_t rc= memcached_server_push(memc, servers);
+  memcached_server_list_free(servers);
+
+  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    memcached_free(memc);
+    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  if (opt_username)
+  {
+    memcached_return_t ret;
+    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
+    {
+      std::cerr << memcached_last_error_message(memc) << std::endl;
+      memcached_free(memc);
+      return EXIT_FAILURE;
+    }
+  }
+
+  if (rc != MEMCACHED_SUCCESS and rc != MEMCACHED_SOME_ERRORS)
+  {
+    printf("Failure to communicate with servers (%s)\n",
+           memcached_strerror(memc, rc));
+    exit(EXIT_FAILURE);
+  }
+
+  if (opt_server_version)
+  {
+    if (memcached_failed(memcached_version(memc)))
+    {
+      std::cerr << "Unable to obtain server version";
+      exit(EXIT_FAILURE);
+    }
+
+    memcached_server_fn callbacks[1];
+    callbacks[0]= server_print_callback;
+    memcached_server_cursor(memc, callbacks, NULL,  1);
+  }
+  else if (opt_analyze)
+  {
+    memcached_stat_st *memc_stat= memcached_stat(memc, NULL, &rc);
+
+    if (memc_stat == NULL)
+    {
+      exit(EXIT_FAILURE);
+    }
+
+    run_analyzer(memc, memc_stat);
+
+    memcached_stat_free(memc, memc_stat);
+  }
+  else
+  {
+    rc= memcached_stat_execute(memc, stat_args, stat_printer, NULL);
+  }
+
+  memcached_free(memc);
+
+  return rc == MEMCACHED_SUCCESS ? EXIT_SUCCESS: EXIT_FAILURE;
+}
+
+static void run_analyzer(memcached_st *memc, memcached_stat_st *memc_stat)
+{
+  memcached_return_t rc;
+
+  if (analyze_mode == NULL)
+  {
+    memcached_analysis_st *report;
+    report= memcached_analyze(memc, memc_stat, &rc);
+    if (rc != MEMCACHED_SUCCESS || report == NULL)
+    {
+      printf("Failure to analyze servers (%s)\n",
+             memcached_strerror(memc, rc));
+      exit(1);
+    }
+    print_analysis_report(memc, report);
+    free(report);
+  }
+  else if (strcmp(analyze_mode, "latency") == 0)
+  {
+    uint32_t flags, server_count= memcached_server_count(memc);
+    uint32_t num_of_tests= 32;
+    const char *test_key= "libmemcached_test_key";
+
+    memcached_st **servers= static_cast<memcached_st**>(malloc(sizeof(memcached_st*) * server_count));
+    if (servers == NULL)
+    {
+      fprintf(stderr, "Failed to allocate memory\n");
+      return;
+    }
+
+    for (uint32_t x= 0; x < server_count; x++)
+    {
+      const memcached_instance_st * instance=
+        memcached_server_instance_by_position(memc, x);
+
+      if ((servers[x]= memcached_create(NULL)) == NULL)
+      {
+        fprintf(stderr, "Failed to memcached_create()\n");
+        if (x > 0)
+        {
+          memcached_free(servers[0]);
+        }
+        x--;
+
+        for (; x > 0; x--)
+        {
+          memcached_free(servers[x]);
+        }
+
+        free(servers);
+
+        return;
+      }
+      memcached_server_add(servers[x],
+                           memcached_server_name(instance),
+                           memcached_server_port(instance));
+    }
+
+    printf("Network Latency Test:\n\n");
+    struct timeval start_time, end_time;
+    uint32_t slowest_server= 0;
+    long elapsed_time, slowest_time= 0;
+
+    for (uint32_t x= 0; x < server_count; x++)
+    {
+      const memcached_instance_st * instance=
+        memcached_server_instance_by_position(memc, x);
+      gettimeofday(&start_time, NULL);
+
+      for (uint32_t y= 0; y < num_of_tests; y++)
+      {
+        size_t vlen;
+        char *val= memcached_get(servers[x], test_key, strlen(test_key),
+                                 &vlen, &flags, &rc);
+        if (rc != MEMCACHED_NOTFOUND and rc != MEMCACHED_SUCCESS)
+        {
+          break;
+        }
+        free(val);
+      }
+      gettimeofday(&end_time, NULL);
+
+      elapsed_time= (long) timedif(end_time, start_time);
+      elapsed_time /= (long) num_of_tests;
+
+      if (elapsed_time > slowest_time)
+      {
+        slowest_server= x;
+        slowest_time= elapsed_time;
+      }
+
+      if (rc != MEMCACHED_NOTFOUND && rc != MEMCACHED_SUCCESS)
+      {
+        printf("\t %s (%d)  =>  failed to reach the server\n",
+               memcached_server_name(instance),
+               memcached_server_port(instance));
+      }
+      else
+      {
+        printf("\t %s (%d)  =>  %ld.%ld seconds\n",
+               memcached_server_name(instance),
+               memcached_server_port(instance),
+               elapsed_time / 1000, elapsed_time % 1000);
+      }
+    }
+
+    if (server_count > 1 && slowest_time > 0)
+    {
+      const memcached_instance_st * slowest=
+        memcached_server_instance_by_position(memc, slowest_server);
+
+      printf("---\n");
+      printf("Slowest Server: %s (%d) => %ld.%ld seconds\n",
+             memcached_server_name(slowest),
+             memcached_server_port(slowest),
+             slowest_time / 1000, slowest_time % 1000);
+    }
+    printf("\n");
+
+    for (uint32_t x= 0; x < server_count; x++)
+    {
+      memcached_free(servers[x]);
+    }
+
+    free(servers);
+    free(analyze_mode);
+  }
+  else
+  {
+    fprintf(stderr, "Invalid Analyzer Option provided\n");
+    free(analyze_mode);
+  }
+}
+
+static void print_analysis_report(memcached_st *memc,
+                                  memcached_analysis_st *report)
+                                  
+{
+  uint32_t server_count= memcached_server_count(memc);
+  const memcached_instance_st * most_consumed_server= memcached_server_instance_by_position(memc, report->most_consumed_server);
+  const memcached_instance_st * least_free_server= memcached_server_instance_by_position(memc, report->least_free_server);
+  const memcached_instance_st * oldest_server= memcached_server_instance_by_position(memc, report->oldest_server);
+
+  printf("Memcached Cluster Analysis Report\n\n");
+
+  printf("\tNumber of Servers Analyzed         : %u\n", server_count);
+  printf("\tAverage Item Size (incl/overhead)  : %u bytes\n",
+         report->average_item_size);
+
+  if (server_count == 1)
+  {
+    printf("\nFor a detailed report, you must supply multiple servers.\n");
+    return;
+  }
+
+  printf("\n");
+  printf("\tNode with most memory consumption  : %s:%u (%llu bytes)\n",
+         memcached_server_name(most_consumed_server),
+         (uint32_t)memcached_server_port(most_consumed_server),
+         (unsigned long long)report->most_used_bytes);
+  printf("\tNode with least free space         : %s:%u (%llu bytes remaining)\n",
+         memcached_server_name(least_free_server),
+         (uint32_t)memcached_server_port(least_free_server),
+         (unsigned long long)report->least_remaining_bytes);
+  printf("\tNode with longest uptime           : %s:%u (%us)\n",
+         memcached_server_name(oldest_server),
+         (uint32_t)memcached_server_port(oldest_server),
+         report->longest_uptime);
+  printf("\tPool-wide Hit Ratio                : %1.f%%\n", report->pool_hit_ratio);
+  printf("\n");
+}
+
+static void options_parse(int argc, char *argv[])
+{
+  memcached_programs_help_st help_options[]=
+  {
+    {0},
+  };
+
+  int option_index= 0;
+
+  bool opt_version= false;
+  bool opt_help= false;
+  while (1) 
+  {
+    int option_rv= getopt_long(argc, argv, "Vhvds:a", long_options, &option_index);
+
+    if (option_rv == -1)
+      break;
+
+    switch (option_rv)
+    {
+    case 0:
+      break;
+
+    case OPT_VERBOSE: /* --verbose or -v */
+      opt_verbose= true;
+      break;
+
+    case OPT_DEBUG: /* --debug or -d */
+      opt_verbose= true;
+      break;
+
+    case OPT_BINARY:
+      opt_binary= true;
+      break;
+
+    case OPT_SERVER_VERSION:
+      opt_server_version= true;
+      break;
+
+    case OPT_VERSION: /* --version or -V */
+      opt_version= true;
+      break;
+
+    case OPT_HELP: /* --help or -h */
+      opt_help= true;
+      break;
+
+    case OPT_SERVERS: /* --servers or -s */
+      opt_servers= strdup(optarg);
+      break;
+
+    case OPT_STAT_ARGS:
+      stat_args= strdup(optarg);
+      break;
+
+    case OPT_ANALYZE: /* --analyze or -a */
+      opt_analyze= true;
+      analyze_mode= (optarg) ? strdup(optarg) : NULL;
+      break;
+
+    case OPT_QUIET:
+      close_stdio();
+      break;
+
+    case OPT_USERNAME:
+      opt_username= optarg;
+      opt_binary= true;
+      break;
+
+    case OPT_PASSWD:
+      opt_passwd= optarg;
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(1);
+    default:
+      abort();
+    }
+  }
+
+  if (opt_version)
+  {
+    version_command(PROGRAM_NAME);
+    exit(EXIT_SUCCESS);
+  }
+
+  if (opt_help)
+  {
+    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
+    exit(EXIT_SUCCESS);
+  }
+}
diff --git a/src/bin/memstat.sh b/src/bin/memstat.sh
new file mode 100755 (executable)
index 0000000..cadaf36
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/bash
+src/bin/memstat -v --servers localhost
diff --git a/src/bin/memtouch.cc b/src/bin/memtouch.cc
new file mode 100644 (file)
index 0000000..09e0c92
--- /dev/null
@@ -0,0 +1,256 @@
+/* LibMemcached
+ * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+#include <mem_config.h>
+
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
+#include <getopt.h>
+#include <iostream>
+#include <unistd.h>
+
+#include <libmemcached-1.0/memcached.h>
+
+#include "utilities.h"
+
+#define PROGRAM_NAME "memtouch"
+#define PROGRAM_DESCRIPTION "Update the expiration value of an already existing value in the server"
+
+
+/* Prototypes */
+void options_parse(int argc, char *argv[]);
+
+static int opt_binary= 0;
+static int opt_verbose= 0;
+static char *opt_servers= NULL;
+static char *opt_hash= NULL;
+static char *opt_username;
+static char *opt_passwd;
+
+time_t expiration= 0;
+
+int main(int argc, char *argv[])
+{
+  int return_code= EXIT_SUCCESS;
+
+  options_parse(argc, argv);
+  initialize_sockets();
+
+  if (opt_servers == NULL)
+  {
+    char *temp;
+
+    if ((temp= getenv("MEMCACHED_SERVERS")))
+    {
+      opt_servers= strdup(temp);
+    }
+
+    if (opt_servers == NULL)
+    {
+      std::cerr << "No Servers provided" << std::endl;
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  memcached_server_st* servers= memcached_servers_parse(opt_servers);
+  if (servers == NULL or memcached_server_list_count(servers) == 0)
+  {
+    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  memcached_st *memc= memcached_create(NULL);
+  process_hash_option(memc, opt_hash);
+
+  memcached_server_push(memc, servers);
+  memcached_server_list_free(servers);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
+                         (uint64_t)opt_binary);
+
+  if (opt_username and LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    memcached_free(memc);
+    std::cerr << "--username was supplied, but binary was not built with SASL support." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  if (opt_username)
+  {
+    memcached_return_t ret;
+    if (memcached_failed(ret= memcached_set_sasl_auth_data(memc, opt_username, opt_passwd)))
+    {
+      std::cerr << memcached_last_error_message(memc) << std::endl;
+      memcached_free(memc);
+      return EXIT_FAILURE;
+    }
+  }
+
+  while (optind < argc)
+  {
+    memcached_return_t rc= memcached_touch(memc, argv[optind], strlen(argv[optind]), expiration);
+    if (rc == MEMCACHED_NOTFOUND)
+    {
+      if (opt_verbose)
+      {
+        std::cout << "Could not find key \"" << argv[optind] << "\"" << std::endl;
+      }
+
+      return_code= EXIT_FAILURE;
+    }
+    else if (memcached_failed(rc))
+    {
+      if (opt_verbose)
+      {
+        std::cerr << "Fatal error for key \"" << argv[optind] << "\" :" <<  memcached_last_error_message(memc) << std::endl;
+      }
+
+      return_code= EXIT_FAILURE;
+    }
+    else // success
+    {
+      if (opt_verbose)
+      {
+        std::cout << "Found key " << argv[optind] << std::endl;
+      }
+    }
+
+    optind++;
+  }
+
+  memcached_free(memc);
+
+  if (opt_servers)
+  {
+    free(opt_servers);
+  }
+
+  if (opt_hash)
+  {
+    free(opt_hash);
+  }
+
+  return return_code;
+}
+
+
+void options_parse(int argc, char *argv[])
+{
+  memcached_programs_help_st help_options[]=
+  {
+    {0},
+  };
+
+  static struct option long_options[]=
+    {
+      {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
+      {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
+      {(OPTIONSTRING)"quiet", no_argument, NULL, OPT_QUIET},
+      {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
+      {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
+      {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
+      {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
+      {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
+      {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
+      {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
+      {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
+      {0, 0, 0, 0},
+    };
+
+  bool opt_version= false;
+  bool opt_help= false;
+  int option_index= 0;
+
+  while (1)
+  {
+    int option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
+    if (option_rv == -1) 
+    {
+      break;
+    }
+
+    switch (option_rv)
+    {
+    case 0:
+      break;
+
+    case OPT_BINARY:
+      opt_binary = true;
+      break;
+
+    case OPT_VERBOSE: /* --verbose or -v */
+      opt_verbose = OPT_VERBOSE;
+      break;
+
+    case OPT_DEBUG: /* --debug or -d */
+      opt_verbose = OPT_DEBUG;
+      break;
+
+    case OPT_VERSION: /* --version or -V */
+      opt_version= true;
+      break;
+
+    case OPT_HELP: /* --help or -h */
+      opt_help= true;
+      break;
+
+    case OPT_SERVERS: /* --servers or -s */
+      opt_servers= strdup(optarg);
+      break;
+
+    case OPT_HASH:
+      opt_hash= strdup(optarg);
+      break;
+
+    case OPT_USERNAME:
+      opt_username= optarg;
+      break;
+
+    case OPT_PASSWD:
+      opt_passwd= optarg;
+      break;
+
+    case OPT_EXPIRE:
+      errno= 0;
+      expiration= time_t(strtoul(optarg, (char **)NULL, 10));
+      if (errno != 0)
+      {
+        fprintf(stderr, "Invalid value for --expire: %s\n", optarg);
+        exit(EXIT_FAILURE);
+      }
+      break;
+
+    case OPT_QUIET:
+      close_stdio();
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(EXIT_FAILURE);
+
+    default:
+      abort();
+    }
+  }
+
+  if (opt_version)
+  {
+    version_command(PROGRAM_NAME);
+    exit(EXIT_SUCCESS);
+  }
+
+  if (opt_help)
+  {
+    help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
+    exit(EXIT_SUCCESS);
+  }
+}
diff --git a/src/bin/memtouch.sh b/src/bin/memtouch.sh
new file mode 100755 (executable)
index 0000000..a082eb5
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+src/bin/memcp.sh
+src/bin/memtouch -v --servers localhost mem.testdata
diff --git a/src/bin/ms_atomic.h b/src/bin/ms_atomic.h
new file mode 100644 (file)
index 0000000..6ec990c
--- /dev/null
@@ -0,0 +1,114 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+#ifndef CLIENTS_MS_ATOMIC_H
+#define CLIENTS_MS_ATOMIC_H
+
+#if HAVE_C_STDATOMIC
+# define ATOMIC _Atomic
+#else
+# define ATOMIC volatile
+#endif
+
+#if defined(__SUNPRO_C)
+# define _KERNEL
+# include <atomic.h>
+# if SIZEOF_SIZE_T == 8
+#  define  atomic_add_size(X, Y) atomic_add_64((X), (Y))
+#  define  atomic_add_size_nv(X, Y) atomic_add_64((X), (Y))
+#  define  atomic_dec_size(X, Y) atomic_add_64((X), (Y))
+#  define  atomic_dec_size_nv(X, Y) atomic_add_64((X), (Y))
+# else
+#  define  atomic_add_size(X, Y) atomic_add_32((X), (Y))
+#  define  atomic_add_size_nv(X, Y) atomic_add_32((X), (Y))
+#  define  atomic_dec_size(X, Y) atomic_add_32((X), (Y))
+#  define  atomic_dec_size_nv(X, Y) atomic_add_32((X), (Y))
+# endif
+# undef _KERNEL
+#elif HAVE_GCC_ATOMIC_BUILTINS
+# define atomic_add_8(X, Y)  __sync_fetch_and_add((X), (Y))
+# define atomic_add_16(X, Y) __sync_fetch_and_add((X), (Y))
+# define atomic_add_32(X, Y) __sync_fetch_and_add((X), (Y))
+# define atomic_add_size(X, Y) __sync_fetch_and_add((X), (Y))
+# define atomic_dec_8(X)  __sync_fetch_and_sub((X), 1)
+# define atomic_dec_16(X) __sync_fetch_and_sub((X), 1)
+# define atomic_dec_32(X) __sync_fetch_and_sub((X), 1)
+# define atomic_dec_size(X) __sync_fetch_and_sub((X), 1)
+/* The same as above, but these return the new value instead of void */
+# define atomic_add_8_nv(X, Y)  __sync_fetch_and_add((X), (Y))
+# define atomic_add_16_nv(X, Y) __sync_fetch_and_add((X), (Y))
+# define atomic_add_32_nv(X, Y) __sync_fetch_and_add((X), (Y))
+# define atomic_add_size_nv(X, Y) __sync_fetch_and_add((X), (Y))
+# define atomic_dec_8_nv(X)  __sync_fetch_and_sub((X), 1)
+# define atomic_dec_16_nv(X) __sync_fetch_and_sub((X), 1)
+# define atomic_dec_32_nv(X) __sync_fetch_and_sub((X), 1)
+# define atomic_dec_size_nv(X) __sync_fetch_and_sub((X), 1)
+#elif HAVE_C_STDATOMIC
+# include <stdatomic.h>
+# define atomic_add_8(X, Y) atomic_fetch_add(X, Y)
+# define atomic_add_16(X, Y) atomic_fetch_add(X, Y)
+# define atomic_add_32(X, Y) atomic_fetch_add(X, Y)
+# define atomic_add_size(X, Y) atomic_fetch_add(X, Y)
+# define atomic_dec_8(X) atomic_fetch_sub(X, 1)
+# define atomic_dec_16(X) atomic_fetch_sub(X, 1)
+# define atomic_dec_32(X) atomic_fetch_sub(X, 1)
+# define atomic_dec_size(X) atomic_fetch_sub(X, 1)
+/* The same as above, but these return the new value instead of void */
+# define ATOMIC_ADD_FETCH_DECL(T) \
+static inline T atomic_add_fetch_##T(ATOMIC T *ptr, T add) { \
+       T des, cur = atomic_load(ptr); \
+       do { \
+               des = cur + add; \
+       } while(!atomic_compare_exchange_weak(ptr, &cur, des)); \
+       return des; \
+}
+# define ATOMIC_SUB_FETCH_DECL(T) \
+T atomic_sub_fetch_##T(ATOMIC T *ptr) { \
+       T des, cur = atomic_load(ptr); \
+       do { \
+               des = cur - 1; \
+       } while(!atomic_compare_exchange_weak(ptr, &cur, des)); \
+       return des; \
+}
+ATOMIC_ADD_FETCH_DECL(uint8_t)
+# define atomic_add_8_nv(X, Y) atomic_add_fetch_uint8_t(X, Y)
+ATOMIC_ADD_FETCH_DECL(uint16_t)
+# define atomic_add_16_nv(X, Y) atomic_add_fetch_uint16_t(X, Y)
+ATOMIC_ADD_FETCH_DECL(uint32_t)
+# define atomic_add_32_nv(X, Y) atomic_add_fetch_uint32_t(X, Y)
+ATOMIC_ADD_FETCH_DECL(size_t)
+# define atomic_add_size_nv(X, Y) atomic_add_fetch_size_t(X, Y)
+# define atomic_dec_8_nv(X) atomic_sub_fetch<uint8_t>(X, Y)
+# define atomic_dec_16_nv(X) atomic_sub_fetch<uint16_t>(X, Y)
+# define atomic_dec_32_nv(X) atomic_sub_fetch<uint32_t>(X, Y)
+# define atomic_dec_size_nv(X) atomic_sub_fetch<size_t>(X, Y)
+#else
+#warning "Atomic operators not found so memslap will not work correctly"
+# define atomic_add_8(X, Y) 0
+# define atomic_add_16(X, Y) 0
+# define atomic_add_32(X, Y) 0
+# define atomic_add_size(X, Y) 0
+# define atomic_dec_8(X) 0
+# define atomic_dec_16(X) 0
+# define atomic_dec_32(X) 0
+# define atomic_dec_size(X) 0
+/* The same as above, but these return the new value instead of void */
+# define atomic_add_8_nv(X, Y) 0
+# define atomic_add_16_nv(X, Y) 0
+# define atomic_add_32_nv(X, Y) 0
+# define atomic_add_size_nv(X, Y) 0
+# define atomic_dec_8_nv(X) 0
+# define atomic_dec_16_nv(X) 0
+# define atomic_dec_32_nv(X) 0
+# define atomic_dec_size_nv(X) 0
+#endif /* defined(__SUNPRO_C) */
+
+#endif /* CLIENTS_MS_ATOMIC_H */
diff --git a/src/bin/ms_conn.c b/src/bin/ms_conn.c
new file mode 100644 (file)
index 0000000..71353d5
--- /dev/null
@@ -0,0 +1,3427 @@
+/*
+ * File:   ms_conn.c
+ * Author: Mingqiang Zhuang
+ *
+ * Created on February 10, 2009
+ *
+ * (c) Copyright 2009, Schooner Information Technology, Inc.
+ * http://www.schoonerinfotech.com/
+ *
+ */
+
+#include "mem_config.h"
+
+#include <stdio.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <sys/uio.h>
+#include <event.h>
+#include <fcntl.h>
+#include <netinet/tcp.h>
+#include <netinet/in.h>
+
+#if defined(HAVE_ARPA_INET_H)
+# include <arpa/inet.h>
+#endif
+
+#if defined(HAVE_SYS_TIME_H)
+# include <sys/time.h>
+#endif
+
+#if defined(HAVE_TIME_H)
+# include <time.h>
+#endif
+
+#include "ms_setting.h"
+#include "ms_thread.h"
+#include "ms_atomic.h"
+
+#ifdef linux
+/* /usr/include/netinet/in.h defines macros from ntohs() to _bswap_nn to
+ * optimize the conversion functions, but the prototypes generate warnings
+ * from gcc. The conversion methods isn't the bottleneck for my app, so
+ * just remove the warnings by undef'ing the optimization ..
+ */
+#undef ntohs
+#undef ntohl
+#undef htons
+#undef htonl
+#endif
+
+/* for network write */
+#define TRANSMIT_COMPLETE      0
+#define TRANSMIT_INCOMPLETE    1
+#define TRANSMIT_SOFT_ERROR    2
+#define TRANSMIT_HARD_ERROR    3
+
+/* for generating key */
+#define KEY_PREFIX_BASE        0x1010101010101010 /* not include ' ' '\r' '\n' '\0' */
+#define KEY_PREFIX_MASK        0x1010101010101010
+
+/* For parse the value length return by server */
+#define KEY_TOKEN              1
+#define VALUELEN_TOKEN         3
+
+/* global increasing counter, to ensure the key prefix unique */
+static uint64_t key_prefix_seq= KEY_PREFIX_BASE;
+
+/* global increasing counter, generating request id for UDP */
+static ATOMIC uint32_t udp_request_id= 0;
+
+extern pthread_key_t ms_thread_key;
+
+/* generate upd request id */
+static uint32_t ms_get_udp_request_id(void);
+
+
+/* connect initialize */
+static void ms_task_init(ms_conn_t *c);
+static int ms_conn_udp_init(ms_conn_t *c, const bool is_udp);
+static int ms_conn_sock_init(ms_conn_t *c);
+static int ms_conn_event_init(ms_conn_t *c);
+static int ms_conn_init(ms_conn_t *c,
+                        const int init_state,
+                        const int read_buffer_size,
+                        const bool is_udp);
+static void ms_warmup_num_init(ms_conn_t *c);
+static int ms_item_win_init(ms_conn_t *c);
+
+
+/* connection close */
+void ms_conn_free(ms_conn_t *c);
+static void ms_conn_close(ms_conn_t *c);
+
+
+/* create network connection */
+static int ms_new_socket(struct addrinfo *ai);
+static void ms_maximize_sndbuf(const int sfd);
+static int ms_network_connect(ms_conn_t *c,
+                              char *srv_host_name,
+                              const int srv_port,
+                              const bool is_udp,
+                              int *ret_sfd);
+static int ms_reconn(ms_conn_t *c);
+
+
+/* read and parse */
+static int ms_tokenize_command(char *command,
+                               token_t *tokens,
+                               const int max_tokens);
+static int ms_ascii_process_line(ms_conn_t *c, char *command);
+static int ms_try_read_line(ms_conn_t *c);
+static int ms_sort_udp_packet(ms_conn_t *c, char *buf, int rbytes);
+static int ms_udp_read(ms_conn_t *c, char *buf, int len);
+static int ms_try_read_network(ms_conn_t *c);
+static void ms_verify_value(ms_conn_t *c,
+                            ms_mlget_task_item_t *mlget_item,
+                            char *value,
+                            int vlen);
+static void ms_ascii_complete_nread(ms_conn_t *c);
+static void ms_bin_complete_nread(ms_conn_t *c);
+static void ms_complete_nread(ms_conn_t *c);
+
+
+/* send functions */
+static int ms_add_msghdr(ms_conn_t *c);
+static int ms_ensure_iov_space(ms_conn_t *c);
+static int ms_add_iov(ms_conn_t *c, const void *buf, int len);
+static int ms_build_udp_headers(ms_conn_t *c);
+static int ms_transmit(ms_conn_t *c);
+
+
+/* status adjustment */
+static void ms_conn_shrink(ms_conn_t *c);
+static void ms_conn_set_state(ms_conn_t *c, int state);
+static bool ms_update_event(ms_conn_t *c, const int new_flags);
+static uint32_t ms_get_rep_sock_index(ms_conn_t *c, int cmd);
+static uint32_t ms_get_next_sock_index(ms_conn_t *c);
+static int ms_update_conn_sock_event(ms_conn_t *c);
+static bool ms_need_yield(ms_conn_t *c);
+static void ms_update_start_time(ms_conn_t *c);
+
+
+/* main loop */
+static void ms_drive_machine(ms_conn_t *c);
+void ms_event_handler(const int fd, const short which, void *arg);
+
+
+/* ascii protocol */
+static int ms_build_ascii_write_buf_set(ms_conn_t *c, ms_task_item_t *item);
+static int ms_build_ascii_write_buf_get(ms_conn_t *c, ms_task_item_t *item);
+static int ms_build_ascii_write_buf_mlget(ms_conn_t *c);
+
+
+/* binary protocol */
+static int ms_bin_process_response(ms_conn_t *c);
+static void ms_add_bin_header(ms_conn_t *c,
+                              uint8_t opcode,
+                              uint8_t hdr_len,
+                              uint16_t key_len,
+                              uint32_t body_len);
+static void ms_add_key_to_iov(ms_conn_t *c, ms_task_item_t *item);
+static int ms_build_bin_write_buf_set(ms_conn_t *c, ms_task_item_t *item);
+static int ms_build_bin_write_buf_get(ms_conn_t *c, ms_task_item_t *item);
+static int ms_build_bin_write_buf_mlget(ms_conn_t *c);
+
+
+/**
+ * each key has two parts, prefix and suffix. The suffix is a
+ * string random get form the character table. The prefix is a
+ * uint64_t variable. And the prefix must be unique. we use the
+ * prefix to identify a key. And the prefix can't include
+ * character ' ' '\r' '\n' '\0'.
+ *
+ * @return uint64_t
+ */
+uint64_t ms_get_key_prefix(void)
+{
+  uint64_t key_prefix;
+
+  pthread_mutex_lock(&ms_global.seq_mutex);
+  key_prefix_seq|= KEY_PREFIX_MASK;
+  key_prefix= key_prefix_seq;
+  key_prefix_seq++;
+  pthread_mutex_unlock(&ms_global.seq_mutex);
+
+  return key_prefix;
+} /* ms_get_key_prefix */
+
+
+/**
+ * get an unique udp request id
+ *
+ * @return an unique UDP request id
+ */
+static uint32_t ms_get_udp_request_id(void)
+{
+  return atomic_add_32_nv(&udp_request_id, 1);
+}
+
+
+/**
+ * initialize current task structure
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_task_init(ms_conn_t *c)
+{
+  c->curr_task.cmd= CMD_NULL;
+  c->curr_task.item= 0;
+  c->curr_task.verify= false;
+  c->curr_task.finish_verify= true;
+  c->curr_task.get_miss= true;
+
+  c->curr_task.get_opt= 0;
+  c->curr_task.set_opt= 0;
+  c->curr_task.cycle_undo_get= 0;
+  c->curr_task.cycle_undo_set= 0;
+  c->curr_task.verified_get= 0;
+  c->curr_task.overwrite_set= 0;
+} /* ms_task_init */
+
+
+/**
+ * initialize udp for the connection structure
+ *
+ * @param c, pointer of the concurrency
+ * @param is_udp, whether it's udp
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_conn_udp_init(ms_conn_t *c, const bool is_udp)
+{
+  c->hdrbuf= 0;
+  c->rudpbuf= 0;
+  c->udppkt= 0;
+
+  c->rudpsize= UDP_DATA_BUFFER_SIZE;
+  c->hdrsize= 0;
+
+  c->rudpbytes= 0;
+  c->packets= 0;
+  c->recvpkt= 0;
+  c->pktcurr= 0;
+  c->ordcurr= 0;
+
+  c->udp= is_udp;
+
+  if (c->udp || (! c->udp && ms_setting.facebook_test))
+  {
+    c->rudpbuf= (char *)malloc((size_t)c->rudpsize);
+    c->udppkt= (ms_udppkt_t *)malloc(MAX_UDP_PACKET * sizeof(ms_udppkt_t));
+
+    if ((c->rudpbuf == NULL) || (c->udppkt == NULL))
+    {
+      if (c->rudpbuf != NULL)
+        free(c->rudpbuf);
+      if (c->udppkt != NULL)
+        free(c->udppkt);
+      fprintf(stderr, "malloc()\n");
+      return -1;
+    }
+    memset(c->udppkt, 0, MAX_UDP_PACKET * sizeof(ms_udppkt_t));
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_conn_udp_init */
+
+
+/**
+ * initialize the connection structure
+ *
+ * @param c, pointer of the concurrency
+ * @param init_state, (conn_read, conn_write, conn_closing)
+ * @param read_buffer_size
+ * @param is_udp, whether it's udp
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_conn_init(ms_conn_t *c,
+                        const int init_state,
+                        const int read_buffer_size,
+                        const bool is_udp)
+{
+  assert(c != NULL);
+
+  c->rbuf= c->wbuf= 0;
+  c->iov= 0;
+  c->msglist= 0;
+
+  c->rsize= read_buffer_size;
+  c->wsize= WRITE_BUFFER_SIZE;
+  c->iovsize= IOV_LIST_INITIAL;
+  c->msgsize= MSG_LIST_INITIAL;
+
+  /* for replication, each connection need connect all the server */
+  if (ms_setting.rep_write_srv > 0)
+  {
+    c->total_sfds= ms_setting.srv_cnt * ms_setting.sock_per_conn;
+  }
+  else
+  {
+    c->total_sfds= ms_setting.sock_per_conn;
+  }
+  c->alive_sfds= 0;
+
+  c->rbuf= (char *)malloc((size_t)c->rsize);
+  c->wbuf= (char *)malloc((size_t)c->wsize);
+  c->iov= (struct iovec *)malloc(sizeof(struct iovec) * (size_t)c->iovsize);
+  c->msglist= (struct msghdr *)malloc(
+    sizeof(struct msghdr) * (size_t)c->msgsize);
+  if (ms_setting.mult_key_num > 1)
+  {
+    c->mlget_task.mlget_item= (ms_mlget_task_item_t *)
+                              malloc(
+      sizeof(ms_mlget_task_item_t) * (size_t)ms_setting.mult_key_num);
+  }
+  c->tcpsfd= (int *)malloc((size_t)c->total_sfds * sizeof(int));
+
+  if ((c->rbuf == NULL) || (c->wbuf == NULL) || (c->iov == NULL)
+      || (c->msglist == NULL) || (c->tcpsfd == NULL)
+      || ((ms_setting.mult_key_num > 1)
+          && (c->mlget_task.mlget_item == NULL)))
+  {
+    if (c->rbuf != NULL)
+      free(c->rbuf);
+    if (c->wbuf != NULL)
+      free(c->wbuf);
+    if (c->iov != NULL)
+      free(c->iov);
+    if (c->msglist != NULL)
+      free(c->msglist);
+    if (c->mlget_task.mlget_item != NULL)
+      free(c->mlget_task.mlget_item);
+    if (c->tcpsfd != NULL)
+      free(c->tcpsfd);
+    fprintf(stderr, "malloc()\n");
+    return -1;
+  }
+
+  c->state= init_state;
+  c->rvbytes= 0;
+  c->rbytes= 0;
+  c->rcurr= c->rbuf;
+  c->wcurr= c->wbuf;
+  c->iovused= 0;
+  c->msgcurr= 0;
+  c->msgused= 0;
+  c->cur_idx= c->total_sfds;       /* default index is a invalid value */
+
+  c->ctnwrite= false;
+  c->readval= false;
+  c->change_sfd= false;
+
+  c->precmd.cmd= c->currcmd.cmd= CMD_NULL;
+  c->precmd.isfinish= true;         /* default the previous command finished */
+  c->currcmd.isfinish= false;
+  c->precmd.retstat= c->currcmd.retstat= MCD_FAILURE;
+  c->precmd.key_prefix= c->currcmd.key_prefix= 0;
+
+  c->mlget_task.mlget_num= 0;
+  c->mlget_task.value_index= -1;         /* default invalid value */
+
+  if (ms_setting.binary_prot_)
+  {
+    c->protocol= binary_prot;
+  }
+  else
+  {
+    c->protocol= ascii_prot;
+  }
+
+  /* initialize udp */
+  if (ms_conn_udp_init(c, is_udp) != 0)
+  {
+    return -1;
+  }
+
+  /* initialize task */
+  ms_task_init(c);
+
+  if (! (ms_setting.facebook_test && is_udp))
+  {
+    atomic_add_32(&ms_stats.active_conns, 1);
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_conn_init */
+
+
+/**
+ * when doing 100% get operation, it could preset some objects
+ * to warmup the server. this function is used to initialize the
+ * number of the objects to preset.
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_warmup_num_init(ms_conn_t *c)
+{
+  /* no set operation, preset all the items in the window  */
+  if (ms_setting.cmd_distr[CMD_SET].cmd_prop < PROP_ERROR)
+  {
+    c->warmup_num= c->win_size;
+    c->remain_warmup_num= c->warmup_num;
+  }
+  else
+  {
+    c->warmup_num= 0;
+    c->remain_warmup_num= c->warmup_num;
+  }
+} /* ms_warmup_num_init */
+
+
+/**
+ * each connection has an item window, this function initialize
+ * the window. The window is used to generate task.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_item_win_init(ms_conn_t *c)
+{
+  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
+  int exp_cnt= 0;
+
+  c->win_size= (int)ms_setting.win_size;
+  c->set_cursor= 0;
+  c->exec_num= ms_thread->thread_ctx->exec_num_perconn;
+  c->remain_exec_num= c->exec_num;
+
+  c->item_win= (ms_task_item_t *)malloc(
+    sizeof(ms_task_item_t) * (size_t)c->win_size);
+  if (c->item_win == NULL)
+  {
+    fprintf(stderr, "Can't allocate task item array for conn.\n");
+    return -1;
+  }
+  memset(c->item_win, 0, sizeof(ms_task_item_t) * (size_t)c->win_size);
+
+  for (int i= 0; i < c->win_size; i++)
+  {
+    c->item_win[i].key_size= (int)ms_setting.distr[i].key_size;
+    c->item_win[i].key_prefix= ms_get_key_prefix();
+    c->item_win[i].key_suffix_offset= ms_setting.distr[i].key_offset;
+    c->item_win[i].value_size= (int)ms_setting.distr[i].value_size;
+    c->item_win[i].value_offset= INVALID_OFFSET;         /* default in invalid offset */
+    c->item_win[i].client_time= 0;
+
+    /* set expire time base on the proportion */
+    if (exp_cnt < ms_setting.exp_ver_per * i)
+    {
+      c->item_win[i].exp_time= FIXED_EXPIRE_TIME;
+      exp_cnt++;
+    }
+    else
+    {
+      c->item_win[i].exp_time= 0;
+    }
+  }
+
+  ms_warmup_num_init(c);
+
+  return EXIT_SUCCESS;
+} /* ms_item_win_init */
+
+
+/**
+ * each connection structure can include one or more sock
+ * handlers. this function create these socks and connect the
+ * server(s).
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_conn_sock_init(ms_conn_t *c)
+{
+  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
+  uint32_t i;
+  int ret_sfd;
+  uint32_t srv_idx= 0;
+
+  assert(c != NULL);
+  assert(c->tcpsfd != NULL);
+
+  for (i= 0; i < c->total_sfds; i++)
+  {
+    ret_sfd= 0;
+    if (ms_setting.rep_write_srv > 0)
+    {
+      /* for replication, each connection need connect all the server */
+      srv_idx= i % ms_setting.srv_cnt;
+    }
+    else
+    {
+      /* all the connections in a thread connects the same server */
+      srv_idx= ms_thread->thread_ctx->srv_idx;
+    }
+
+    if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name,
+                           ms_setting.servers[srv_idx].srv_port,
+                           ms_setting.udp, &ret_sfd) != 0)
+    {
+      break;
+    }
+
+    if (i == 0)
+    {
+      c->sfd= ret_sfd;
+    }
+
+    if (! ms_setting.udp)
+    {
+      c->tcpsfd[i]= ret_sfd;
+    }
+
+    c->alive_sfds++;
+  }
+
+  /* initialize udp sock handler if necessary */
+  if (ms_setting.facebook_test)
+  {
+    ret_sfd= 0;
+    if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name,
+                           ms_setting.servers[srv_idx].srv_port,
+                           true, &ret_sfd) != 0)
+    {
+      c->udpsfd= 0;
+    }
+    else
+    {
+      c->udpsfd= ret_sfd;
+    }
+  }
+
+  if ((i != c->total_sfds) || (ms_setting.facebook_test && (c->udpsfd == 0)))
+  {
+    if (ms_setting.udp)
+    {
+      close(c->sfd);
+    }
+    else
+    {
+      for (uint32_t j= 0; j < i; j++)
+      {
+        close(c->tcpsfd[j]);
+      }
+    }
+
+    if (c->udpsfd != 0)
+    {
+      close(c->udpsfd);
+    }
+
+    return -1;
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_conn_sock_init */
+
+
+/**
+ * each connection is managed by libevent, this function
+ * initialize the event of the connection structure.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_conn_event_init(ms_conn_t *c)
+{
+  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
+  short event_flags= EV_WRITE | EV_PERSIST;
+
+  event_set(&c->event, c->sfd, event_flags, ms_event_handler, (void *)c);
+  event_base_set(ms_thread->base, &c->event);
+  c->ev_flags= event_flags;
+
+  if (event_add(&c->event, NULL) == -1)
+  {
+    return -1;
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_conn_event_init */
+
+
+/**
+ * setup a connection, each connection structure of each
+ * thread must call this function to initialize.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+int ms_setup_conn(ms_conn_t *c)
+{
+  if (ms_item_win_init(c) != 0)
+  {
+    return -1;
+  }
+
+  if (ms_conn_init(c, conn_write, DATA_BUFFER_SIZE, ms_setting.udp) != 0)
+  {
+    return -1;
+  }
+
+  if (ms_conn_sock_init(c) != 0)
+  {
+    return -1;
+  }
+
+  if (ms_conn_event_init(c) != 0)
+  {
+    return -1;
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_setup_conn */
+
+
+/**
+ * Frees a connection.
+ *
+ * @param c, pointer of the concurrency
+ */
+void ms_conn_free(ms_conn_t *c)
+{
+  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
+  if (c != NULL)
+  {
+    if (c->hdrbuf != NULL)
+      free(c->hdrbuf);
+    if (c->msglist != NULL)
+      free(c->msglist);
+    if (c->rbuf != NULL)
+      free(c->rbuf);
+    if (c->wbuf != NULL)
+      free(c->wbuf);
+    if (c->iov != NULL)
+      free(c->iov);
+    if (c->mlget_task.mlget_item != NULL)
+      free(c->mlget_task.mlget_item);
+    if (c->rudpbuf != NULL)
+      free(c->rudpbuf);
+    if (c->udppkt != NULL)
+      free(c->udppkt);
+    if (c->item_win != NULL)
+      free(c->item_win);
+    if (c->tcpsfd != NULL)
+      free(c->tcpsfd);
+
+    if (--ms_thread->nactive_conn == 0)
+    {
+      free(ms_thread->conn);
+    }
+  }
+} /* ms_conn_free */
+
+
+/**
+ * close a connection
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_conn_close(ms_conn_t *c)
+{
+  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
+  assert(c != NULL);
+
+  /* delete the event, the socket and the connection */
+  event_del(&c->event);
+
+  for (uint32_t i= 0; i < c->total_sfds; i++)
+  {
+    if (c->tcpsfd[i] > 0)
+    {
+      close(c->tcpsfd[i]);
+    }
+  }
+  c->sfd= 0;
+
+  if (ms_setting.facebook_test)
+  {
+    close(c->udpsfd);
+  }
+
+  atomic_dec_32(&ms_stats.active_conns);
+
+  ms_conn_free(c);
+
+  if (ms_setting.run_time == 0)
+  {
+    pthread_mutex_lock(&ms_global.run_lock.lock);
+    ms_global.run_lock.count++;
+    pthread_cond_signal(&ms_global.run_lock.cond);
+    pthread_mutex_unlock(&ms_global.run_lock.lock);
+  }
+
+  if (ms_thread->nactive_conn == 0)
+  {
+    pthread_exit(NULL);
+  }
+} /* ms_conn_close */
+
+
+/**
+ * create a new sock
+ *
+ * @param ai, server address information
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_new_socket(struct addrinfo *ai)
+{
+  int sfd;
+
+  if ((sfd= socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == -1)
+  {
+    fprintf(stderr, "socket() error: %s.\n", strerror(errno));
+    return -1;
+  }
+
+  return sfd;
+} /* ms_new_socket */
+
+
+/**
+ * Sets a socket's send buffer size to the maximum allowed by the system.
+ *
+ * @param sfd, file descriptor of socket
+ */
+static void ms_maximize_sndbuf(const int sfd)
+{
+  socklen_t intsize= sizeof(int);
+  unsigned int last_good= 0;
+  unsigned int min, max, avg;
+  unsigned int old_size;
+
+  /* Start with the default size. */
+  if (getsockopt(sfd, SOL_SOCKET, SO_SNDBUF, &old_size, &intsize) != 0)
+  {
+    fprintf(stderr, "getsockopt(SO_SNDBUF)\n");
+    return;
+  }
+
+  /* Binary-search for the real maximum. */
+  min= old_size;
+  max= MAX_SENDBUF_SIZE;
+
+  while (min <= max)
+  {
+    avg= ((unsigned int)(min + max)) / 2;
+    if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, (void *)&avg, intsize) == 0)
+    {
+      last_good= avg;
+      min= avg + 1;
+    }
+    else
+    {
+      max= avg - 1;
+    }
+  }
+  (void)last_good;
+} /* ms_maximize_sndbuf */
+
+
+/**
+ * socket connects the server
+ *
+ * @param c, pointer of the concurrency
+ * @param srv_host_name, the host name of the server
+ * @param srv_port, port of server
+ * @param is_udp, whether it's udp
+ * @param ret_sfd, the connected socket file descriptor
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_network_connect(ms_conn_t *c,
+                              char *srv_host_name,
+                              const int srv_port,
+                              const bool is_udp,
+                              int *ret_sfd)
+{
+  int sfd;
+  struct linger ling=
+  {
+    0, 0
+  };
+  struct addrinfo *ai;
+  struct addrinfo *next;
+  struct addrinfo hints;
+  char port_buf[NI_MAXSERV];
+  int  error;
+  int  success= 0;
+
+  int flags= 1;
+
+  /*
+   * the memset call clears nonstandard fields in some impementations
+   * that otherwise mess things up.
+   */
+  memset(&hints, 0, sizeof(hints));
+#ifdef AI_ADDRCONFIG
+  hints.ai_flags= AI_PASSIVE | AI_ADDRCONFIG;
+#else
+  hints.ai_flags= AI_PASSIVE;
+#endif /* AI_ADDRCONFIG */
+  if (is_udp)
+  {
+    hints.ai_protocol= IPPROTO_UDP;
+    hints.ai_socktype= SOCK_DGRAM;
+    hints.ai_family= AF_INET;      /* This left here because of issues with OSX 10.5 */
+  }
+  else
+  {
+    hints.ai_family= AF_UNSPEC;
+    hints.ai_protocol= IPPROTO_TCP;
+    hints.ai_socktype= SOCK_STREAM;
+  }
+
+  snprintf(port_buf, NI_MAXSERV, "%d", srv_port);
+  error= getaddrinfo(srv_host_name, port_buf, &hints, &ai);
+  if (error != 0)
+  {
+    if (error != EAI_SYSTEM)
+      fprintf(stderr, "getaddrinfo(): %s.\n", gai_strerror(error));
+    else
+      perror("getaddrinfo()\n");
+
+    return -1;
+  }
+
+  for (next= ai; next; next= next->ai_next)
+  {
+    if ((sfd= ms_new_socket(next)) == -1)
+    {
+      freeaddrinfo(ai);
+      return -1;
+    }
+
+    setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags));
+    if (is_udp)
+    {
+      ms_maximize_sndbuf(sfd);
+    }
+    else
+    {
+      setsockopt(sfd, SOL_SOCKET, SO_KEEPALIVE, (void *)&flags,
+                 sizeof(flags));
+      setsockopt(sfd, SOL_SOCKET, SO_LINGER, (void *)&ling, sizeof(ling));
+      setsockopt(sfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags,
+                 sizeof(flags));
+    }
+
+    if (is_udp)
+    {
+      c->srv_recv_addr_size= sizeof(struct sockaddr);
+      memcpy(&c->srv_recv_addr, next->ai_addr, c->srv_recv_addr_size);
+    }
+    else
+    {
+      if (connect(sfd, next->ai_addr, next->ai_addrlen) == -1)
+      {
+        close(sfd);
+        freeaddrinfo(ai);
+        return -1;
+      }
+    }
+
+    if (((flags= fcntl(sfd, F_GETFL, 0)) < 0)
+        || (fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0))
+    {
+      fprintf(stderr, "setting O_NONBLOCK\n");
+      close(sfd);
+      freeaddrinfo(ai);
+      return -1;
+    }
+
+    if (ret_sfd != NULL)
+    {
+      *ret_sfd= sfd;
+    }
+
+    success++;
+  }
+
+  freeaddrinfo(ai);
+
+  /* Return zero if we detected no errors in starting up connections */
+  return success == 0;
+} /* ms_network_connect */
+
+
+/**
+ * reconnect a disconnected sock
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_reconn(ms_conn_t *c)
+{
+  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
+  uint32_t srv_idx= 0;
+  uint32_t srv_conn_cnt= 0;
+
+  if (ms_setting.rep_write_srv > 0)
+  {
+    srv_idx= c->cur_idx % ms_setting.srv_cnt;
+    srv_conn_cnt= ms_setting.sock_per_conn  * ms_setting.nconns;
+  }
+  else
+  {
+    srv_idx= ms_thread->thread_ctx->srv_idx;
+    srv_conn_cnt= ms_setting.nconns / ms_setting.srv_cnt;
+  }
+
+  /* close the old socket handler */
+  close(c->sfd);
+  c->tcpsfd[c->cur_idx]= 0;
+
+  if (atomic_add_32_nv(&ms_setting.servers[srv_idx].disconn_cnt, 1)
+      % srv_conn_cnt == 0)
+  {
+    gettimeofday(&ms_setting.servers[srv_idx].disconn_time, NULL);
+    fprintf(stderr, "Server %s:%d disconnect\n",
+            ms_setting.servers[srv_idx].srv_host_name,
+            ms_setting.servers[srv_idx].srv_port);
+  }
+
+  if (ms_setting.rep_write_srv > 0)
+  {
+    uint32_t i= 0;
+
+    for (i= 0; i < c->total_sfds; i++)
+    {
+      if (c->tcpsfd[i] != 0)
+      {
+        break;
+      }
+    }
+
+    /* all socks disconnect */
+    if (i == c->total_sfds)
+    {
+      return -1;
+    }
+  }
+  else
+  {
+    do
+    {
+      /* reconnect success, break the loop */
+      if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name,
+                             ms_setting.servers[srv_idx].srv_port,
+                             ms_setting.udp, &c->sfd) == 0)
+      {
+        c->tcpsfd[c->cur_idx]= c->sfd;
+        if (atomic_add_32_nv(&ms_setting.servers[srv_idx].reconn_cnt, 1)
+            % (uint32_t)srv_conn_cnt == 0)
+        {
+          gettimeofday(&ms_setting.servers[srv_idx].reconn_time, NULL);
+          int reconn_time=
+            (int)(ms_setting.servers[srv_idx].reconn_time.tv_sec
+                  - ms_setting.servers[srv_idx].disconn_time
+                     .tv_sec);
+          fprintf(stderr, "Server %s:%d reconnect after %ds\n",
+                  ms_setting.servers[srv_idx].srv_host_name,
+                  ms_setting.servers[srv_idx].srv_port, reconn_time);
+        }
+        break;
+      }
+
+      if (ms_setting.rep_write_srv == 0 && c->total_sfds > 0)
+      {
+        /* wait a second and reconnect */
+        sleep(1);
+      }
+    }
+    while (ms_setting.rep_write_srv == 0 && c->total_sfds > 0);
+  }
+
+  if ((c->total_sfds > 1) && (c->tcpsfd[c->cur_idx] == 0))
+  {
+    c->sfd= 0;
+    c->alive_sfds--;
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_reconn */
+
+
+/**
+ *  reconnect several disconnected socks in the connection
+ *  structure, the ever-1-second timer of the thread will check
+ *  whether some socks in the connections disconnect. if
+ *  disconnect, reconnect the sock.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+int ms_reconn_socks(ms_conn_t *c)
+{
+  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
+  uint32_t srv_idx= 0;
+  int ret_sfd= 0;
+  uint32_t srv_conn_cnt= 0;
+  struct timeval cur_time;
+
+  assert(c != NULL);
+
+  if ((c->total_sfds == 1) || (c->total_sfds == c->alive_sfds))
+  {
+    return EXIT_SUCCESS;
+  }
+
+  for (uint32_t i= 0; i < c->total_sfds; i++)
+  {
+    if (c->tcpsfd[i] == 0)
+    {
+      gettimeofday(&cur_time, NULL);
+
+      /**
+       *  For failover test of replication, reconnect the socks after
+       *  it disconnects more than 5 seconds, Otherwise memslap will
+       *  block at connect() function and the work threads can't work
+       *  in this interval.
+       */
+      if (cur_time.tv_sec
+          - ms_setting.servers[srv_idx].disconn_time.tv_sec < 5)
+      {
+        break;
+      }
+
+      if (ms_setting.rep_write_srv > 0)
+      {
+        srv_idx= i % ms_setting.srv_cnt;
+        srv_conn_cnt= ms_setting.sock_per_conn * ms_setting.nconns;
+      }
+      else
+      {
+        srv_idx= ms_thread->thread_ctx->srv_idx;
+        srv_conn_cnt= ms_setting.nconns / ms_setting.srv_cnt;
+      }
+
+      if (ms_network_connect(c, ms_setting.servers[srv_idx].srv_host_name,
+                             ms_setting.servers[srv_idx].srv_port,
+                             ms_setting.udp, &ret_sfd) == 0)
+      {
+        c->tcpsfd[i]= ret_sfd;
+        c->alive_sfds++;
+
+        if (atomic_add_32_nv(&ms_setting.servers[srv_idx].reconn_cnt, 1)
+            % (uint32_t)srv_conn_cnt == 0)
+        {
+          gettimeofday(&ms_setting.servers[srv_idx].reconn_time, NULL);
+          int reconn_time=
+            (int)(ms_setting.servers[srv_idx].reconn_time.tv_sec
+                  - ms_setting.servers[srv_idx].disconn_time
+                     .tv_sec);
+          fprintf(stderr, "Server %s:%d reconnect after %ds\n",
+                  ms_setting.servers[srv_idx].srv_host_name,
+                  ms_setting.servers[srv_idx].srv_port, reconn_time);
+        }
+      }
+    }
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_reconn_socks */
+
+
+/**
+ * Tokenize the command string by replacing whitespace with '\0' and update
+ * the token array tokens with pointer to start of each token and length.
+ * Returns total number of tokens.  The last valid token is the terminal
+ * token (value points to the first unprocessed character of the string and
+ * length zero).
+ *
+ * Usage example:
+ *
+ *  while(ms_tokenize_command(command, ncommand, tokens, max_tokens) > 0) {
+ *      for(int ix = 0; tokens[ix].length != 0; ix++) {
+ *          ...
+ *      }
+ *      ncommand = tokens[ix].value - command;
+ *      command  = tokens[ix].value;
+ *   }
+ *
+ * @param command, the command string to token
+ * @param tokens, array to store tokens
+ * @param max_tokens, maximum tokens number
+ *
+ * @return int, the number of tokens
+ */
+static int ms_tokenize_command(char *command,
+                               token_t *tokens,
+                               const int max_tokens)
+{
+  char *s, *e;
+  int  ntokens= 0;
+
+  assert(command != NULL && tokens != NULL && max_tokens > 1);
+
+  for (s= e= command; ntokens < max_tokens - 1; ++e)
+  {
+    if (*e == ' ')
+    {
+      if (s != e)
+      {
+        tokens[ntokens].value= s;
+        tokens[ntokens].length= (size_t)(e - s);
+        ntokens++;
+        *e= '\0';
+      }
+      s= e + 1;
+    }
+    else if (*e == '\0')
+    {
+      if (s != e)
+      {
+        tokens[ntokens].value= s;
+        tokens[ntokens].length= (size_t)(e - s);
+        ntokens++;
+      }
+
+      break;       /* string end */
+    }
+  }
+
+  return ntokens;
+} /* ms_tokenize_command */
+
+
+/**
+ * parse the response of server.
+ *
+ * @param c, pointer of the concurrency
+ * @param command, the string responded by server
+ *
+ * @return int, if the command completed return EXIT_SUCCESS, else return
+ *         -1
+ */
+static int ms_ascii_process_line(ms_conn_t *c, char *command)
+{
+  int ret= 0;
+  int64_t value_len;
+  char *buffer= command;
+
+  assert(c != NULL);
+
+  /**
+   * for command get, we store the returned value into local buffer
+   * then continue in ms_complete_nread().
+   */
+
+  switch (buffer[0])
+  {
+  case 'V':                     /* VALUE || VERSION */
+    if (buffer[1] == 'A')       /* VALUE */
+    {
+      token_t tokens[MAX_TOKENS];
+      ms_tokenize_command(command, tokens, MAX_TOKENS);
+      errno= 0;
+      value_len= strtol(tokens[VALUELEN_TOKEN].value, NULL, 10);
+      if (errno != 0)
+      {
+        printf("<%d ERROR %s\n", c->sfd, strerror(errno));
+      }
+      c->currcmd.key_prefix= *(uint64_t *)tokens[KEY_TOKEN].value;
+
+      /*
+       *  We read the \r\n into the string since not doing so is more
+       *  cycles then the waster of memory to do so.
+       *
+       *  We are null terminating through, which will most likely make
+       *  some people lazy about using the return length.
+       */
+      c->rvbytes= (int)(value_len + 2);
+      c->readval= true;
+      ret= -1;
+    }
+
+    break;
+
+  case 'O':   /* OK */
+    c->currcmd.retstat= MCD_SUCCESS;
+    break;
+
+  case 'S':                    /* STORED STATS SERVER_ERROR */
+    if (buffer[2] == 'A')      /* STORED STATS */
+    {       /* STATS*/
+      c->currcmd.retstat= MCD_STAT;
+    }
+    else if (buffer[1] == 'E')
+    {
+      /* SERVER_ERROR */
+      printf("<%d %s\n", c->sfd, buffer);
+
+      c->currcmd.retstat= MCD_SERVER_ERROR;
+    }
+    else if (buffer[1] == 'T')
+    {
+      /* STORED */
+      c->currcmd.retstat= MCD_STORED;
+    }
+    else
+    {
+      c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
+    }
+    break;
+
+  case 'D':   /* DELETED DATA */
+    if (buffer[1] == 'E')
+    {
+      c->currcmd.retstat= MCD_DELETED;
+    }
+    else
+    {
+      c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
+    }
+
+    break;
+
+  case 'N':   /* NOT_FOUND NOT_STORED*/
+    if (buffer[4] == 'F')
+    {
+      c->currcmd.retstat= MCD_NOTFOUND;
+    }
+    else if (buffer[4] == 'S')
+    {
+      printf("<%d %s\n", c->sfd, buffer);
+      c->currcmd.retstat= MCD_NOTSTORED;
+    }
+    else
+    {
+      c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
+    }
+    break;
+
+  case 'E':   /* PROTOCOL ERROR or END */
+    if (buffer[1] == 'N')
+    {
+      /* END */
+      c->currcmd.retstat= MCD_END;
+    }
+    else if (buffer[1] == 'R')
+    {
+      printf("<%d ERROR\n", c->sfd);
+      c->currcmd.retstat= MCD_PROTOCOL_ERROR;
+    }
+    else if (buffer[1] == 'X')
+    {
+      c->currcmd.retstat= MCD_DATA_EXISTS;
+      printf("<%d %s\n", c->sfd, buffer);
+    }
+    else
+    {
+      c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
+    }
+    break;
+
+  case 'C':   /* CLIENT ERROR */
+    printf("<%d %s\n", c->sfd, buffer);
+    c->currcmd.retstat= MCD_CLIENT_ERROR;
+    break;
+
+  default:
+    c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
+    break;
+  } /* switch */
+
+  return ret;
+} /* ms_ascii_process_line */
+
+
+/**
+ * after one operation completes, reset the concurrency
+ *
+ * @param c, pointer of the concurrency
+ * @param timeout, whether it's timeout
+ */
+void ms_reset_conn(ms_conn_t *c, bool timeout)
+{
+  assert(c != NULL);
+
+  if (c->udp)
+  {
+    if ((c->packets > 0) && (c->packets < MAX_UDP_PACKET))
+    {
+      memset(c->udppkt, 0, sizeof(ms_udppkt_t) * (size_t)c->packets);
+    }
+
+    c->packets= 0;
+    c->recvpkt= 0;
+    c->pktcurr= 0;
+    c->ordcurr= 0;
+    c->rudpbytes= 0;
+  }
+  c->currcmd.isfinish= true;
+  c->ctnwrite= false;
+  c->rbytes= 0;
+  c->rcurr= c->rbuf;
+  c->msgcurr = 0;
+  c->msgused = 0;
+  c->iovused = 0;
+  ms_conn_set_state(c, conn_write);
+  memcpy(&c->precmd, &c->currcmd, sizeof(ms_cmdstat_t));    /* replicate command state */
+
+  if (timeout)
+  {
+    ms_drive_machine(c);
+  }
+} /* ms_reset_conn */
+
+
+/**
+ * if we have a complete line in the buffer, process it.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_try_read_line(ms_conn_t *c)
+{
+  if (c->protocol == binary_prot)
+  {
+    /* Do we have the complete packet header? */
+    if ((uint64_t)c->rbytes < sizeof(c->binary_header))
+    {
+      /* need more data! */
+      return EXIT_SUCCESS;
+    }
+    else
+    {
+#ifdef NEED_ALIGN
+      if (((long)(c->rcurr)) % 8 != 0)
+      {
+        /* must realign input buffer */
+        memmove(c->rbuf, c->rcurr, c->rbytes);
+        c->rcurr= c->rbuf;
+        if (settings.verbose)
+        {
+          fprintf(stderr, "%d: Realign input buffer.\n", c->sfd);
+        }
+      }
+#endif
+      protocol_binary_response_header *rsp;
+      rsp= (protocol_binary_response_header *)c->rcurr;
+
+      c->binary_header= *rsp;
+      c->binary_header.response.extlen= rsp->response.extlen;
+      c->binary_header.response.keylen= ntohs(rsp->response.keylen);
+      c->binary_header.response.bodylen= ntohl(rsp->response.bodylen);
+      c->binary_header.response.status= ntohs(rsp->response.status);
+
+      if (c->binary_header.response.magic != PROTOCOL_BINARY_RES)
+      {
+        fprintf(stderr, "Invalid magic:  %x\n",
+                c->binary_header.response.magic);
+        ms_conn_set_state(c, conn_closing);
+        return EXIT_SUCCESS;
+      }
+
+      /* process this complete response */
+      if (ms_bin_process_response(c) == 0)
+      {
+        /* current operation completed */
+        ms_reset_conn(c, false);
+        return -1;
+      }
+      else
+      {
+        c->rbytes-= (int32_t)sizeof(c->binary_header);
+        c->rcurr+= sizeof(c->binary_header);
+      }
+    }
+  }
+  else
+  {
+    char *el, *cont;
+
+    assert(c != NULL);
+    assert(c->rcurr <= (c->rbuf + c->rsize));
+
+    if (c->rbytes == 0)
+      return EXIT_SUCCESS;
+
+    el= memchr(c->rcurr, '\n', (size_t)c->rbytes);
+    if (! el)
+      return EXIT_SUCCESS;
+
+    cont= el + 1;
+    if (((el - c->rcurr) > 1) && (*(el - 1) == '\r'))
+    {
+      el--;
+    }
+    *el= '\0';
+
+    assert(cont <= (c->rcurr + c->rbytes));
+
+    /* process this complete line */
+    if (ms_ascii_process_line(c, c->rcurr) == 0)
+    {
+      /* current operation completed */
+      ms_reset_conn(c, false);
+      return -1;
+    }
+    else
+    {
+      /* current operation didn't complete */
+      c->rbytes-= (int32_t)(cont - c->rcurr);
+      c->rcurr= cont;
+    }
+
+    assert(c->rcurr <= (c->rbuf + c->rsize));
+  }
+
+  return -1;
+} /* ms_try_read_line */
+
+
+/**
+ *  because the packet of UDP can't ensure the order, the
+ *  function is used to sort the received udp packet.
+ *
+ * @param c, pointer of the concurrency
+ * @param buf, the buffer to store the ordered packages data
+ * @param rbytes, the maximum capacity of the buffer
+ *
+ * @return int, if success, return the copy bytes, else return
+ *         -1
+ */
+static int ms_sort_udp_packet(ms_conn_t *c, char *buf, int rbytes)
+{
+  int len= 0;
+  int wbytes= 0;
+  uint16_t req_id= 0;
+  uint16_t seq_num= 0;
+  uint16_t packets= 0;
+  unsigned char *header= NULL;
+
+  /* no enough data */
+  assert(c != NULL);
+  assert(buf != NULL);
+  assert(c->rudpbytes >= UDP_HEADER_SIZE);
+
+  /* calculate received packets count */
+  if (c->rudpbytes % UDP_MAX_PAYLOAD_SIZE >= UDP_HEADER_SIZE)
+  {
+    /* the last packet has some data */
+    c->recvpkt= c->rudpbytes / UDP_MAX_PAYLOAD_SIZE + 1;
+  }
+  else
+  {
+    c->recvpkt= c->rudpbytes / UDP_MAX_PAYLOAD_SIZE;
+  }
+
+  /* get the total packets count if necessary */
+  if (c->packets == 0)
+  {
+    c->packets= HEADER_TO_PACKETS((unsigned char *)c->rudpbuf);
+  }
+
+  /* build the ordered packet array */
+  for (int i= c->pktcurr; i < c->recvpkt; i++)
+  {
+    header= (unsigned char *)c->rudpbuf + i * UDP_MAX_PAYLOAD_SIZE;
+    req_id= (uint16_t)HEADER_TO_REQID(header);
+    assert(req_id == c->request_id % (1 << 16));
+
+    packets= (uint16_t)HEADER_TO_PACKETS(header);
+    assert(c->packets == HEADER_TO_PACKETS(header));
+
+    seq_num= (uint16_t)HEADER_TO_SEQNUM(header);
+    c->udppkt[seq_num].header= header;
+    c->udppkt[seq_num].data= (char *)header + UDP_HEADER_SIZE;
+
+    if (i == c->recvpkt - 1)
+    {
+      /* last received packet */
+      if (c->rudpbytes % UDP_MAX_PAYLOAD_SIZE == 0)
+      {
+        c->udppkt[seq_num].rbytes= UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE;
+        c->pktcurr++;
+      }
+      else
+      {
+        c->udppkt[seq_num].rbytes= c->rudpbytes % UDP_MAX_PAYLOAD_SIZE
+                                   - UDP_HEADER_SIZE;
+      }
+    }
+    else
+    {
+      c->udppkt[seq_num].rbytes= UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE;
+      c->pktcurr++;
+    }
+  }
+
+  for (int i= c->ordcurr; i < c->recvpkt; i++)
+  {
+    /* there is some data to copy */
+    if ((c->udppkt[i].data != NULL)
+        && (c->udppkt[i].copybytes < c->udppkt[i].rbytes))
+    {
+      header= c->udppkt[i].header;
+      len= c->udppkt[i].rbytes - c->udppkt[i].copybytes;
+      if (len > rbytes - wbytes)
+      {
+        len= rbytes - wbytes;
+      }
+
+      assert(len <= rbytes - wbytes);
+      assert(i == HEADER_TO_SEQNUM(header));
+
+      memcpy(buf + wbytes, c->udppkt[i].data + c->udppkt[i].copybytes,
+             (size_t)len);
+      wbytes+= len;
+      c->udppkt[i].copybytes+= len;
+
+      if ((c->udppkt[i].copybytes == c->udppkt[i].rbytes)
+          && (c->udppkt[i].rbytes == UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE))
+      {
+        /* finish copying all the data of this packet, next */
+        c->ordcurr++;
+      }
+
+      /* last received packet, and finish copying all the data */
+      if ((c->recvpkt == c->packets) && (i == c->recvpkt - 1)
+          && (c->udppkt[i].copybytes == c->udppkt[i].rbytes))
+      {
+        break;
+      }
+
+      /* no space to copy data */
+      if (wbytes >= rbytes)
+      {
+        break;
+      }
+
+      /* it doesn't finish reading all the data of the packet from network */
+      if ((i != c->recvpkt - 1)
+          && (c->udppkt[i].rbytes < UDP_MAX_PAYLOAD_SIZE - UDP_HEADER_SIZE))
+      {
+        break;
+      }
+    }
+    else
+    {
+      /* no data to copy */
+      break;
+    }
+  }
+  (void)packets;
+
+  return wbytes == 0 ? -1 : wbytes;
+} /* ms_sort_udp_packet */
+
+
+/**
+ * encapsulate upd read like tcp read
+ *
+ * @param c, pointer of the concurrency
+ * @param buf, read buffer
+ * @param len, length to read
+ *
+ * @return int, if success, return the read bytes, else return
+ *         -1
+ */
+static int ms_udp_read(ms_conn_t *c, char *buf, int len)
+{
+  int res= 0;
+  int avail= 0;
+  int rbytes= 0;
+  int copybytes= 0;
+
+  assert(c->udp);
+
+  while (1)
+  {
+    if (c->rudpbytes + UDP_MAX_PAYLOAD_SIZE > c->rudpsize)
+    {
+      char *new_rbuf= realloc(c->rudpbuf, (size_t)c->rudpsize * 2);
+      if (! new_rbuf)
+      {
+        fprintf(stderr, "Couldn't realloc input buffer.\n");
+        c->rudpbytes= 0;          /* ignore what we read */
+        return -1;
+      }
+      c->rudpbuf= new_rbuf;
+      c->rudpsize*= 2;
+    }
+
+    avail= c->rudpsize - c->rudpbytes;
+    /* UDP each time read a packet, 1400 bytes */
+    res= (int)read(c->sfd, c->rudpbuf + c->rudpbytes, (size_t)avail);
+
+    if (res > 0)
+    {
+      atomic_add_size(&ms_stats.bytes_read, res);
+      c->rudpbytes+= res;
+      rbytes+= res;
+      if (res == avail)
+      {
+        continue;
+      }
+      else
+      {
+        break;
+      }
+    }
+
+    if (res == 0)
+    {
+      /* "connection" closed */
+      return res;
+    }
+
+    if (res == -1)
+    {
+      /* no data to read */
+      return res;
+    }
+  }
+
+  /* copy data to read buffer */
+  if (rbytes > 0)
+  {
+    copybytes= ms_sort_udp_packet(c, buf, len);
+  }
+
+  if (copybytes == -1)
+  {
+    atomic_add_size(&ms_stats.pkt_disorder, 1);
+  }
+
+  return copybytes;
+} /* ms_udp_read */
+
+
+/*
+ * read from network as much as we can, handle buffer overflow and connection
+ * close.
+ * before reading, move the remaining incomplete fragment of a command
+ * (if any) to the beginning of the buffer.
+ * return EXIT_SUCCESS if there's nothing to read on the first read.
+ */
+
+/**
+ * read from network as much as we can, handle buffer overflow and connection
+ * close. before reading, move the remaining incomplete fragment of a command
+ * (if any) to the beginning of the buffer.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int,
+ *         return EXIT_SUCCESS if there's nothing to read on the first read.
+ *         return EXIT_FAILURE if get data
+ *         return -1 if error happens
+ */
+static int ms_try_read_network(ms_conn_t *c)
+{
+  int gotdata= 0;
+  int res;
+  int64_t avail;
+
+  assert(c != NULL);
+
+  if ((c->rcurr != c->rbuf)
+      && (! c->readval || (c->rvbytes > c->rsize - (c->rcurr - c->rbuf))
+          || (c->readval && (c->rcurr - c->rbuf > c->rbytes))))
+  {
+    if (c->rbytes != 0)     /* otherwise there's nothing to copy */
+      memmove(c->rbuf, c->rcurr, (size_t)c->rbytes);
+    c->rcurr= c->rbuf;
+  }
+
+  while (1)
+  {
+    if (c->rbytes >= c->rsize)
+    {
+      char *new_rbuf= realloc(c->rbuf, (size_t)c->rsize * 2);
+      if (! new_rbuf)
+      {
+        fprintf(stderr, "Couldn't realloc input buffer.\n");
+        c->rbytes= 0;          /* ignore what we read */
+        return -1;
+      }
+      c->rcurr= c->rbuf= new_rbuf;
+      c->rsize*= 2;
+    }
+
+    avail= c->rsize - c->rbytes - (c->rcurr - c->rbuf);
+    if (avail == 0)
+    {
+      break;
+    }
+
+    if (c->udp)
+    {
+      res= (int32_t)ms_udp_read(c, c->rcurr + c->rbytes, (int32_t)avail);
+    }
+    else
+    {
+      res= (int)read(c->sfd, c->rcurr + c->rbytes, (size_t)avail);
+    }
+
+    if (res > 0)
+    {
+      if (! c->udp)
+      {
+        atomic_add_size(&ms_stats.bytes_read, res);
+      }
+      gotdata= 1;
+      c->rbytes+= res;
+      if (res == avail)
+      {
+        continue;
+      }
+      else
+      {
+        break;
+      }
+    }
+    if (res == 0)
+    {
+      /* connection closed */
+      ms_conn_set_state(c, conn_closing);
+      return -1;
+    }
+    if (res == -1)
+    {
+      if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+        break;
+      /* Should close on unhandled errors. */
+      ms_conn_set_state(c, conn_closing);
+      return -1;
+    }
+  }
+
+  return gotdata;
+} /* ms_try_read_network */
+
+
+/**
+ * after get the object from server, verify the value if
+ * necessary.
+ *
+ * @param c, pointer of the concurrency
+ * @param mlget_item, pointer of mulit-get task item structure
+ * @param value, received value string
+ * @param vlen, received value string length
+ */
+static void ms_verify_value(ms_conn_t *c,
+                            ms_mlget_task_item_t *mlget_item,
+                            char *value,
+                            int vlen)
+{
+  if (c->curr_task.verify)
+  {
+    assert(c->curr_task.item->value_offset != INVALID_OFFSET);
+    char *orignval= &ms_setting.char_block[c->curr_task.item->value_offset];
+    char *orignkey=
+      &ms_setting.char_block[c->curr_task.item->key_suffix_offset];
+
+    /* verify expire time if necessary */
+    if (c->curr_task.item->exp_time > 0)
+    {
+      struct timeval curr_time;
+      gettimeofday(&curr_time, NULL);
+
+      /* object expired but get it now */
+      if (curr_time.tv_sec - c->curr_task.item->client_time
+          > c->curr_task.item->exp_time + EXPIRE_TIME_ERROR)
+      {
+        atomic_add_size(&ms_stats.exp_get, 1);
+
+        if (ms_setting.verbose)
+        {
+          char set_time[64];
+          char cur_time[64];
+          strftime(set_time, 64, "%Y-%m-%d %H:%M:%S",
+                   localtime(&c->curr_task.item->client_time));
+          strftime(cur_time, 64, "%Y-%m-%d %H:%M:%S",
+                   localtime(&curr_time.tv_sec));
+          fprintf(stderr,
+                  "\n<%d expire time verification failed, "
+                  "object expired but get it now\n"
+                  "\tkey len: %d\n"
+                  "\tkey: %" PRIx64 " %.*s\n"
+                  "\tset time: %s current time: %s "
+                  "diff time: %d expire time: %d\n"
+                  "\texpected data: \n"
+                  "\treceived data len: %d\n"
+                  "\treceived data: %.*s\n",
+                  c->sfd,
+                  c->curr_task.item->key_size,
+                  c->curr_task.item->key_prefix,
+                  c->curr_task.item->key_size - (int)KEY_PREFIX_SIZE,
+                  orignkey,
+                  set_time,
+                  cur_time,
+                  (int)(curr_time.tv_sec - c->curr_task.item->client_time),
+                  c->curr_task.item->exp_time,
+                  vlen,
+                  vlen,
+                  value);
+          fflush(stderr);
+        }
+      }
+    }
+    else
+    {
+      if ((c->curr_task.item->value_size != vlen)
+          || (memcmp(orignval, value, (size_t)vlen) != 0))
+      {
+        atomic_add_size(&ms_stats.vef_failed, 1);
+
+        if (ms_setting.verbose)
+        {
+          fprintf(stderr,
+                  "\n<%d data verification failed\n"
+                  "\tkey len: %d\n"
+                  "\tkey: %" PRIx64" %.*s\n"
+                  "\texpected data len: %d\n"
+                  "\texpected data: %.*s\n"
+                  "\treceived data len: %d\n"
+                  "\treceived data: %.*s\n",
+                  c->sfd,
+                  c->curr_task.item->key_size,
+                  c->curr_task.item->key_prefix,
+                  c->curr_task.item->key_size - (int)KEY_PREFIX_SIZE,
+                  orignkey,
+                  c->curr_task.item->value_size,
+                  c->curr_task.item->value_size,
+                  orignval,
+                  vlen,
+                  vlen,
+                  value);
+          fflush(stderr);
+        }
+      }
+    }
+
+    c->curr_task.finish_verify= true;
+
+    if (mlget_item != NULL)
+    {
+      mlget_item->finish_verify= true;
+    }
+  }
+} /* ms_verify_value */
+
+
+/**
+ * For ASCII protocol, after store the data into the local
+ * buffer, run this function to handle the data.
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_ascii_complete_nread(ms_conn_t *c)
+{
+  assert(c != NULL);
+  assert(c->rbytes >= c->rvbytes);
+  assert(c->protocol == ascii_prot);
+  if (c->rvbytes > 2)
+  {
+    assert(
+      c->rcurr[c->rvbytes - 1] == '\n' && c->rcurr[c->rvbytes - 2] == '\r');
+  }
+
+  /* multi-get */
+  ms_mlget_task_item_t *mlget_item= NULL;
+  if (((ms_setting.mult_key_num > 1)
+       && (c->mlget_task.mlget_num >= ms_setting.mult_key_num))
+      || ((c->remain_exec_num == 0) && (c->mlget_task.mlget_num > 0)))
+  {
+    c->mlget_task.value_index++;
+    mlget_item= &c->mlget_task.mlget_item[c->mlget_task.value_index];
+
+    if (mlget_item->item->key_prefix == c->currcmd.key_prefix)
+    {
+      c->curr_task.item= mlget_item->item;
+      c->curr_task.verify= mlget_item->verify;
+      c->curr_task.finish_verify= mlget_item->finish_verify;
+      mlget_item->get_miss= false;
+    }
+    else
+    {
+      /* Try to find the task item in multi-get task array */
+      for (int i= 0; i < c->mlget_task.mlget_num; i++)
+      {
+        mlget_item= &c->mlget_task.mlget_item[i];
+        if (mlget_item->item->key_prefix == c->currcmd.key_prefix)
+        {
+          c->curr_task.item= mlget_item->item;
+          c->curr_task.verify= mlget_item->verify;
+          c->curr_task.finish_verify= mlget_item->finish_verify;
+          mlget_item->get_miss= false;
+
+          break;
+        }
+      }
+    }
+  }
+
+  ms_verify_value(c, mlget_item, c->rcurr, c->rvbytes - 2);
+
+  c->curr_task.get_miss= false;
+  c->rbytes-= c->rvbytes;
+  c->rcurr= c->rcurr + c->rvbytes;
+  assert(c->rcurr <= (c->rbuf + c->rsize));
+  c->readval= false;
+  c->rvbytes= 0;
+} /* ms_ascii_complete_nread */
+
+
+/**
+ * For binary protocol, after store the data into the local
+ * buffer, run this function to handle the data.
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_bin_complete_nread(ms_conn_t *c)
+{
+  assert(c != NULL);
+  assert(c->rbytes >= c->rvbytes);
+  assert(c->protocol == binary_prot);
+
+  int extlen= c->binary_header.response.extlen;
+  int keylen= c->binary_header.response.keylen;
+  uint8_t opcode= c->binary_header.response.opcode;
+
+  /* not get command or not include value, just return */
+  if (((opcode != PROTOCOL_BINARY_CMD_GET)
+       && (opcode != PROTOCOL_BINARY_CMD_GETQ))
+      || (c->rvbytes <= extlen + keylen))
+  {
+    /* get miss */
+    if (c->binary_header.response.opcode == PROTOCOL_BINARY_CMD_GET)
+    {
+      c->currcmd.retstat= MCD_END;
+      c->curr_task.get_miss= true;
+    }
+
+    c->readval= false;
+    c->rvbytes= 0;
+    ms_reset_conn(c, false);
+    return;
+  }
+
+  /* multi-get */
+  ms_mlget_task_item_t *mlget_item= NULL;
+  if (((ms_setting.mult_key_num > 1)
+       && (c->mlget_task.mlget_num >= ms_setting.mult_key_num))
+      || ((c->remain_exec_num == 0) && (c->mlget_task.mlget_num > 0)))
+  {
+    c->mlget_task.value_index++;
+    mlget_item= &c->mlget_task.mlget_item[c->mlget_task.value_index];
+
+    c->curr_task.item= mlget_item->item;
+    c->curr_task.verify= mlget_item->verify;
+    c->curr_task.finish_verify= mlget_item->finish_verify;
+    mlget_item->get_miss= false;
+  }
+
+  ms_verify_value(c,
+                  mlget_item,
+                  c->rcurr + extlen + keylen,
+                  c->rvbytes - extlen - keylen);
+
+  c->currcmd.retstat= MCD_END;
+  c->curr_task.get_miss= false;
+  c->rbytes-= c->rvbytes;
+  c->rcurr= c->rcurr + c->rvbytes;
+  assert(c->rcurr <= (c->rbuf + c->rsize));
+  c->readval= false;
+  c->rvbytes= 0;
+
+  if (ms_setting.mult_key_num > 1)
+  {
+    /* multi-get have check all the item */
+    if (c->mlget_task.value_index == c->mlget_task.mlget_num - 1)
+    {
+      ms_reset_conn(c, false);
+    }
+  }
+  else
+  {
+    /* single get */
+    ms_reset_conn(c, false);
+  }
+} /* ms_bin_complete_nread */
+
+
+/**
+ * we get here after reading the value of get commands.
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_complete_nread(ms_conn_t *c)
+{
+  assert(c != NULL);
+  assert(c->rbytes >= c->rvbytes);
+  assert(c->protocol == ascii_prot
+         || c->protocol == binary_prot);
+
+  if (c->protocol == binary_prot)
+  {
+    ms_bin_complete_nread(c);
+  }
+  else
+  {
+    ms_ascii_complete_nread(c);
+  }
+} /* ms_complete_nread */
+
+
+/**
+ * Adds a message header to a connection.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_add_msghdr(ms_conn_t *c)
+{
+  struct msghdr *msg;
+
+  assert(c != NULL);
+
+  if (c->msgsize == c->msgused)
+  {
+    msg=
+      realloc(c->msglist, (size_t)c->msgsize * 2 * sizeof(struct msghdr));
+    if (! msg)
+      return -1;
+
+    c->msglist= msg;
+    c->msgsize*= 2;
+  }
+
+  msg= c->msglist + c->msgused;
+
+  /**
+   *  this wipes msg_iovlen, msg_control, msg_controllen, and
+   *  msg_flags, the last 3 of which aren't defined on solaris:
+   */
+  memset(msg, 0, sizeof(struct msghdr));
+
+  msg->msg_iov= &c->iov[c->iovused];
+
+  if (c->udp && (c->srv_recv_addr_size > 0))
+  {
+    msg->msg_name= &c->srv_recv_addr;
+    msg->msg_namelen= c->srv_recv_addr_size;
+  }
+
+  c->msgbytes= 0;
+  c->msgused++;
+
+  if (c->udp)
+  {
+    /* Leave room for the UDP header, which we'll fill in later. */
+    return ms_add_iov(c, NULL, UDP_HEADER_SIZE);
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_add_msghdr */
+
+
+/**
+ * Ensures that there is room for another structure iovec in a connection's
+ * iov list.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_ensure_iov_space(ms_conn_t *c)
+{
+  assert(c != NULL);
+
+  if (c->iovused >= c->iovsize)
+  {
+    int i, iovnum;
+    struct iovec *new_iov= (struct iovec *)realloc(c->iov,
+                                                   ((size_t)c->iovsize
+                                                    * 2)
+                                                   * sizeof(struct iovec));
+    if (! new_iov)
+      return -1;
+
+    c->iov= new_iov;
+    c->iovsize*= 2;
+
+    /* Point all the msghdr structures at the new list. */
+    for (i= 0, iovnum= 0; i < c->msgused; i++)
+    {
+      c->msglist[i].msg_iov= &c->iov[iovnum];
+      iovnum+= (int)c->msglist[i].msg_iovlen;
+    }
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_ensure_iov_space */
+
+
+/**
+ * Adds data to the list of pending data that will be written out to a
+ * connection.
+ *
+ * @param c, pointer of the concurrency
+ * @param buf, the buffer includes data to send
+ * @param len, the data length in the buffer
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_add_iov(ms_conn_t *c, const void *buf, int len)
+{
+  struct msghdr *m;
+  int  leftover;
+  bool limit_to_mtu;
+
+  assert(c != NULL);
+
+  do
+  {
+    m= &c->msglist[c->msgused - 1];
+
+    /*
+     * Limit UDP packets, to UDP_MAX_PAYLOAD_SIZE bytes.
+     */
+    limit_to_mtu= c->udp;
+
+#ifdef IOV_MAX
+    /* We may need to start a new msghdr if this one is full. */
+    if ((m->msg_iovlen == IOV_MAX)
+        || (limit_to_mtu && (c->msgbytes >= UDP_MAX_SEND_PAYLOAD_SIZE)))
+    {
+      ms_add_msghdr(c);
+      m= &c->msglist[c->msgused - 1];
+    }
+#endif
+
+    if (ms_ensure_iov_space(c) != 0)
+      return -1;
+
+    /* If the fragment is too big to fit in the datagram, split it up */
+    if (limit_to_mtu && (len + c->msgbytes > UDP_MAX_SEND_PAYLOAD_SIZE))
+    {
+      leftover= len + c->msgbytes - UDP_MAX_SEND_PAYLOAD_SIZE;
+      len-= leftover;
+    }
+    else
+    {
+      leftover= 0;
+    }
+
+    m= &c->msglist[c->msgused - 1];
+    m->msg_iov[m->msg_iovlen].iov_base= (void *)buf;
+    m->msg_iov[m->msg_iovlen].iov_len= (size_t)len;
+
+    c->msgbytes+= len;
+    c->iovused++;
+    m->msg_iovlen++;
+
+    buf= ((char *)buf) + len;
+    len= leftover;
+  }
+  while (leftover > 0);
+
+  return EXIT_SUCCESS;
+} /* ms_add_iov */
+
+
+/**
+ * Constructs a set of UDP headers and attaches them to the outgoing messages.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_build_udp_headers(ms_conn_t *c)
+{
+  int i;
+  unsigned char *hdr;
+
+  assert(c != NULL);
+
+  c->request_id= ms_get_udp_request_id();
+
+  if (c->msgused > c->hdrsize)
+  {
+    void *new_hdrbuf;
+    if (c->hdrbuf)
+      new_hdrbuf= realloc(c->hdrbuf,
+                          (size_t)c->msgused * 2 * UDP_HEADER_SIZE);
+    else
+      new_hdrbuf= malloc((size_t)c->msgused * 2 * UDP_HEADER_SIZE);
+    if (! new_hdrbuf)
+      return -1;
+
+    c->hdrbuf= (unsigned char *)new_hdrbuf;
+    c->hdrsize= c->msgused * 2;
+  }
+
+  /* If this is a multi-packet request, drop it. */
+  if (c->udp && (c->msgused > 1))
+  {
+    fprintf(stderr, "multi-packet request for UDP not supported.\n");
+    return -1;
+  }
+
+  hdr= c->hdrbuf;
+  for (i= 0; i < c->msgused; i++)
+  {
+    c->msglist[i].msg_iov[0].iov_base= (void *)hdr;
+    c->msglist[i].msg_iov[0].iov_len= UDP_HEADER_SIZE;
+    *hdr++= (unsigned char)(c->request_id / 256);
+    *hdr++= (unsigned char)(c->request_id % 256);
+    *hdr++= (unsigned char)(i / 256);
+    *hdr++= (unsigned char)(i % 256);
+    *hdr++= (unsigned char)(c->msgused / 256);
+    *hdr++= (unsigned char)(c->msgused % 256);
+    *hdr++= (unsigned char)1;          /* support facebook memcached */
+    *hdr++= (unsigned char)0;
+    assert(hdr ==
+           ((unsigned char *)c->msglist[i].msg_iov[0].iov_base
+            + UDP_HEADER_SIZE));
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_build_udp_headers */
+
+
+/**
+ * Transmit the next chunk of data from our list of msgbuf structures.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return  TRANSMIT_COMPLETE   All done writing.
+ *          TRANSMIT_INCOMPLETE More data remaining to write.
+ *          TRANSMIT_SOFT_ERROR Can't write any more right now.
+ *          TRANSMIT_HARD_ERROR Can't write (c->state is set to conn_closing)
+ */
+static int ms_transmit(ms_conn_t *c)
+{
+  assert(c != NULL);
+
+  if ((c->msgcurr < c->msgused)
+      && (c->msglist[c->msgcurr].msg_iovlen == 0))
+  {
+    /* Finished writing the current msg; advance to the next. */
+    c->msgcurr++;
+  }
+
+  if (c->msgcurr < c->msgused)
+  {
+    ssize_t res;
+    struct msghdr *m= &c->msglist[c->msgcurr];
+
+    res= sendmsg(c->sfd, m, 0);
+    if (res > 0)
+    {
+      atomic_add_size(&ms_stats.bytes_written, res);
+
+      /* We've written some of the data. Remove the completed
+       *  iovec entries from the list of pending writes. */
+      while (m->msg_iovlen > 0 && res >= (ssize_t)m->msg_iov->iov_len)
+      {
+        res-= (ssize_t)m->msg_iov->iov_len;
+        m->msg_iovlen--;
+        m->msg_iov++;
+      }
+
+      /* Might have written just part of the last iovec entry;
+       *  adjust it so the next write will do the rest. */
+      if (res > 0)
+      {
+        m->msg_iov->iov_base= (void *)((unsigned char *)m->msg_iov->iov_base + res);
+        m->msg_iov->iov_len-= (size_t)res;
+      }
+      return TRANSMIT_INCOMPLETE;
+    }
+    if ((res == -1) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
+    {
+      if (! ms_update_event(c, EV_WRITE | EV_PERSIST))
+      {
+        fprintf(stderr, "Couldn't update event.\n");
+        ms_conn_set_state(c, conn_closing);
+        return TRANSMIT_HARD_ERROR;
+      }
+      return TRANSMIT_SOFT_ERROR;
+    }
+
+    /* if res==0 or res==-1 and error is not EAGAIN or EWOULDBLOCK,
+     *  we have a real error, on which we close the connection */
+    fprintf(stderr, "Failed to write, and not due to blocking.\n");
+
+    ms_conn_set_state(c, conn_closing);
+    return TRANSMIT_HARD_ERROR;
+  }
+  else
+  {
+    return TRANSMIT_COMPLETE;
+  }
+} /* ms_transmit */
+
+
+/**
+ * Shrinks a connection's buffers if they're too big.  This prevents
+ * periodic large "mget" response from server chewing lots of client
+ * memory.
+ *
+ * This should only be called in between requests since it can wipe output
+ * buffers!
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_conn_shrink(ms_conn_t *c)
+{
+  assert(c != NULL);
+
+  if (c->udp)
+    return;
+
+  if ((c->rsize > READ_BUFFER_HIGHWAT) && (c->rbytes < DATA_BUFFER_SIZE))
+  {
+    char *newbuf;
+
+    if (c->rcurr != c->rbuf)
+      memmove(c->rbuf, c->rcurr, (size_t)c->rbytes);
+
+    newbuf= (char *)realloc((void *)c->rbuf, DATA_BUFFER_SIZE);
+
+    if (newbuf)
+    {
+      c->rbuf= newbuf;
+      c->rsize= DATA_BUFFER_SIZE;
+    }
+    c->rcurr= c->rbuf;
+  }
+
+  if (c->udp && (c->rudpsize > UDP_DATA_BUFFER_HIGHWAT)
+      && (c->rudpbytes + UDP_MAX_PAYLOAD_SIZE < UDP_DATA_BUFFER_SIZE))
+  {
+    char *new_rbuf= (char *)realloc(c->rudpbuf, (size_t)c->rudpsize * 2);
+    if (new_rbuf)
+    {
+      c->rudpbuf= new_rbuf;
+      c->rudpsize= UDP_DATA_BUFFER_SIZE;
+    }
+    /* TODO check error condition? */
+  }
+
+  if (c->msgsize > MSG_LIST_HIGHWAT)
+  {
+    struct msghdr *newbuf= (struct msghdr *)realloc(
+      (void *)c->msglist,
+      MSG_LIST_INITIAL
+      * sizeof(c->msglist[0]));
+    if (newbuf)
+    {
+      c->msglist= newbuf;
+      c->msgsize= MSG_LIST_INITIAL;
+    }
+    /* TODO check error condition? */
+  }
+
+  if (c->iovsize > IOV_LIST_HIGHWAT)
+  {
+    struct iovec *newbuf= (struct iovec *)realloc((void *)c->iov,
+                                                  IOV_LIST_INITIAL
+                                                  * sizeof(c->iov[0]));
+    if (newbuf)
+    {
+      c->iov= newbuf;
+      c->iovsize= IOV_LIST_INITIAL;
+    }
+    /* TODO check return value */
+  }
+} /* ms_conn_shrink */
+
+
+/**
+ * Sets a connection's current state in the state machine. Any special
+ * processing that needs to happen on certain state transitions can
+ * happen here.
+ *
+ * @param c, pointer of the concurrency
+ * @param state, connection state
+ */
+static void ms_conn_set_state(ms_conn_t *c, int state)
+{
+  assert(c != NULL);
+
+  if (state != c->state)
+  {
+    if (state == conn_read)
+    {
+      ms_conn_shrink(c);
+    }
+    c->state= state;
+  }
+} /* ms_conn_set_state */
+
+
+/**
+ * update the event if socks change state. for example: when
+ * change the listen scoket read event to sock write event, or
+ * change socket handler, we could call this function.
+ *
+ * @param c, pointer of the concurrency
+ * @param new_flags, new event flags
+ *
+ * @return bool, if success, return true, else return false
+ */
+static bool ms_update_event(ms_conn_t *c, const int new_flags)
+{
+  assert(c != NULL);
+
+  struct event_base *base= c->event.ev_base;
+  if ((c->ev_flags == new_flags) && (ms_setting.rep_write_srv == 0)
+      && (! ms_setting.facebook_test || (c->total_sfds == 1)))
+  {
+    return true;
+  }
+
+  if (event_del(&c->event) == -1)
+  {
+    /* try to delete the event again */
+    if (event_del(&c->event) == -1)
+    {
+      return false;
+    }
+  }
+
+  event_set(&c->event,
+            c->sfd,
+            (short)new_flags,
+            ms_event_handler,
+            (void *)c);
+  event_base_set(base, &c->event);
+  c->ev_flags= (short)new_flags;
+
+  if (event_add(&c->event, NULL) == -1)
+  {
+    return false;
+  }
+
+  return true;
+} /* ms_update_event */
+
+
+/**
+ * If user want to get the expected throughput, we could limit
+ * the performance of memslap. we could give up some work and
+ * just wait a short time. The function is used to check this
+ * case.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return bool, if success, return true, else return false
+ */
+static bool ms_need_yield(ms_conn_t *c)
+{
+  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
+  int64_t tps= 0;
+  int64_t time_diff= 0;
+  struct timeval curr_time;
+  ms_task_t *task= &c->curr_task;
+
+  if (ms_setting.expected_tps > 0)
+  {
+    gettimeofday(&curr_time, NULL);
+    time_diff= ms_time_diff(&ms_thread->startup_time, &curr_time);
+    tps= (int64_t)(((task->get_opt + task->set_opt) / (uint64_t)time_diff) * 1000000);
+
+    /* current throughput is greater than expected throughput */
+    if (tps > ms_thread->thread_ctx->tps_perconn)
+    {
+      return true;
+    }
+  }
+
+  return false;
+} /* ms_need_yield */
+
+
+/**
+ * used to update the start time of each operation
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_update_start_time(ms_conn_t *c)
+{
+  ms_task_item_t *item= c->curr_task.item;
+
+  if ((ms_setting.stat_freq > 0) || c->udp
+      || ((c->currcmd.cmd == CMD_SET) && (item->exp_time > 0)))
+  {
+    gettimeofday(&c->start_time, NULL);
+    if ((c->currcmd.cmd == CMD_SET) && (item->exp_time > 0))
+    {
+      /* record the current time */
+      item->client_time= c->start_time.tv_sec;
+    }
+  }
+} /* ms_update_start_time */
+
+
+/**
+ * run the state machine
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_drive_machine(ms_conn_t *c)
+{
+  bool stop= false;
+
+  assert(c != NULL);
+
+  while (! stop)
+  {
+    switch (c->state)
+    {
+    case conn_read:
+      if (c->readval)
+      {
+        if (c->rbytes >= c->rvbytes)
+        {
+          ms_complete_nread(c);
+          break;
+        }
+      }
+      else
+      {
+        if (ms_try_read_line(c) != 0)
+        {
+          break;
+        }
+      }
+
+      if (ms_try_read_network(c) != 0)
+      {
+        break;
+      }
+
+      /* doesn't read all the response data, wait event wake up */
+      if (! c->currcmd.isfinish)
+      {
+        if (! ms_update_event(c, EV_READ | EV_PERSIST))
+        {
+          fprintf(stderr, "Couldn't update event.\n");
+          ms_conn_set_state(c, conn_closing);
+          break;
+        }
+        stop= true;
+        break;
+      }
+
+      /* we have no command line and no data to read from network, next write */
+      ms_conn_set_state(c, conn_write);
+      memcpy(&c->precmd, &c->currcmd, sizeof(ms_cmdstat_t));        /* replicate command state */
+
+      break;
+
+    case conn_write:
+      if (! c->ctnwrite && ms_need_yield(c))
+      {
+        usleep(10);
+
+        if (! ms_update_event(c, EV_WRITE | EV_PERSIST))
+        {
+          fprintf(stderr, "Couldn't update event.\n");
+          ms_conn_set_state(c, conn_closing);
+          break;
+        }
+        stop= true;
+        break;
+      }
+
+      if (! c->ctnwrite && (ms_exec_task(c) != 0))
+      {
+        ms_conn_set_state(c, conn_closing);
+        break;
+      }
+
+      /* record the start time before starting to send data if necessary */
+      if (! c->ctnwrite || (c->change_sfd && c->ctnwrite))
+      {
+        if (c->change_sfd)
+        {
+          c->change_sfd= false;
+        }
+        ms_update_start_time(c);
+      }
+
+      /* change sfd if necessary */
+      if (c->change_sfd)
+      {
+        c->ctnwrite= true;
+        stop= true;
+        break;
+      }
+
+      /* execute task until nothing need be written to network */
+      if (! c->ctnwrite && (c->msgcurr == c->msgused))
+      {
+        if (! ms_update_event(c, EV_WRITE | EV_PERSIST))
+        {
+          fprintf(stderr, "Couldn't update event.\n");
+          ms_conn_set_state(c, conn_closing);
+          break;
+        }
+        stop= true;
+        break;
+      }
+
+      switch (ms_transmit(c))
+      {
+      case TRANSMIT_COMPLETE:
+        /* we have no data to write to network, next wait repose */
+        if (! ms_update_event(c, EV_READ | EV_PERSIST))
+        {
+          fprintf(stderr, "Couldn't update event.\n");
+          ms_conn_set_state(c, conn_closing);
+          c->ctnwrite= false;
+          break;
+        }
+        ms_conn_set_state(c, conn_read);
+        c->ctnwrite= false;
+        stop= true;
+        break;
+
+      case TRANSMIT_INCOMPLETE:
+        c->ctnwrite= true;
+        break;                           /* Continue in state machine. */
+
+      case TRANSMIT_HARD_ERROR:
+        c->ctnwrite= false;
+        break;
+
+      case TRANSMIT_SOFT_ERROR:
+        c->ctnwrite= true;
+        stop= true;
+        break;
+
+      default:
+        break;
+      } /* switch */
+
+      break;
+
+    case conn_closing:
+      /* recovery mode, need reconnect if connection close */
+      if (ms_setting.reconnect && (! ms_global.time_out
+                                   || ((ms_setting.run_time == 0)
+                                       && (c->remain_exec_num > 0))))
+      {
+        if (ms_reconn(c) != 0)
+        {
+          ms_conn_close(c);
+          stop= true;
+          break;
+        }
+
+        ms_reset_conn(c, false);
+
+        if (c->total_sfds == 1)
+        {
+          if (! ms_update_event(c, EV_WRITE | EV_PERSIST))
+          {
+            fprintf(stderr, "Couldn't update event.\n");
+            ms_conn_set_state(c, conn_closing);
+            break;
+          }
+        }
+
+        break;
+      }
+      else
+      {
+        ms_conn_close(c);
+        stop= true;
+        break;
+      }
+
+    default:
+      assert(0);
+    } /* switch */
+  }
+} /* ms_drive_machine */
+
+
+/**
+ * the event handler of each thread
+ *
+ * @param fd, the file descriptor of socket
+ * @param which, event flag
+ * @param arg, argument
+ */
+void ms_event_handler(const int fd, const short which, void *arg)
+{
+  ms_conn_t *c= (ms_conn_t *)arg;
+
+  assert(c != NULL);
+
+  c->which= which;
+
+  /* sanity */
+  if (fd != c->sfd)
+  {
+    fprintf(stderr,
+            "Catastrophic: event fd: %d doesn't match conn fd: %d\n",
+            fd,
+            c->sfd);
+    ms_conn_close(c);
+    exit(1);
+  }
+  assert(fd == c->sfd);
+
+  ms_drive_machine(c);
+
+  /* wait for next event */
+} /* ms_event_handler */
+
+
+/**
+ * get the next socket descriptor index to run for replication
+ *
+ * @param c, pointer of the concurrency
+ * @param cmd, command(get or set )
+ *
+ * @return int, if success, return the index, else return EXIT_SUCCESS
+ */
+static uint32_t ms_get_rep_sock_index(ms_conn_t *c, int cmd)
+{
+  uint32_t sock_index= 0;
+  uint32_t i= 0;
+
+  if (c->total_sfds == 1)
+  {
+    return EXIT_SUCCESS;
+  }
+
+  if (ms_setting.rep_write_srv == 0)
+  {
+    return sock_index;
+  }
+
+  do
+  {
+    if (cmd == CMD_SET)
+    {
+      for (i= 0; i < ms_setting.rep_write_srv; i++)
+      {
+        if (c->tcpsfd[i] > 0)
+        {
+          break;
+        }
+      }
+
+      if (i == ms_setting.rep_write_srv)
+      {
+        /* random get one replication server to read */
+        sock_index= (uint32_t)random() % c->total_sfds;
+      }
+      else
+      {
+        /* random get one replication writing server to write */
+        sock_index= (uint32_t)random() % ms_setting.rep_write_srv;
+      }
+    }
+    else if (cmd == CMD_GET)
+    {
+      /* random get one replication server to read */
+      sock_index= (uint32_t)random() % c->total_sfds;
+    }
+  }
+  while (c->tcpsfd[sock_index] == 0);
+
+  return sock_index;
+} /* ms_get_rep_sock_index */
+
+
+/**
+ * get the next socket descriptor index to run
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, return the index
+ */
+static uint32_t ms_get_next_sock_index(ms_conn_t *c)
+{
+  uint32_t sock_index= 0;
+
+  do
+  {
+    sock_index= (++c->cur_idx == c->total_sfds) ? 0 : c->cur_idx;
+  }
+  while (c->tcpsfd[sock_index] == 0);
+
+  return sock_index;
+} /* ms_get_next_sock_index */
+
+
+/**
+ * update socket event of the connections
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_update_conn_sock_event(ms_conn_t *c)
+{
+  assert(c != NULL);
+
+  switch (c->currcmd.cmd)
+  {
+  case CMD_SET:
+    if (ms_setting.facebook_test && c->udp)
+    {
+      c->sfd= c->tcpsfd[0];
+      c->udp= false;
+      c->change_sfd= true;
+    }
+    break;
+
+  case CMD_GET:
+    if (ms_setting.facebook_test && ! c->udp)
+    {
+      c->sfd= c->udpsfd;
+      c->udp= true;
+      c->change_sfd= true;
+    }
+    break;
+
+  default:
+    break;
+  } /* switch */
+
+  if (! c->udp && (c->total_sfds > 1))
+  {
+    if (c->cur_idx != c->total_sfds)
+    {
+      if (ms_setting.rep_write_srv == 0)
+      {
+        c->cur_idx= ms_get_next_sock_index(c);
+      }
+      else
+      {
+        c->cur_idx= ms_get_rep_sock_index(c, c->currcmd.cmd);
+      }
+    }
+    else
+    {
+      /* must select the first sock of the connection at the beginning */
+      c->cur_idx= 0;
+    }
+
+    c->sfd= c->tcpsfd[c->cur_idx];
+    assert(c->sfd != 0);
+    c->change_sfd= true;
+  }
+
+  if (c->change_sfd)
+  {
+    if (! ms_update_event(c, EV_WRITE | EV_PERSIST))
+    {
+      fprintf(stderr, "Couldn't update event.\n");
+      ms_conn_set_state(c, conn_closing);
+      return -1;
+    }
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_update_conn_sock_event */
+
+
+/**
+ * for ASCII protocol, this function build the set command
+ * string and send the command.
+ *
+ * @param c, pointer of the concurrency
+ * @param item, pointer of task item which includes the object
+ *            information
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_build_ascii_write_buf_set(ms_conn_t *c, ms_task_item_t *item)
+{
+  int value_offset;
+  int write_len;
+  char *buffer= c->wbuf;
+
+  write_len= snprintf(buffer,
+                      c->wsize,
+                      " %u %d %d\r\n",
+                      0,
+                      item->exp_time,
+                      item->value_size);
+
+  if (write_len > c->wsize || write_len < 0)
+  {
+    /* ought to be always enough. just fail for simplicity */
+    fprintf(stderr, "output command line too long.\n");
+    return -1;
+  }
+
+  if (item->value_offset == INVALID_OFFSET)
+  {
+    value_offset= item->key_suffix_offset;
+  }
+  else
+  {
+    value_offset= item->value_offset;
+  }
+
+  if ((ms_add_iov(c, "set ", 4) != 0)
+      || (ms_add_iov(c, (char *)&item->key_prefix,
+                     (int)KEY_PREFIX_SIZE) != 0)
+      || (ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset],
+                     item->key_size - (int)KEY_PREFIX_SIZE) != 0)
+      || (ms_add_iov(c, buffer, write_len) != 0)
+      || (ms_add_iov(c, &ms_setting.char_block[value_offset],
+                     item->value_size) != 0)
+      || (ms_add_iov(c, "\r\n", 2) != 0)
+      || (c->udp && (ms_build_udp_headers(c) != 0)))
+  {
+    return -1;
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_build_ascii_write_buf_set */
+
+
+/**
+ * used to send set command to server
+ *
+ * @param c, pointer of the concurrency
+ * @param item, pointer of task item which includes the object
+ *            information
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+int ms_mcd_set(ms_conn_t *c, ms_task_item_t *item)
+{
+  assert(c != NULL);
+
+  c->currcmd.cmd= CMD_SET;
+  c->currcmd.isfinish= false;
+  c->currcmd.retstat= MCD_FAILURE;
+
+  if (ms_update_conn_sock_event(c) != 0)
+  {
+    return -1;
+  }
+
+  c->msgcurr= 0;
+  c->msgused= 0;
+  c->iovused= 0;
+  if (ms_add_msghdr(c) != 0)
+  {
+    fprintf(stderr, "Out of memory preparing request.");
+    return -1;
+  }
+
+  /* binary protocol */
+  if (c->protocol == binary_prot)
+  {
+    if (ms_build_bin_write_buf_set(c, item) != 0)
+    {
+      return -1;
+    }
+  }
+  else
+  {
+    if (ms_build_ascii_write_buf_set(c, item) != 0)
+    {
+      return -1;
+    }
+  }
+
+  atomic_add_size(&ms_stats.obj_bytes,
+                  item->key_size + item->value_size);
+  atomic_add_size(&ms_stats.cmd_set, 1);
+
+  return EXIT_SUCCESS;
+} /* ms_mcd_set */
+
+
+/**
+ * for ASCII protocol, this function build the get command
+ * string and send the command.
+ *
+ * @param c, pointer of the concurrency
+ * @param item, pointer of task item which includes the object
+ *            information
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_build_ascii_write_buf_get(ms_conn_t *c, ms_task_item_t *item)
+{
+  if ((ms_add_iov(c, "get ", 4) != 0)
+      || (ms_add_iov(c, (char *)&item->key_prefix,
+                     (int)KEY_PREFIX_SIZE) != 0)
+      || (ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset],
+                     item->key_size - (int)KEY_PREFIX_SIZE) != 0)
+      || (ms_add_iov(c, "\r\n", 2) != 0)
+      || (c->udp && (ms_build_udp_headers(c) != 0)))
+  {
+    return -1;
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_build_ascii_write_buf_get */
+
+
+/**
+ * used to send the get command to server
+ *
+ * @param c, pointer of the concurrency
+ * @param item, pointer of task item which includes the object
+ *            information
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+int ms_mcd_get(ms_conn_t *c, ms_task_item_t *item)
+{
+  assert(c != NULL);
+
+  c->currcmd.cmd= CMD_GET;
+  c->currcmd.isfinish= false;
+  c->currcmd.retstat= MCD_FAILURE;
+
+  if (ms_update_conn_sock_event(c) != 0)
+  {
+    return -1;
+  }
+
+  c->msgcurr= 0;
+  c->msgused= 0;
+  c->iovused= 0;
+  if (ms_add_msghdr(c) != 0)
+  {
+    fprintf(stderr, "Out of memory preparing request.");
+    return -1;
+  }
+
+  /* binary protocol */
+  if (c->protocol == binary_prot)
+  {
+    if (ms_build_bin_write_buf_get(c, item) != 0)
+    {
+      return -1;
+    }
+  }
+  else
+  {
+    if (ms_build_ascii_write_buf_get(c, item) != 0)
+    {
+      return -1;
+    }
+  }
+
+  atomic_add_size(&ms_stats.cmd_get, 1);
+
+  return EXIT_SUCCESS;
+} /* ms_mcd_get */
+
+
+/**
+ * for ASCII protocol, this function build the multi-get command
+ * string and send the command.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_build_ascii_write_buf_mlget(ms_conn_t *c)
+{
+  ms_task_item_t *item;
+
+  if (ms_add_iov(c, "get", 3) != 0)
+  {
+    return -1;
+  }
+
+  for (int i= 0; i < c->mlget_task.mlget_num; i++)
+  {
+    item= c->mlget_task.mlget_item[i].item;
+    assert(item != NULL);
+    if ((ms_add_iov(c, " ", 1) != 0)
+        || (ms_add_iov(c, (char *)&item->key_prefix,
+                       (int)KEY_PREFIX_SIZE) != 0)
+        || (ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset],
+                       item->key_size - (int)KEY_PREFIX_SIZE) != 0))
+    {
+      return -1;
+    }
+  }
+
+  if ((ms_add_iov(c, "\r\n", 2) != 0)
+      || (c->udp && (ms_build_udp_headers(c) != 0)))
+  {
+    return -1;
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_build_ascii_write_buf_mlget */
+
+
+/**
+ * used to send the multi-get command to server
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+int ms_mcd_mlget(ms_conn_t *c)
+{
+  ms_task_item_t *item;
+
+  assert(c != NULL);
+  assert(c->mlget_task.mlget_num >= 1);
+
+  c->currcmd.cmd= CMD_GET;
+  c->currcmd.isfinish= false;
+  c->currcmd.retstat= MCD_FAILURE;
+
+  if (ms_update_conn_sock_event(c) != 0)
+  {
+    return -1;
+  }
+
+  c->msgcurr= 0;
+  c->msgused= 0;
+  c->iovused= 0;
+  if (ms_add_msghdr(c) != 0)
+  {
+    fprintf(stderr, "Out of memory preparing request.");
+    return -1;
+  }
+
+  /* binary protocol */
+  if (c->protocol == binary_prot)
+  {
+    if (ms_build_bin_write_buf_mlget(c) != 0)
+    {
+      return -1;
+    }
+  }
+  else
+  {
+    if (ms_build_ascii_write_buf_mlget(c) != 0)
+    {
+      return -1;
+    }
+  }
+
+  /* decrease operation time of each item */
+  for (int i= 0; i < c->mlget_task.mlget_num; i++)
+  {
+    item= c->mlget_task.mlget_item[i].item;
+    atomic_add_size(&ms_stats.cmd_get, 1);
+  }
+
+  (void)item;
+
+  return EXIT_SUCCESS;
+} /* ms_mcd_mlget */
+
+
+/**
+ * binary protocol support
+ */
+
+/**
+ * for binary protocol, parse the response of server
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_bin_process_response(ms_conn_t *c)
+{
+  const char *errstr= NULL;
+
+  assert(c != NULL);
+
+  uint32_t bodylen= c->binary_header.response.bodylen;
+  uint8_t  opcode= c->binary_header.response.opcode;
+  uint16_t status= c->binary_header.response.status;
+
+  if (bodylen > 0)
+  {
+    c->rvbytes= (int32_t)bodylen;
+    c->readval= true;
+    return EXIT_FAILURE;
+  }
+  else
+  {
+    switch (status)
+    {
+    case PROTOCOL_BINARY_RESPONSE_SUCCESS:
+      if (opcode == PROTOCOL_BINARY_CMD_SET)
+      {
+        c->currcmd.retstat= MCD_STORED;
+      }
+      else if (opcode == PROTOCOL_BINARY_CMD_DELETE)
+      {
+        c->currcmd.retstat= MCD_DELETED;
+      }
+      else if (opcode == PROTOCOL_BINARY_CMD_GET)
+      {
+        c->currcmd.retstat= MCD_END;
+      }
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_ENOMEM:
+      errstr= "Out of memory";
+      c->currcmd.retstat= MCD_SERVER_ERROR;
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
+      errstr= "Unknown command";
+      c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT:
+      errstr= "Not found";
+      c->currcmd.retstat= MCD_NOTFOUND;
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_EINVAL:
+      errstr= "Invalid arguments";
+      c->currcmd.retstat= MCD_PROTOCOL_ERROR;
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS:
+      errstr= "Data exists for key.";
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_E2BIG:
+      errstr= "Too large.";
+      c->currcmd.retstat= MCD_SERVER_ERROR;
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_NOT_STORED:
+      errstr= "Not stored.";
+      c->currcmd.retstat= MCD_NOTSTORED;
+      break;
+
+    default:
+      errstr= "Unknown error";
+      c->currcmd.retstat= MCD_UNKNOWN_READ_FAILURE;
+      break;
+    } /* switch */
+
+    if (errstr != NULL)
+    {
+      fprintf(stderr, "%s\n", errstr);
+    }
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_bin_process_response */
+
+
+/* build binary header and add the header to the buffer to send */
+
+/**
+ * build binary header and add the header to the buffer to send
+ *
+ * @param c, pointer of the concurrency
+ * @param opcode, operation code
+ * @param hdr_len, length of header
+ * @param key_len, length of key
+ * @param body_len. length of body
+ */
+static void ms_add_bin_header(ms_conn_t *c,
+                              uint8_t opcode,
+                              uint8_t hdr_len,
+                              uint16_t key_len,
+                              uint32_t body_len)
+{
+  protocol_binary_request_header *header;
+
+  assert(c != NULL);
+
+  header= (protocol_binary_request_header *)c->wcurr;
+
+  header->request.magic= (uint8_t)PROTOCOL_BINARY_REQ;
+  header->request.opcode= (uint8_t)opcode;
+  header->request.keylen= htons(key_len);
+
+  header->request.extlen= (uint8_t)hdr_len;
+  header->request.datatype= (uint8_t)PROTOCOL_BINARY_RAW_BYTES;
+  header->request.vbucket= 0;
+
+  header->request.bodylen= htonl(body_len);
+  header->request.opaque= 0;
+  header->request.cas= 0;
+
+  ms_add_iov(c, c->wcurr, sizeof(header->request));
+} /* ms_add_bin_header */
+
+
+/**
+ * add the key to the socket write buffer array
+ *
+ * @param c, pointer of the concurrency
+ * @param item, pointer of task item which includes the object
+ *            information
+ */
+static void ms_add_key_to_iov(ms_conn_t *c, ms_task_item_t *item)
+{
+  ms_add_iov(c, (char *)&item->key_prefix, (int)KEY_PREFIX_SIZE);
+  ms_add_iov(c, &ms_setting.char_block[item->key_suffix_offset],
+             item->key_size - (int)KEY_PREFIX_SIZE);
+}
+
+
+/**
+ * for binary protocol, this function build the set command
+ * and add the command to send buffer array.
+ *
+ * @param c, pointer of the concurrency
+ * @param item, pointer of task item which includes the object
+ *            information
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_build_bin_write_buf_set(ms_conn_t *c, ms_task_item_t *item)
+{
+  assert(c->wbuf == c->wcurr);
+
+  int value_offset;
+  protocol_binary_request_set *rep= (protocol_binary_request_set *)c->wcurr;
+  uint16_t keylen= (uint16_t)item->key_size;
+  uint32_t bodylen= (uint32_t)sizeof(rep->message.body)
+                    + (uint32_t)keylen + (uint32_t)item->value_size;
+
+  ms_add_bin_header(c,
+                    PROTOCOL_BINARY_CMD_SET,
+                    sizeof(rep->message.body),
+                    keylen,
+                    bodylen);
+  rep->message.body.flags= 0;
+  rep->message.body.expiration= htonl((uint32_t)item->exp_time);
+  ms_add_iov(c, &rep->message.body, sizeof(rep->message.body));
+  ms_add_key_to_iov(c, item);
+
+  if (item->value_offset == INVALID_OFFSET)
+  {
+    value_offset= item->key_suffix_offset;
+  }
+  else
+  {
+    value_offset= item->value_offset;
+  }
+  ms_add_iov(c, &ms_setting.char_block[value_offset], item->value_size);
+
+  return EXIT_SUCCESS;
+} /* ms_build_bin_write_buf_set */
+
+
+/**
+ * for binary protocol, this function build the get command and
+ * add the command to send buffer array.
+ *
+ * @param c, pointer of the concurrency
+ * @param item, pointer of task item which includes the object
+ *            information
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_build_bin_write_buf_get(ms_conn_t *c, ms_task_item_t *item)
+{
+  assert(c->wbuf == c->wcurr);
+
+  ms_add_bin_header(c, PROTOCOL_BINARY_CMD_GET, 0, (uint16_t)item->key_size,
+                    (uint32_t)item->key_size);
+  ms_add_key_to_iov(c, item);
+
+  return EXIT_SUCCESS;
+} /* ms_build_bin_write_buf_get */
+
+
+/**
+ * for binary protocol, this function build the multi-get
+ * command and add the command to send buffer array.
+ *
+ * @param c, pointer of the concurrency
+ * @param item, pointer of task item which includes the object
+ *            information
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_build_bin_write_buf_mlget(ms_conn_t *c)
+{
+  ms_task_item_t *item;
+
+  assert(c->wbuf == c->wcurr);
+
+  for (int i= 0; i < c->mlget_task.mlget_num; i++)
+  {
+    item= c->mlget_task.mlget_item[i].item;
+    assert(item != NULL);
+
+    ms_add_bin_header(c,
+                      PROTOCOL_BINARY_CMD_GET,
+                      0,
+                      (uint16_t)item->key_size,
+                      (uint32_t)item->key_size);
+    ms_add_key_to_iov(c, item);
+    c->wcurr+= sizeof(protocol_binary_request_get);
+  }
+
+  c->wcurr= c->wbuf;
+
+  return EXIT_SUCCESS;
+} /* ms_build_bin_write_buf_mlget */
diff --git a/src/bin/ms_conn.h b/src/bin/ms_conn.h
new file mode 100644 (file)
index 0000000..943965c
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * File:   ms_conn.h
+ * Author: Mingqiang Zhuang
+ *
+ * Created on February 10, 2009
+ *
+ * (c) Copyright 2009, Schooner Information Technology, Inc.
+ * http://www.schoonerinfotech.com/
+ *
+ */
+#ifndef MS_CONN_H
+#define MS_CONN_H
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <event.h>
+#include <netdb.h>
+
+#include "ms_task.h"
+#include <libmemcachedprotocol-0.0/binary.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DATA_BUFFER_SIZE             (1024 * 1024 + 2048) /* read buffer, 1M + 2k, enough for the max value(1M) */
+#define WRITE_BUFFER_SIZE            (32 * 1024)          /* write buffer, 32k */
+#define UDP_DATA_BUFFER_SIZE         (1 * 1024 * 1024)    /* read buffer for UDP, 1M */
+#define UDP_MAX_PAYLOAD_SIZE         1400                 /* server limit UDP payload size */
+#define UDP_MAX_SEND_PAYLOAD_SIZE    1400                 /* mtu size is 1500 */
+#define UDP_HEADER_SIZE              8                    /* UDP header size */
+#define MAX_SENDBUF_SIZE             (256 * 1024 * 1024)  /* Maximum socket buffer size */
+#define SOCK_WAIT_TIMEOUT            30                   /* maximum waiting time of UDP, 30s */
+#define MAX_UDP_PACKET               (1 << 16)            /* maximum UDP packets, 65536 */
+
+/* Initial size of the sendmsg() scatter/gather array. */
+#define IOV_LIST_INITIAL             400
+
+/* Initial number of sendmsg() argument structures to allocate. */
+#define MSG_LIST_INITIAL             10
+
+/* High water marks for buffer shrinking */
+#define READ_BUFFER_HIGHWAT          (2 * DATA_BUFFER_SIZE)
+#define UDP_DATA_BUFFER_HIGHWAT      (4 * UDP_DATA_BUFFER_SIZE)
+#define IOV_LIST_HIGHWAT             600
+#define MSG_LIST_HIGHWAT             100
+
+/* parse udp header */
+#define HEADER_TO_REQID(ptr)      ((uint16_t)*ptr * 256 \
+                                   + (uint16_t)*(ptr + 1))
+#define HEADER_TO_SEQNUM(ptr)     ((uint16_t)*(ptr        \
+                                               + 2) * 256 \
+                                   + (uint16_t)*(ptr + 3))
+#define HEADER_TO_PACKETS(ptr)    ((uint16_t)*(ptr        \
+                                               + 4) * 256 \
+                                   + (uint16_t)*(ptr + 5))
+
+/* states of connection */
+enum conn_states
+{
+  conn_read,         /* reading in a command line */
+  conn_write,        /* writing out a simple response */
+  conn_closing      /* closing this connection */
+};
+
+/* returned states of memcached command */
+enum mcd_ret
+{
+  MCD_SUCCESS,                      /* command success */
+  MCD_FAILURE,                      /* command failure */
+  MCD_UNKNOWN_READ_FAILURE,         /* unknown read failure */
+  MCD_PROTOCOL_ERROR,               /* protocol error */
+  MCD_CLIENT_ERROR,                 /* client error, wrong command */
+  MCD_SERVER_ERROR,                 /* server error, server run command failed */
+  MCD_DATA_EXISTS,                  /* object is existent in server */
+  MCD_NOTSTORED,                    /* server doesn't set the object successfully */
+  MCD_STORED,                       /* server set the object successfully */
+  MCD_NOTFOUND,                     /* server not find the object */
+  MCD_END,                          /* end of the response of get command */
+  MCD_DELETED,                      /* server delete the object successfully */
+  MCD_STAT                         /* response of stats command */
+};
+
+/* used to store the current or previous running command state */
+typedef struct cmdstat
+{
+  int cmd;                  /* command name */
+  int retstat;              /* return state of this command */
+  bool isfinish;            /* if it read all the response data */
+  uint64_t key_prefix;      /* key prefix */
+} ms_cmdstat_t;
+
+/* udp packet structure */
+typedef struct udppkt
+{
+  uint8_t *header;          /* udp header of the packet */
+  char *data;               /* udp data of the packet */
+  int rbytes;               /* number of data in the packet */
+  int copybytes;            /* number of copied data in the packet */
+} ms_udppkt_t;
+
+/* three protocols supported */
+enum protocol
+{
+  ascii_prot = 3,           /* ASCII protocol */
+  binary_prot              /* binary protocol */
+};
+
+/**
+ *  concurrency structure
+ *
+ *  Each thread has a libevent to manage the events of network.
+ *  Each thread has one or more self-governed concurrencies;
+ *  each concurrency has one or more socket connections. This
+ *  concurrency structure includes all the private variables of
+ *  the concurrency.
+ */
+typedef struct conn
+{
+  uint32_t conn_idx;             /* connection index in the thread */
+  int sfd;                  /* current tcp sock handler of the connection structure */
+  int udpsfd;               /* current udp sock handler of the connection structure*/
+  int state;                /* state of the connection */
+  struct event event;       /* event for libevent */
+  short ev_flags;           /* event flag for libevent */
+  short which;              /* which events were just triggered */
+  bool change_sfd;          /* whether change sfd */
+
+  int *tcpsfd;              /* TCP sock array */
+  uint32_t total_sfds;           /* how many socks in the tcpsfd array */
+  uint32_t alive_sfds;           /* alive socks */
+  uint32_t cur_idx;              /* current sock index in tcpsfd array */
+
+  ms_cmdstat_t precmd;      /* previous command state */
+  ms_cmdstat_t currcmd;     /* current command state */
+
+  char *rbuf;               /* buffer to read commands into */
+  char *rcurr;              /* but if we parsed some already, this is where we stopped */
+  int rsize;                /* total allocated size of rbuf */
+  int rbytes;               /* how much data, starting from rcur, do we have unparsed */
+
+  bool readval;             /* read value state, read known data size */
+  int rvbytes;              /* total value size need to read */
+
+  char *wbuf;               /* buffer to write commands out */
+  char *wcurr;              /* for multi-get, where we stopped */
+  int wsize;                /* total allocated size of wbuf */
+  bool ctnwrite;            /* continue to write */
+
+  /* data for the mwrite state */
+  struct iovec *iov;
+  int iovsize;              /* number of elements allocated in iov[] */
+  int iovused;              /* number of elements used in iov[] */
+
+  struct msghdr *msglist;
+  int msgsize;              /* number of elements allocated in msglist[] */
+  int msgused;              /* number of elements used in msglist[] */
+  int msgcurr;              /* element in msglist[] being transmitted now */
+  int msgbytes;             /* number of bytes in current msg */
+
+  /* data for UDP clients */
+  bool udp;                          /* is this is a UDP "connection" */
+  uint32_t request_id;                   /* UDP request ID of current operation, if this is a UDP "connection" */
+  uint8_t *hdrbuf;                  /* udp packet headers */
+  int hdrsize;                      /* number of headers' worth of space is allocated */
+  struct  sockaddr srv_recv_addr;   /* Sent the most recent request to which server */
+  socklen_t srv_recv_addr_size;
+
+  /* udp read buffer */
+  char *rudpbuf;                    /* buffer to read commands into for udp */
+  int rudpsize;                     /* total allocated size of rudpbuf */
+  int rudpbytes;                    /* how much data, starting from rudpbuf */
+
+  /* order udp packet */
+  ms_udppkt_t *udppkt;              /* the offset of udp packet in rudpbuf */
+  int packets;                      /* number of total packets need to read */
+  int recvpkt;                      /* number of received packets */
+  int pktcurr;                      /* current packet in rudpbuf being ordered */
+  int ordcurr;                      /* current ordered packet */
+
+  ms_task_item_t *item_win;         /* task sequence */
+  int win_size;                     /* current task window size */
+  uint64_t set_cursor;              /* current set item index in the item window */
+  ms_task_t curr_task;              /* current running task */
+  ms_mlget_task_t mlget_task;       /* multi-get task */
+
+  int warmup_num;                   /* to run how many warm up operations*/
+  int remain_warmup_num;            /* left how many warm up operations to run */
+  int64_t exec_num;                 /* to run how many task operations */
+  int64_t remain_exec_num;          /* how many remained task operations to run */
+
+  /* response time statistic and time out control */
+  struct timeval start_time;        /* start time of current operation(s) */
+  struct timeval end_time;          /* end time of current operation(s) */
+
+  /* Binary protocol stuff */
+  protocol_binary_response_header binary_header;    /* local temporary binary header */
+  enum protocol protocol;                           /* which protocol this connection speaks */
+} ms_conn_t;
+
+/* used to generate the key prefix */
+uint64_t ms_get_key_prefix(void);
+
+
+/**
+ * setup a connection, each connection structure of each
+ * thread must call this function to initialize.
+ */
+int ms_setup_conn(ms_conn_t *c);
+
+
+/* after one operation completes, reset the connection */
+void ms_reset_conn(ms_conn_t *c, bool timeout);
+
+
+/**
+ *  reconnect several disconnected socks in the connection
+ *  structure, the ever-1-second timer of the thread will check
+ *  whether some socks in the connections disconnect. if
+ *  disconnect, reconnect the sock.
+ */
+int ms_reconn_socks(ms_conn_t *c);
+
+
+/* used to send set command to server */
+int ms_mcd_set(ms_conn_t *c, ms_task_item_t *item);
+
+
+/* used to send the get command to server */
+int ms_mcd_get(ms_conn_t *c, ms_task_item_t *item);
+
+
+/* used to send the multi-get command to server */
+int ms_mcd_mlget(ms_conn_t *c);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of MS_CONN_H */
diff --git a/src/bin/ms_memslap.h b/src/bin/ms_memslap.h
new file mode 100644 (file)
index 0000000..9575a81
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * File:   ms_memslap.h
+ * Author: Mingqiang Zhuang
+ *
+ * Created on February 10, 2009
+ *
+ * (c) Copyright 2009, Schooner Information Technology, Inc.
+ * http://www.schoonerinfotech.com/
+ *
+ */
+#ifndef MS_MEMSLAP_H
+#define MS_MEMSLAP_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <pthread.h>
+#if !defined(__cplusplus)
+# include <stdbool.h>
+#endif
+#include <math.h>
+
+#include "ms_stats.h"
+#include "ms_atomic.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* command line option  */
+typedef enum
+{
+  OPT_VERSION= 'V',
+  OPT_HELP= 'h',
+  OPT_UDP= 'U',
+  OPT_SERVERS= 's',
+  OPT_EXECUTE_NUMBER= 'x',
+  OPT_THREAD_NUMBER= 'T',
+  OPT_CONCURRENCY= 'c',
+  OPT_FIXED_LTH= 'X',
+  OPT_VERIFY= 'v',
+  OPT_GETS_DIVISION= 'd',
+  OPT_TIME= 't',
+  OPT_CONFIG_CMD= 'F',
+  OPT_WINDOW_SIZE= 'w',
+  OPT_EXPIRE= 'e',
+  OPT_STAT_FREQ= 'S',
+  OPT_RECONNECT= 'R',
+  OPT_VERBOSE= 'b',
+  OPT_FACEBOOK_TEST= 'a',
+  OPT_SOCK_PER_CONN= 'n',
+  OPT_BINARY_PROTOCOL= 'B',
+  OPT_OVERWRITE= 'o',
+  OPT_TPS= 'P',
+  OPT_REP_WRITE_SRV= 'p'
+} ms_options_t;
+
+/* global statistic of response time */
+typedef struct statistic
+{
+  pthread_mutex_t stat_mutex;       /* synchronize the following members */
+
+  ms_stat_t get_stat;               /* statistics of get command */
+  ms_stat_t set_stat;               /* statistics of set command */
+  ms_stat_t total_stat;             /* statistics of both get and set commands */
+} ms_statistic_t;
+
+/* global status statistic structure */
+typedef struct stats
+{
+  ATOMIC uint32_t active_conns;   /* active connections */
+  ATOMIC size_t bytes_read;       /* read bytes */
+  ATOMIC size_t bytes_written;    /* written bytes */
+  ATOMIC size_t obj_bytes;        /* object bytes */
+  ATOMIC size_t pre_cmd_get;      /* previous total get command count */
+  ATOMIC size_t pre_cmd_set;      /* previous total set command count */
+  ATOMIC size_t cmd_get;          /* current total get command count */
+  ATOMIC size_t cmd_set;          /* current total set command count */
+  ATOMIC size_t get_misses;       /* total objects of get miss */
+  ATOMIC size_t vef_miss;         /* total objects of verification miss  */
+  ATOMIC size_t vef_failed;       /* total objects of verification failed  */
+  ATOMIC size_t unexp_unget;      /* total objects which is unexpired but not get */
+  ATOMIC size_t exp_get;          /* total objects which is expired but get  */
+  ATOMIC size_t pkt_disorder;     /* disorder packages of UDP */
+  ATOMIC size_t pkt_drop;         /* packages dropped of UDP */
+  ATOMIC size_t udp_timeout;      /* how many times timeout of UDP happens */
+} ms_stats_t;
+
+/* lock adapter */
+typedef struct sync_lock
+{
+  uint32_t count;
+  pthread_mutex_t lock;
+  pthread_cond_t cond;
+} ms_sync_lock_t;
+
+/* global variable structure */
+typedef struct global
+{
+  /* synchronize lock */
+  ms_sync_lock_t init_lock;
+  ms_sync_lock_t warmup_lock;
+  ms_sync_lock_t run_lock;
+
+  /* mutex for outputing error log synchronously when memslap crashes */
+  pthread_mutex_t quit_mutex;
+
+  /* mutex for generating key prefix */
+  pthread_mutex_t seq_mutex;
+
+  /* global synchronous flags for slap mode */
+  bool finish_warmup;
+  bool time_out;
+} ms_global_t;
+
+/* global structure */
+ms_global_t ms_global;
+
+/* global stats information structure */
+ms_stats_t ms_stats;
+
+/* global statistic structure */
+ms_statistic_t ms_statistic;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of MS_MEMSLAP_H */
diff --git a/src/bin/ms_setting.c b/src/bin/ms_setting.c
new file mode 100644 (file)
index 0000000..eafe459
--- /dev/null
@@ -0,0 +1,1068 @@
+/*
+ * File:   ms_setting.c
+ * Author: Mingqiang Zhuang
+ *
+ * Created on February 10, 2009
+ *
+ * (c) Copyright 2009, Schooner Information Technology, Inc.
+ * http://www.schoonerinfotech.com/
+ *
+ */
+
+#include "mem_config.h"
+
+#include <libmemcached/memcached.h>
+
+#include <ctype.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <pwd.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+
+
+#include "ms_setting.h"
+#include "ms_conn.h"
+
+#define MAX_EXEC_NUM               0x4000000000000000      /* 1 << 62 */
+#define ADDR_ALIGN(addr)    ((addr + 15) & ~(16 - 1))      /* 16 bytes aligned */
+#define RAND_CHAR_SIZE             (10 * 1024 * 1024)      /* 10M character table */
+#define RESERVED_RAND_CHAR_SIZE    (2 * 1024 * 1024)       /* reserved 2M to avoid pointer sloping over */
+
+#define DEFAULT_CONFIG_NAME ".memslap.cnf"
+
+#define DEFAULT_THREADS_NUM        1                       /* default start one thread */
+#define DEFAULT_CONNS_NUM          16                      /* default each thread with 16 connections */
+#define DEFAULT_EXE_NUM            0                       /* default execute number is 0 */
+#define DEFAULT_VERIFY_RATE        0.0                     /* default it doesn't do data verification */
+#define DEFAULT_OVERWRITE_RATE     0.0                     /* default it doesn't do overwrite */
+#define DEFAULT_DIV                1                       /* default it runs single get */
+#define DEFAULT_RUN_TIME           600                     /* default run time 10 minutes */
+#define DEFAULT_WINDOW_SIZE        (10 * UNIT_ITEMS_COUNT) /* default window size is 10k */
+#define DEFAULT_SOCK_PER_CONN      1                       /* default socks per connection is 1 */
+
+/* Use this for string generation */
+#define CHAR_COUNT                 64 /* number of characters used to generate character table */
+const char ALPHANUMBERICS[]=
+  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-";
+
+ms_setting_st ms_setting;       /* store the settings specified by user */
+
+
+/* read setting from configuration file */
+static void ms_get_serverlist(char *str);
+static uint32_t ms_get_cpu_count(void);
+ms_conf_type_t ms_get_conf_type(char *line);
+static int ms_is_line_data(char *line);
+static int ms_read_is_data(char *line, ssize_t nread);
+static void ms_no_config_file(void);
+static void ms_parse_cfg_file(char *cfg_file);
+
+
+/* initialize setting structure */
+static void ms_init_random_block(void);
+static void ms_calc_avg_size(void);
+static int ms_shuffle_distr(ms_distr_t *distr, int length);
+static void ms_build_distr(void);
+static void ms_print_setting(void);
+static void ms_setting_slapmode_init_pre(void);
+static void ms_setting_slapmode_init_post(void);
+
+#if !defined(HAVE_GETLINE)
+#include <limits.h>
+static ssize_t getline (char **line, size_t *line_size, FILE *fp)
+{
+  char delim= '\n';
+  ssize_t result= 0;
+  size_t cur_len= 0;
+
+  if (line == NULL || line_size == NULL || fp == NULL)
+  {
+    errno = EINVAL;
+    return -1;
+  }
+
+  if (*line == NULL || *line_size == 0)
+  {
+    char *new_line;
+    *line_size = 120;
+    new_line= (char *) realloc (*line, *line_size);
+    if (new_line == NULL)
+    {
+      result= -1;
+      return result;
+    }
+    *line= new_line;
+  }
+
+  for (;;)
+  {
+    int i= getc(fp);
+    if (i == EOF)
+    {
+      result = -1;
+      break;
+    }
+
+    /* Make enough space for len+1 (for final NUL) bytes.  */
+    if (cur_len + 1 >= *line_size)
+    {
+      size_t needed_max=
+        SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
+      size_t needed= (2 * (*line_size)) + 1;
+      char *new_line;
+
+      if (needed_max < needed)
+        needed= needed_max;
+      if (cur_len + 1 >= needed)
+      {
+        result= -1;
+        errno= EOVERFLOW;
+        return result;
+      }
+
+      new_line= (char *)realloc(*line, needed);
+      if (new_line == NULL)
+      {
+        result= -1;
+        return result;
+      }
+
+      *line= new_line;
+      *line_size= needed;
+    }
+
+    (*line)[cur_len]= (char)i;
+    cur_len++;
+
+    if (i == delim)
+      break;
+  }
+  (*line)[cur_len] = '\0';
+  if (cur_len != 0)
+    return (ssize_t)cur_len;
+  return result;
+}
+#endif
+
+/**
+ * parse the server list string, and build the servers
+ * information structure array. this function is used to parse
+ * the command line options specified by user.
+ *
+ * @param str, the string of server list
+ */
+static void ms_get_serverlist(char *str)
+{
+  ms_mcd_server_t *srvs= NULL;
+
+  /**
+   * Servers list format is like this. For example:
+   * "localhost:11108, localhost:11109"
+   */
+  memcached_server_st *server_pool;
+  server_pool = memcached_servers_parse(str);
+
+  for (uint32_t loop= 0; loop < memcached_server_list_count(server_pool); loop++)
+  {
+    assert(ms_setting.srv_cnt < ms_setting.total_srv_cnt);
+    strcpy(ms_setting.servers[ms_setting.srv_cnt].srv_host_name, server_pool[loop].hostname);
+    ms_setting.servers[ms_setting.srv_cnt].srv_port= server_pool[loop].port;
+    ms_setting.servers[ms_setting.srv_cnt].disconn_cnt= 0;
+    ms_setting.servers[ms_setting.srv_cnt].reconn_cnt= 0;
+    ms_setting.srv_cnt++;
+
+    if (ms_setting.srv_cnt >= ms_setting.total_srv_cnt)
+    {
+      srvs= (ms_mcd_server_t *)realloc( ms_setting.servers,
+                                        (size_t)ms_setting.total_srv_cnt * sizeof(ms_mcd_server_t) * 2);
+      if (srvs == NULL)
+      {
+        fprintf(stderr, "Can't reallocate servers structure.\n");
+        exit(1);
+      }
+      ms_setting.servers= srvs;
+      ms_setting.total_srv_cnt*= 2;
+    }
+  }
+
+  memcached_server_free(server_pool);
+} /* ms_get_serverlist */
+
+
+/**
+ * used to get the CPU count of the current system
+ *
+ * @return return the cpu count if get, else return EXIT_FAILURE
+ */
+static uint32_t ms_get_cpu_count()
+{
+#ifdef HAVE__SC_NPROCESSORS_ONLN
+  return sysconf(_SC_NPROCESSORS_CONF);
+
+#else
+# ifdef HAVE_CPU_SET_T
+  int cpu_count= 0;
+  cpu_set_t cpu_set;
+
+  sched_getaffinity(0, sizeof(cpu_set_t), &cpu_set);
+
+  for (int i= 0; i < (sizeof(cpu_set_t) * 8); i++)
+  {
+    if (CPU_ISSET(i, &cpu_set))
+    {
+      cpu_count++;
+    }
+  }
+
+  return cpu_count;
+
+# endif
+#endif
+
+  /* the system with one cpu at least */
+  return EXIT_FAILURE;
+} /* ms_get_cpu_count */
+
+
+/**
+ * used to get the configure type based on the type string read
+ * from the configuration file.
+ *
+ * @param line, string of one line
+ *
+ * @return ms_conf_type_t
+ */
+ms_conf_type_t ms_get_conf_type(char *line)
+{
+  if (! memcmp(line, "key", strlen("key")))
+  {
+    return CONF_KEY;
+  }
+  else if (! memcmp(line, "value", strlen("value")))
+  {
+    return CONF_VALUE;
+  }
+  else if (! memcmp(line, "cmd", strlen("cmd")))
+  {
+    return CONF_CMD;
+  }
+  else
+  {
+    return CONF_NULL;
+  }
+} /* ms_get_conf_type */
+
+
+/**
+ * judge whether the line is a line with useful data. used to
+ * parse the configuration file.
+ *
+ * @param line, string of one line
+ *
+ * @return if success, return EXIT_FAILURE, else return EXIT_SUCCESS
+ */
+static int ms_is_line_data(char *line)
+{
+  assert(line != NULL);
+
+  char *begin_ptr= line;
+
+  while (isspace(*begin_ptr))
+  {
+    begin_ptr++;
+  }
+  if ((begin_ptr[0] == '\0') || (begin_ptr[0] == '#'))
+    return EXIT_SUCCESS;
+
+  return EXIT_FAILURE;
+} /* ms_is_line_data */
+
+
+/**
+ * function to bypass blank line and comments
+ *
+ * @param line, string of one line
+ * @param nread, length of the line
+ *
+ * @return if it's EOF or not line data, return EXIT_SUCCESS, else return EXIT_FAILURE
+ */
+static int ms_read_is_data(char *line, ssize_t nread)
+{
+  if ((nread == EOF) || ! ms_is_line_data(line))
+    return EXIT_SUCCESS;
+
+  return EXIT_FAILURE;
+} /* ms_read_is_data */
+
+
+/**
+ *  if no configuration file, use this function to create the default
+ *  configuration file.
+ */
+static void ms_no_config_file()
+{
+  char userpath[PATH_MAX];
+  struct passwd *usr= NULL;
+  FILE *fd;
+
+  usr= getpwuid(getuid());
+
+  snprintf(userpath, PATH_MAX, "%s/%s", usr->pw_dir, DEFAULT_CONFIG_NAME);
+
+  if (access (userpath, F_OK | R_OK) == 0)
+    goto exit;
+
+  fd= fopen(userpath, "w+");
+
+  if (fd == NULL)
+  {
+    fprintf(stderr, "Could not create default configure file %s\n", userpath);
+    perror(strerror(errno));
+    exit(1);
+  }
+  fprintf(fd, "%s", DEFAULT_CONGIF_STR);
+  fclose(fd);
+
+exit:
+  ms_setting.cfg_file= strdup(userpath);
+} /* ms_no_config_file */
+
+
+/**
+ * parse the configuration file
+ *
+ * @param cfg_file, the configuration file name
+ */
+static void ms_parse_cfg_file(char *cfg_file)
+{
+  FILE *f;
+  size_t start_len, end_len;
+  double proportion;
+  char *line= NULL;
+  size_t  read_len;
+  ssize_t nread;
+  int cmd_type;
+  ms_conf_type_t conf_type;
+  int end_of_file= 0;
+  ms_key_distr_t *key_distr= NULL;
+  ms_value_distr_t *val_distr= NULL;
+
+  if (cfg_file == NULL)
+  {
+    ms_no_config_file();
+    cfg_file= ms_setting.cfg_file;
+  }
+
+  /*read key value configure file*/
+  if ((f= fopen(cfg_file, "r")) == NULL)
+  {
+    fprintf(stderr, "Can not open file: '%s'.\n", cfg_file);
+    exit(1);
+  }
+
+  while (1)
+  {
+    if ((((nread= getline(&line, &read_len, f)) == 1)
+         || ! ms_read_is_data(line, nread)) && (nread != EOF)) /* bypass blank line */
+      continue;
+
+    if (nread == EOF)
+    {
+      fprintf(stderr, "Bad configuration file, no configuration find.\n");
+      exit(1);
+    }
+    conf_type= ms_get_conf_type(line);
+    break;
+  }
+
+  while (! end_of_file)
+  {
+    switch (conf_type)
+    {
+    case CONF_KEY:
+      while (1)
+      {
+        if ((((nread= getline(&line, &read_len, f)) == 1)
+             || ! ms_read_is_data(line, nread)) && (nread != EOF))     /* bypass blank line */
+          continue;
+
+        if (nread != EOF)
+        {
+          if (sscanf(line, "%zu %zu %lf ", &start_len,
+                     &end_len, &proportion) != 3)
+          {
+            conf_type= ms_get_conf_type(line);
+            break;
+          }
+          ms_setting.key_distr[ms_setting.key_rng_cnt].start_len= start_len;
+          ms_setting.key_distr[ms_setting.key_rng_cnt].end_len= end_len;
+          ms_setting.key_distr[ms_setting.key_rng_cnt].key_prop= proportion;
+          ms_setting.key_rng_cnt++;
+
+          if (ms_setting.key_rng_cnt >= ms_setting.total_key_rng_cnt)
+          {
+            key_distr= (ms_key_distr_t *)realloc(
+              ms_setting.key_distr,
+              (size_t)ms_setting.
+                 total_key_rng_cnt * sizeof(ms_key_distr_t) * 2);
+            if (key_distr == NULL)
+            {
+              fprintf(stderr,
+                      "Can't reallocate key distribution structure.\n");
+              exit(1);
+            }
+            ms_setting.key_distr= key_distr;
+            ms_setting.total_key_rng_cnt*= 2;
+          }
+          continue;
+        }
+        end_of_file= 1;
+        break;
+      }
+      break;
+
+    case CONF_VALUE:
+      while (1)
+      {
+        if ((((nread= getline(&line, &read_len, f)) == 1)
+             || ! ms_read_is_data(line, nread)) && (nread != EOF))     /* bypass blank line */
+          continue;
+
+        if (nread != EOF)
+        {
+          if (sscanf(line, "%zu %zu %lf", &start_len, &end_len,
+                     &proportion) != 3)
+          {
+            conf_type= ms_get_conf_type(line);
+            break;
+          }
+          ms_setting.value_distr[ms_setting.val_rng_cnt].start_len=
+            start_len;
+          ms_setting.value_distr[ms_setting.val_rng_cnt].end_len= end_len;
+          ms_setting.value_distr[ms_setting.val_rng_cnt].value_prop=
+            proportion;
+          ms_setting.val_rng_cnt++;
+
+          if (ms_setting.val_rng_cnt >= ms_setting.total_val_rng_cnt)
+          {
+            val_distr= (ms_value_distr_t *)realloc(
+              ms_setting.value_distr,
+              (size_t)ms_setting.
+                 total_val_rng_cnt * sizeof(ms_value_distr_t) * 2);
+            if (val_distr == NULL)
+            {
+              fprintf(stderr,
+                      "Can't reallocate key distribution structure.\n");
+              exit(1);
+            }
+            ms_setting.value_distr= val_distr;
+            ms_setting.total_val_rng_cnt*= 2;
+          }
+          continue;
+        }
+        end_of_file= 1;
+        break;
+      }
+      break;
+
+    case CONF_CMD:
+      while (1)
+      {
+        if ((((nread= getline(&line, &read_len, f)) == 1)
+             || ! ms_read_is_data(line, nread)) && (nread != EOF))     /* bypass blank line */
+          continue;
+
+        if (nread != EOF)
+        {
+          if (sscanf(line, "%d %lf", &cmd_type, &proportion) != 2)
+          {
+            conf_type= ms_get_conf_type(line);
+            break;
+          }
+          if (cmd_type >= CMD_NULL)
+          {
+            continue;
+          }
+          ms_setting.cmd_distr[ms_setting.cmd_used_count].cmd_type=
+            cmd_type;
+          ms_setting.cmd_distr[ms_setting.cmd_used_count].cmd_prop=
+            proportion;
+          ms_setting.cmd_used_count++;
+          continue;
+        }
+        end_of_file= 1;
+        break;
+      }
+
+    case CONF_NULL:
+      while (1)
+      {
+        if ((((nread= getline(&line, &read_len, f)) == 1)
+             || ! ms_read_is_data(line, nread)) && (nread != EOF))     /* bypass blank line */
+          continue;
+
+        if (nread != EOF)
+        {
+          if ((conf_type= ms_get_conf_type(line)) != CONF_NULL)
+          {
+            break;
+          }
+          continue;
+        }
+        end_of_file= 1;
+        break;
+      }
+      break;
+
+    default:
+      assert(0);
+      break;
+    } /* switch */
+  }
+
+  fclose(f);
+
+  if (line != NULL)
+  {
+    free(line);
+  }
+} /* ms_parse_cfg_file */
+
+
+/* calculate the average size of key and value */
+static void ms_calc_avg_size()
+{
+  double avg_val_size= 0.0;
+  double avg_key_size= 0.0;
+  double val_pro= 0.0;
+  double key_pro= 0.0;
+  double averge_len= 0.0;
+  size_t start_len= 0;
+  size_t end_len= 0;
+
+  for (int j= 0; j < ms_setting.val_rng_cnt; j++)
+  {
+    val_pro= ms_setting.value_distr[j].value_prop;
+    start_len= ms_setting.value_distr[j].start_len;
+    end_len= ms_setting.value_distr[j].end_len;
+
+    averge_len= val_pro * ((double)(start_len + end_len)) / 2;
+    avg_val_size+= averge_len;
+  }
+
+  for (int j= 0; j < ms_setting.key_rng_cnt; j++)
+  {
+    key_pro= ms_setting.key_distr[j].key_prop;
+    start_len= ms_setting.key_distr[j].start_len;
+    end_len= ms_setting.key_distr[j].end_len;
+
+    averge_len= key_pro * ((double)(start_len + end_len)) / 2;
+    avg_key_size+= averge_len;
+  }
+
+  ms_setting.avg_val_size= (size_t)avg_val_size;
+  ms_setting.avg_key_size= (size_t)avg_key_size;
+} /* ms_calc_avg_size */
+
+
+/**
+ * used to shuffle key and value distribution array to ensure
+ * (key, value) pair with different set.
+ *
+ * @param distr, pointer of distribution structure array
+ * @param length, length of the array
+ *
+ * @return always return EXIT_SUCCESS
+ */
+static int ms_shuffle_distr(ms_distr_t *distr, int length)
+{
+  int i, j;
+  int tmp_offset;
+  size_t  tmp_size;
+  int64_t rnd;
+
+  for (i= 0; i < length; i++)
+  {
+    rnd= random();
+    j= (int)(rnd % (length - i)) + i;
+
+    switch (rnd % 3)
+    {
+    case 0:
+      tmp_size= distr[j].key_size;
+      distr[j].key_size= distr[i].key_size;
+      distr[i].key_size= tmp_size;
+      break;
+
+    case 1:
+      tmp_offset= distr[j].key_offset;
+      distr[j].key_offset= distr[i].key_offset;
+      distr[i].key_offset= tmp_offset;
+      break;
+
+    case 2:
+      tmp_size= distr[j].value_size;
+      distr[j].value_size= distr[i].value_size;
+      distr[i].value_size= tmp_size;
+      break;
+
+    default:
+      break;
+    } /* switch */
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_shuffle_distr */
+
+
+/**
+ * according to the key and value distribution, to build the
+ * (key, value) pair distribution. the (key, value) pair
+ * distribution array is global, each connection set or get
+ * object keeping this distribution, for the final result, we
+ * can reach the expected key and value distribution.
+ */
+static void ms_build_distr()
+{
+  int offset= 0;
+  int end= 0;
+  int key_cnt= 0;
+  int value_cnt= 0;
+  size_t average_len= 0;
+  size_t diff_len= 0;
+  size_t start_len= 0;
+  size_t end_len= 0;
+  int rnd= 0;
+  ms_distr_t *distr= NULL;
+  int units= (int)ms_setting.win_size / UNIT_ITEMS_COUNT;
+
+  /* calculate average value size and key size */
+  ms_calc_avg_size();
+
+  ms_setting.char_blk_size= RAND_CHAR_SIZE;
+  int key_scope_size=
+    (int)((ms_setting.char_blk_size - RESERVED_RAND_CHAR_SIZE)
+          / UNIT_ITEMS_COUNT);
+
+  ms_setting.distr= (ms_distr_t *)malloc(
+    sizeof(ms_distr_t) * ms_setting.win_size);
+  if (ms_setting.distr == NULL)
+  {
+    fprintf(stderr, "Can't allocate distribution array.");
+    exit(1);
+  }
+
+  /**
+   *  character block is divided by how many different key
+   *  size, each different key size has the same size character
+   *  range.
+   */
+  for (int m= 0; m < units; m++)
+  {
+    for (int i= 0; i < UNIT_ITEMS_COUNT; i++)
+    {
+      ms_setting.distr[m * UNIT_ITEMS_COUNT + i].key_offset=
+        ADDR_ALIGN(key_scope_size * i);
+    }
+  }
+
+  /* initialize key size distribution */
+  for (int m= 0; m < units; m++)
+  {
+    for (int j= 0; j < ms_setting.key_rng_cnt; j++)
+    {
+      key_cnt= (int)(UNIT_ITEMS_COUNT * ms_setting.key_distr[j].key_prop);
+      start_len= ms_setting.key_distr[j].start_len;
+      end_len= ms_setting.key_distr[j].end_len;
+      if ((start_len < MIN_KEY_SIZE) || (end_len < MIN_KEY_SIZE))
+      {
+        fprintf(stderr, "key length must be greater than 16 bytes.\n");
+        exit(1);
+      }
+
+      if (! ms_setting.binary_prot_
+          && ((start_len > MAX_KEY_SIZE) || (end_len > MAX_KEY_SIZE)))
+      {
+        fprintf(stderr, "key length must be less than 250 bytes.\n");
+        exit(1);
+      }
+
+      average_len= (start_len + end_len) / 2;
+      diff_len= (end_len - start_len) / 2;
+      for (int k= 0; k < key_cnt; k++)
+      {
+        if (offset >= (m + 1) * UNIT_ITEMS_COUNT)
+        {
+          break;
+        }
+        rnd= (int)random();
+        if (k % 2 == 0)
+        {
+          ms_setting.distr[offset].key_size=
+            (diff_len == 0) ? average_len :
+            average_len + (size_t)rnd
+            % diff_len;
+        }
+        else
+        {
+          ms_setting.distr[offset].key_size=
+            (diff_len == 0) ? average_len :
+            average_len - (size_t)rnd
+            % diff_len;
+        }
+        offset++;
+      }
+    }
+
+    if (offset < (m + 1) * UNIT_ITEMS_COUNT)
+    {
+      end= (m + 1) * UNIT_ITEMS_COUNT - offset;
+      for (int i= 0; i < end; i++)
+      {
+        ms_setting.distr[offset].key_size= ms_setting.avg_key_size;
+        offset++;
+      }
+    }
+  }
+  offset= 0;
+
+  /* initialize value distribution */
+  if (ms_setting.fixed_value_size != 0)
+  {
+    for (int i= 0; i < units * UNIT_ITEMS_COUNT; i++)
+    {
+      ms_setting.distr[i].value_size= ms_setting.fixed_value_size;
+    }
+  }
+  else
+  {
+    for (int m= 0; m < units; m++)
+    {
+      for (int j= 0; j < ms_setting.val_rng_cnt; j++)
+      {
+        value_cnt=
+          (int)(UNIT_ITEMS_COUNT * ms_setting.value_distr[j].value_prop);
+        start_len= ms_setting.value_distr[j].start_len;
+        end_len= ms_setting.value_distr[j].end_len;
+        if ((start_len <= 0) || (end_len <= 0))
+        {
+          fprintf(stderr, "value length must be greater than 0 bytes.\n");
+          exit(1);
+        }
+
+        if ((start_len > MAX_VALUE_SIZE) || (end_len > MAX_VALUE_SIZE))
+        {
+          fprintf(stderr, "key length must be less than or equal to 1M.\n");
+          exit(1);
+        }
+
+        average_len= (start_len + end_len) / 2;
+        diff_len= (end_len - start_len) / 2;
+        for (int k= 0; k < value_cnt; k++)
+        {
+          if (offset >= (m + 1) * UNIT_ITEMS_COUNT)
+          {
+            break;
+          }
+          rnd= (int)random();
+          if (k % 2 == 0)
+          {
+            ms_setting.distr[offset].value_size=
+              (diff_len == 0) ? average_len :
+              average_len
+              + (size_t)rnd % diff_len;
+          }
+          else
+          {
+            ms_setting.distr[offset].value_size=
+              (diff_len == 0) ? average_len :
+              average_len
+              - (size_t)rnd % diff_len;
+          }
+          offset++;
+        }
+      }
+
+      if (offset < (m + 1) * UNIT_ITEMS_COUNT)
+      {
+        end= (m + 1) * UNIT_ITEMS_COUNT - offset;
+        for (int i= 0; i < end; i++)
+        {
+          ms_setting.distr[offset++].value_size= ms_setting.avg_val_size;
+        }
+      }
+    }
+  }
+
+  /* shuffle distribution */
+  for (int i= 0; i < units; i++)
+  {
+    distr= &ms_setting.distr[i * UNIT_ITEMS_COUNT];
+    for (int j= 0; j < 4; j++)
+    {
+      ms_shuffle_distr(distr, UNIT_ITEMS_COUNT);
+    }
+  }
+} /* ms_build_distr */
+
+
+/**
+ * used to initialize the global character block. The character
+ * block is used to generate the suffix of the key and value. we
+ * only store a pointer in the character block for each key
+ * suffix or value string. It can save much memory to store key
+ * or value string.
+ */
+static void ms_init_random_block()
+{
+  char *ptr= NULL;
+
+  assert(ms_setting.char_blk_size > 0);
+
+  ms_setting.char_block= (char *)malloc(ms_setting.char_blk_size);
+  if (ms_setting.char_block == NULL)
+  {
+    fprintf(stderr, "Can't allocate global char block.");
+    exit(1);
+  }
+  ptr= ms_setting.char_block;
+
+  for (int i= 0; (size_t)i < ms_setting.char_blk_size; i++)
+  {
+    *(ptr++)= ALPHANUMBERICS[random() % CHAR_COUNT];
+  }
+} /* ms_init_random_block */
+
+
+/**
+ * after initialization, call this function to output the main
+ * configuration user specified.
+ */
+static void ms_print_setting()
+{
+  fprintf(stdout, "servers : %s\n", ms_setting.srv_str);
+  fprintf(stdout, "threads count: %d\n", ms_setting.nthreads);
+  fprintf(stdout, "concurrency: %d\n", ms_setting.nconns);
+  if (ms_setting.run_time > 0)
+  {
+    fprintf(stdout, "run time: %ds\n", ms_setting.run_time);
+  }
+  else
+  {
+    fprintf(stdout, "execute number: %" PRId64 "\n", ms_setting.exec_num);
+  }
+  fprintf(stdout, "windows size: %" PRId64 "k\n",
+          (int64_t)(ms_setting.win_size / 1024));
+  fprintf(stdout, "set proportion: set_prop=%.2f\n",
+          ms_setting.cmd_distr[CMD_SET].cmd_prop);
+  fprintf(stdout, "get proportion: get_prop=%.2f\n",
+          ms_setting.cmd_distr[CMD_GET].cmd_prop);
+  fflush(stdout);
+} /* ms_print_setting */
+
+
+/**
+ * previous part of slap mode initialization of setting structure
+ */
+static void ms_setting_slapmode_init_pre()
+{
+  ms_setting.exec_num= DEFAULT_EXE_NUM;
+  ms_setting.verify_percent= DEFAULT_VERIFY_RATE;
+  ms_setting.exp_ver_per= DEFAULT_VERIFY_RATE;
+  ms_setting.overwrite_percent= DEFAULT_OVERWRITE_RATE;
+  ms_setting.mult_key_num= DEFAULT_DIV;
+  ms_setting.fixed_value_size= 0;
+  ms_setting.win_size= DEFAULT_WINDOW_SIZE;
+  ms_setting.udp= false;
+  ms_setting.reconnect= false;
+  ms_setting.verbose= false;
+  ms_setting.facebook_test= false;
+  ms_setting.binary_prot_= false;
+  ms_setting.stat_freq= 0;
+  ms_setting.srv_str= NULL;
+  ms_setting.cfg_file= NULL;
+  ms_setting.sock_per_conn= DEFAULT_SOCK_PER_CONN;
+  ms_setting.expected_tps= 0;
+  ms_setting.rep_write_srv= 0;
+} /* ms_setting_slapmode_init_pre */
+
+
+/**
+ * previous part of initialization of setting structure
+ */
+void ms_setting_init_pre()
+{
+  memset(&ms_setting, 0, sizeof(ms_setting));
+
+  /* common initialize */
+  ms_setting.ncpu= ms_get_cpu_count();
+  ms_setting.nthreads= DEFAULT_THREADS_NUM;
+  ms_setting.nconns= DEFAULT_CONNS_NUM;
+  ms_setting.run_time= DEFAULT_RUN_TIME;
+  ms_setting.total_srv_cnt= MCD_SRVS_NUM_INIT;
+  ms_setting.servers= (ms_mcd_server_t *)malloc(
+    (size_t)ms_setting.total_srv_cnt
+    * sizeof(ms_mcd_server_t));
+  if (ms_setting.servers == NULL)
+  {
+    fprintf(stderr, "Can't allocate servers structure.\n");
+    exit(1);
+  }
+
+  ms_setting_slapmode_init_pre();
+} /* ms_setting_init_pre */
+
+
+/**
+ * post part of slap mode initialization of setting structure
+ */
+static void ms_setting_slapmode_init_post()
+{
+  ms_setting.total_key_rng_cnt= KEY_RANGE_COUNT_INIT;
+  ms_setting.key_distr=
+    (ms_key_distr_t *)malloc((size_t)ms_setting.total_key_rng_cnt * sizeof(ms_key_distr_t));
+
+  if (ms_setting.key_distr == NULL)
+  {
+    fprintf(stderr, "Can't allocate key distribution structure.\n");
+    exit(1);
+  }
+
+  ms_setting.total_val_rng_cnt= VALUE_RANGE_COUNT_INIT;
+
+  ms_setting.value_distr=
+    (ms_value_distr_t *)malloc((size_t)ms_setting.total_val_rng_cnt * sizeof( ms_value_distr_t));
+
+  if (ms_setting.value_distr == NULL)
+  {
+    fprintf(stderr, "Can't allocate value distribution structure.\n");
+    exit(1);
+  }
+
+  ms_parse_cfg_file(ms_setting.cfg_file);
+
+  /* run time mode */
+  if ((ms_setting.exec_num == 0) && (ms_setting.run_time != 0))
+  {
+    ms_setting.exec_num= (int64_t)MAX_EXEC_NUM;
+  }
+  else
+  {
+    /* execute number mode */
+    ms_setting.run_time= 0;
+  }
+
+  if (ms_setting.rep_write_srv > 0)
+  {
+    /* for replication test, need enable reconnect feature */
+    ms_setting.reconnect= true;
+  }
+
+  if (ms_setting.facebook_test && (ms_setting.mult_key_num < 2))
+  {
+    fprintf(stderr, "facebook test must work with multi-get, "
+                    "please specify multi-get key number "
+                    "with '--division' option.\n");
+    exit(1);
+  }
+
+  if (ms_setting.facebook_test && ms_setting.udp)
+  {
+    fprintf(stderr, "facebook test couldn't work with UDP.\n");
+    exit(1);
+  }
+
+  if (ms_setting.udp && (ms_setting.sock_per_conn > 1))
+  {
+    fprintf(stderr, "UDP doesn't support multi-socks "
+                    "in one connection structure.\n");
+    exit(1);
+  }
+
+  if ((ms_setting.rep_write_srv > 0) && (ms_setting.srv_cnt < 2))
+  {
+    fprintf(stderr, "Please specify 2 servers at least for replication\n");
+    exit(1);
+  }
+
+  if ((ms_setting.rep_write_srv > 0)
+      && (ms_setting.srv_cnt < ms_setting.rep_write_srv))
+  {
+    fprintf(stderr, "Servers to do replication writing "
+                    "is larger than the total servers\n");
+    exit(1);
+  }
+
+  if (ms_setting.udp && (ms_setting.rep_write_srv > 0))
+  {
+    fprintf(stderr, "UDP doesn't support replication.\n");
+    exit(1);
+  }
+
+  if (ms_setting.facebook_test && (ms_setting.rep_write_srv > 0))
+  {
+    fprintf(stderr, "facebook test couldn't work with replication.\n");
+    exit(1);
+  }
+
+  ms_build_distr();
+
+  /* initialize global character block */
+  ms_init_random_block();
+  ms_print_setting();
+} /* ms_setting_slapmode_init_post */
+
+
+/**
+ * post part of initialization of setting structure
+ */
+void ms_setting_init_post()
+{
+  ms_get_serverlist(ms_setting.srv_str);
+  ms_setting_slapmode_init_post();
+}
+
+
+/**
+ * clean up the global setting structure
+ */
+void ms_setting_cleanup()
+{
+  if (ms_setting.distr != NULL)
+  {
+    free(ms_setting.distr);
+  }
+
+  if (ms_setting.char_block != NULL)
+  {
+    free(ms_setting.char_block);
+  }
+
+  if (ms_setting.srv_str != NULL)
+  {
+    free(ms_setting.srv_str);
+  }
+
+  if (ms_setting.cfg_file != NULL)
+  {
+    free(ms_setting.cfg_file);
+  }
+
+  if (ms_setting.servers != NULL)
+  {
+    free(ms_setting.servers);
+  }
+
+  if (ms_setting.key_distr != NULL)
+  {
+    free(ms_setting.key_distr);
+  }
+
+  if (ms_setting.value_distr != NULL)
+  {
+    free(ms_setting.value_distr);
+  }
+} /* ms_setting_cleanup */
diff --git a/src/bin/ms_setting.h b/src/bin/ms_setting.h
new file mode 100644 (file)
index 0000000..9db956c
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * File:   ms_setting.h
+ * Author: Mingqiang Zhuang
+ *
+ * Created on February 10, 2009
+ *
+ * (c) Copyright 2009, Schooner Information Technology, Inc.
+ * http://www.schoonerinfotech.com/
+ *
+ */
+#ifndef MS_SETTING_H
+#define MS_SETTING_H
+
+#include "ms_memslap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MCD_SRVS_NUM_INIT         8
+#define MCD_HOST_LENGTH           64
+#define KEY_RANGE_COUNT_INIT      8
+#define VALUE_RANGE_COUNT_INIT    8
+#define PROP_ERROR                0.001
+
+#define MIN_KEY_SIZE              16
+#define MAX_KEY_SIZE              250
+#define MAX_VALUE_SIZE            (1024 * 1024)
+
+/* the content of the configuration file for memslap running without configuration file */
+#define DEFAULT_CONGIF_STR \
+  "key\n"                  \
+  "64 64 1\n"              \
+  "value\n"                \
+  "1024 1024 1\n"          \
+  "cmd\n"                  \
+  "0 0.1\n"                \
+  "1 0.9"
+
+/* Used to parse the value length return by server and path string */
+typedef struct token_s
+{
+  char *value;
+  size_t length;
+} token_t;
+
+#define MAX_TOKENS    10
+
+/* server information */
+typedef struct mcd_server
+{
+  char srv_host_name[MCD_HOST_LENGTH];              /* host name of server */
+  int srv_port;                                     /* server port */
+
+  /* for calculating how long the server disconnects */
+  ATOMIC uint32_t disconn_cnt;                    /* number of disconnections count */
+  ATOMIC uint32_t reconn_cnt;                     /* number of reconnections count */
+  struct timeval disconn_time;                      /* start time of disconnection */
+  struct timeval reconn_time;                       /* end time of reconnection */
+} ms_mcd_server_t;
+
+/* information of an item distribution including key and value */
+typedef struct distr
+{
+  size_t key_size;                  /* size of key */
+  int key_offset;                   /* offset of one key in character block */
+  size_t value_size;                /* size of value */
+} ms_distr_t;
+
+/* information of key distribution */
+typedef struct key_distr
+{
+  size_t start_len;                 /* start of the key length range */
+  size_t end_len;                   /* end of the key length range */
+  double key_prop;                  /* key proportion */
+} ms_key_distr_t;
+
+/* information of value distribution */
+typedef struct value_distr
+{
+  size_t start_len;                 /* start of the value length range */
+  size_t end_len;                   /* end of the value length range */
+  double value_prop;                /* value proportion */
+} ms_value_distr_t;
+
+/* memcached command types */
+typedef enum cmd_type
+{
+  CMD_SET,
+  CMD_GET,
+  CMD_NULL
+} ms_cmd_type_t;
+
+/* types in the configuration file */
+typedef enum conf_type
+{
+  CONF_KEY,
+  CONF_VALUE,
+  CONF_CMD,
+  CONF_NULL
+} ms_conf_type_t;
+
+/* information of command distribution */
+typedef struct cmd_distr
+{
+  ms_cmd_type_t cmd_type;               /* command type */
+  double cmd_prop;                      /* proportion of the command */
+} ms_cmd_distr_t;
+
+/* global setting structure */
+typedef struct setting
+{
+  uint32_t ncpu;                             /* cpu count of this system */
+  uint32_t nthreads;                         /* total thread count, must equal or less than cpu cores */
+  uint32_t nconns;                      /* total conn count, must multiply by total thread count */
+  int64_t exec_num;                     /* total execute number */
+  int run_time;                         /* total run time */
+
+  uint32_t char_blk_size;               /* global character block size */
+  char *char_block;                     /* global character block with random character */
+  ms_distr_t *distr;                    /* distribution from configure file */
+
+  char *srv_str;                        /* string includes servers information */
+  char *cfg_file;                       /* configure file name */
+
+  ms_mcd_server_t *servers;             /* servers array */
+  uint32_t total_srv_cnt;                    /* total servers count of the servers array */
+  uint32_t srv_cnt;                          /* servers count */
+
+  ms_key_distr_t *key_distr;            /* array of key distribution */
+  int total_key_rng_cnt;                /* total key range count of the array */
+  int key_rng_cnt;                      /* actual key range count */
+
+  ms_value_distr_t *value_distr;        /* array of value distribution */
+  int total_val_rng_cnt;                /* total value range count of the array */
+  int val_rng_cnt;                      /* actual value range count */
+
+  ms_cmd_distr_t cmd_distr[CMD_NULL];   /* total we have CMD_NULL commands */
+  int cmd_used_count;                   /* supported command count */
+
+  size_t fixed_value_size;              /* fixed value size */
+  size_t avg_val_size;                  /* average value size */
+  size_t avg_key_size;                  /* average value size */
+
+  double verify_percent;                /* percent of data verification */
+  double exp_ver_per;                   /* percent of data verification with expire time */
+  double overwrite_percent;             /* percent of overwrite */
+  int mult_key_num;                     /* number of keys used by multi-get once */
+  size_t win_size;                      /* item window size per connection */
+  bool udp;                             /* whether or not use UDP */
+  int stat_freq;                        /* statistic frequency second */
+  bool reconnect;                       /* whether it reconnect when connection close */
+  bool verbose;                         /* whether it outputs detailed information when verification */
+  bool facebook_test;                   /* facebook test, TCP set and multi-get with UDP */
+  uint32_t sock_per_conn;                    /* number of socks per connection structure */
+  bool binary_prot_;                     /* whether it use binary protocol */
+  int expected_tps;                     /* expected throughput */
+  uint32_t rep_write_srv;                    /* which servers are used to do replication writing */
+} ms_setting_st;
+
+extern ms_setting_st ms_setting;
+
+/* previous part of initialization of setting structure */
+void ms_setting_init_pre(void);
+
+
+/* post part of initialization of setting structure */
+void ms_setting_init_post(void);
+
+
+/* clean up the global setting structure */
+void ms_setting_cleanup(void);
+
+
+#define UNUSED_ARGUMENT(x)    (void)x
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of MS_SETTING_H */
diff --git a/src/bin/ms_sigsegv.c b/src/bin/ms_sigsegv.c
new file mode 100644 (file)
index 0000000..303381f
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * File:   ms_sigsegv.c
+ * Author: Mingqiang Zhuang
+ *
+ * Created on March 15, 2009
+ *
+ * (c) Copyright 2009, Schooner Information Technology, Inc.
+ * http://www.schoonerinfotech.com/
+ *
+ * Rewrite of stack dump:
+ *  Copyright (C) 2009 Sun Microsystems
+ *  Author Trond Norbye
+ */
+
+#include "mem_config.h"
+
+#include <memory.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <signal.h>
+#include <pthread.h>
+
+#include "ms_memslap.h"
+#include "ms_setting.h"
+
+/* prototypes */
+int ms_setup_sigsegv(void);
+int ms_setup_sigpipe(void);
+int ms_setup_sigint(void);
+
+
+/* signal seg reaches, this function will run */
+static void ms_signal_segv(int signum, siginfo_t *info, void *ptr)
+{
+  UNUSED_ARGUMENT(signum);
+  UNUSED_ARGUMENT(info);
+  UNUSED_ARGUMENT(ptr);
+
+  pthread_mutex_lock(&ms_global.quit_mutex);
+  fprintf(stderr, "Segmentation fault occurred.\nStack trace:\n");
+#if 0
+  pandora_print_callstack(stderr);
+#endif
+  fprintf(stderr, "End of stack trace\n");
+  pthread_mutex_unlock(&ms_global.quit_mutex);
+  abort();
+}
+
+/* signal int reaches, this function will run */
+static void ms_signal_int(int signum, siginfo_t *info, void *ptr)
+{
+  UNUSED_ARGUMENT(signum);
+  UNUSED_ARGUMENT(info);
+  UNUSED_ARGUMENT(ptr);
+
+  pthread_mutex_lock(&ms_global.quit_mutex);
+  fprintf(stderr, "SIGINT handled.\n");
+  pthread_mutex_unlock(&ms_global.quit_mutex);
+  exit(1);
+} /* ms_signal_int */
+
+
+/**
+ * redirect signal seg
+ *
+ * @return if success, return EXIT_SUCCESS, else return -1
+ */
+int ms_setup_sigsegv(void)
+{
+  struct sigaction action;
+
+  memset(&action, 0, sizeof(action));
+  action.sa_sigaction= ms_signal_segv;
+  action.sa_flags= SA_SIGINFO;
+  if (sigaction(SIGSEGV, &action, NULL) < 0)
+  {
+    perror("sigaction");
+    return EXIT_SUCCESS;
+  }
+
+  return -1;
+} /* ms_setup_sigsegv */
+
+
+/**
+ * redirect signal pipe
+ *
+ * @return if success, return EXIT_SUCCESS, else return -1
+ */
+int ms_setup_sigpipe(void)
+{
+  /* ignore the SIGPIPE signal */
+  signal(SIGPIPE, SIG_IGN);
+
+  return -1;
+} /* ms_setup_sigpipe */
+
+
+/**
+ * redirect signal int
+ *
+ * @return if success, return EXIT_SUCCESS, else return -1
+ */
+int ms_setup_sigint(void)
+{
+  struct sigaction action_3;
+
+  memset(&action_3, 0, sizeof(action_3));
+  action_3.sa_sigaction= ms_signal_int;
+  action_3.sa_flags= SA_SIGINFO;
+  if (sigaction(SIGINT, &action_3, NULL) < 0)
+  {
+    perror("sigaction");
+    return EXIT_SUCCESS;
+  }
+
+  return -1;
+} /* ms_setup_sigint */
+
+
+#ifndef SIGSEGV_NO_AUTO_INIT
+static void __attribute((constructor)) ms_init(void)
+{
+  ms_setup_sigsegv();
+  ms_setup_sigpipe();
+  ms_setup_sigint();
+}
+#endif
diff --git a/src/bin/ms_sigsegv.h b/src/bin/ms_sigsegv.h
new file mode 100644 (file)
index 0000000..7990ff6
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * File:   ms_sigsegv.h
+ * Author: Mingqiang Zhuang
+ *
+ * Created on March 15, 2009
+ *
+ * (c) Copyright 2009, Schooner Information Technology, Inc.
+ * http://www.schoonerinfotech.com/
+ *
+ */
+#ifndef MS_SIGSEGV_H
+#define MS_SIGSEGV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* redirect signal seg */
+int ms_setup_sigsegv(void);
+
+
+/* redirect signal pipe */
+int ms_setup_sigpipe(void);
+
+
+/* redirect signal int */
+int ms_setup_sigint(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of MS_SIGSEGV_H */
diff --git a/src/bin/ms_stats.c b/src/bin/ms_stats.c
new file mode 100644 (file)
index 0000000..086fb3e
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * File:   ms_stats.h
+ * Author: Mingqiang Zhuang
+ *
+ * Created on March 25, 2009
+ *
+ * (c) Copyright 2009, Schooner Information Technology, Inc.
+ * http://www.schoonerinfotech.com/
+ *
+ */
+
+#include "mem_config.h"
+
+#include <inttypes.h>
+#include "ms_stats.h"
+
+#define array_size(x)    (sizeof(x) / sizeof((x)[0]))
+
+static int ms_local_log2(uint64_t value);
+static uint64_t ms_get_events(ms_stat_t *stat);
+
+
+/**
+ * get the index of local log2 array
+ *
+ * @param value
+ *
+ * @return return the index of local log2 array
+ */
+static int ms_local_log2(uint64_t value)
+{
+  int result= 0;
+
+  while (result <= 63 && ((uint64_t)1 << result) < value)
+  {
+    result++;
+  }
+
+  return result;
+} /* ms_local_log2 */
+
+
+/**
+ * initialize statistic structure
+ *
+ * @param stat, pointer of the statistic structure
+ * @param name, name of the statistic
+ */
+void ms_init_stats(ms_stat_t *stat, const char *name)
+{
+  memset(stat, 0, sizeof(*stat));
+
+  stat->name= (char *)name;
+  stat->min_time= (uint64_t)-1;
+  stat->max_time= 0;
+  stat->period_min_time= (uint64_t)-1;
+  stat->period_max_time= 0;
+  stat->log_product= 0;
+  stat->total_time= 0;
+  stat->pre_total_time= 0;
+  stat->squares= 0;
+  stat->pre_squares= 0;
+  stat->pre_events= 0;
+  stat->pre_log_product= 0;
+  stat->get_miss= 0;
+  stat->pre_get_miss= 0;
+} /* ms_init_stats */
+
+
+/**
+ * record one event
+ *
+ * @param stat, pointer of the statistic structure
+ * @param total_time, response time of the command
+ * @param get_miss, whether it gets miss
+ */
+void ms_record_event(ms_stat_t *stat, uint64_t total_time, int get_miss)
+{
+  stat->total_time+= total_time;
+
+  if (total_time < stat->min_time)
+  {
+    stat->min_time= total_time;
+  }
+
+  if (total_time > stat->max_time)
+  {
+    stat->max_time= total_time;
+  }
+
+  if (total_time < stat->period_min_time)
+  {
+    stat->period_min_time= total_time;
+  }
+
+  if (total_time > stat->period_max_time)
+  {
+    stat->period_max_time= total_time;
+  }
+
+  if (get_miss)
+  {
+    stat->get_miss++;
+  }
+
+  stat->dist[ms_local_log2(total_time)]++;
+  stat->squares+= (double)(total_time * total_time);
+
+  if (total_time != 0)
+  {
+    stat->log_product+= log((double)total_time);
+  }
+} /* ms_record_event */
+
+
+/**
+ * get the events count
+ *
+ * @param stat, pointer of the statistic structure
+ *
+ * @return total events recorded
+ */
+static uint64_t ms_get_events(ms_stat_t *stat)
+{
+  uint64_t events= 0;
+
+  for (uint32_t i= 0; i < array_size(stat->dist); i++)
+  {
+    events+= stat->dist[i];
+  }
+
+  return events;
+} /* ms_get_events */
+
+
+/**
+ * dump the statistics
+ *
+ * @param stat, pointer of the statistic structure
+ */
+void ms_dump_stats(ms_stat_t *stat)
+{
+  uint64_t events= 0;
+  int max_non_zero= 0;
+  int min_non_zero= 0;
+  double average= 0;
+
+  for (uint32_t i= 0; i < array_size(stat->dist); i++)
+  {
+    events+= stat->dist[i];
+    if (stat->dist[i] != 0)
+    {
+      max_non_zero= (int)i;
+    }
+  }
+
+  if (events == 0)
+  {
+    return;
+  }
+  average= (double)(stat->total_time / events);
+
+  printf("%s Statistics (%lld events)\n", stat->name, (long long)events);
+  printf("   Min:  %8lld\n", (long long)stat->min_time);
+  printf("   Max:  %8lld\n", (long long)stat->max_time);
+  printf("   Avg:  %8lld\n", (long long)(stat->total_time / events));
+  printf("   Geo:  %8.2lf\n", exp(stat->log_product / (double)events));
+
+  if (events > 1)
+  {
+    printf("   Std:  %8.2lf\n",
+           sqrt((stat->squares - (double)events * average
+                 * average) / ((double)events - 1)));
+  }
+  printf("   Log2 Dist:");
+
+  for (int i= 0; i <= max_non_zero - 4; i+= 4)
+  {
+    if ((stat->dist[i + 0] != 0)
+        || (stat->dist[i + 1] != 0)
+        || (stat->dist[i + 2] != 0)
+        || (stat->dist[i + 3] != 0))
+    {
+      min_non_zero= i;
+      break;
+    }
+  }
+
+  for (int i= min_non_zero; i <= max_non_zero; i++)
+  {
+    if ((i % 4) == 0)
+    {
+      printf("\n      %2d:", (int)i);
+    }
+    printf("   %6" PRIu64 , stat->dist[i]);
+  }
+
+  printf("\n\n");
+} /* ms_dump_stats */
+
+
+/**
+ * dump the format statistics
+ *
+ * @param stat, pointer of the statistic structure
+ * @param run_time, the total run time
+ * @param freq, statistic frequency
+ * @param obj_size, average object size
+ */
+void ms_dump_format_stats(ms_stat_t *stat,
+                          int run_time,
+                          int freq,
+                          int obj_size)
+{
+  uint64_t events= 0;
+  double global_average= 0;
+  uint64_t global_tps= 0;
+  double global_rate= 0;
+  double global_std= 0;
+  double global_log= 0;
+
+  double period_average= 0;
+  uint64_t period_tps= 0;
+  double period_rate= 0;
+  double period_std= 0;
+  double period_log= 0;
+
+  if ((events= ms_get_events(stat)) == 0)
+  {
+    return;
+  }
+
+  global_average= (double)(stat->total_time / events);
+  global_tps= events / (uint64_t)run_time;
+  global_rate= (double)events * obj_size / 1024 / 1024 / run_time;
+  global_std= sqrt((stat->squares - (double)events * global_average
+                    * global_average) / (double)(events - 1));
+  global_log= exp(stat->log_product / (double)events);
+
+  uint64_t diff_time= stat->total_time - stat->pre_total_time;
+  uint64_t diff_events= events - stat->pre_events;
+  if (diff_events >= 1)
+  {
+    period_average= (double)(diff_time / diff_events);
+    period_tps= diff_events / (uint64_t)freq;
+    period_rate= (double)diff_events * obj_size / 1024 / 1024 / freq;
+    double diff_squares= (double)stat->squares - (double)stat->pre_squares;
+    period_std= sqrt((diff_squares - (double)diff_events * period_average
+                      * period_average) / (double)(diff_events - 1));
+    double diff_log_product= stat->log_product - stat->pre_log_product;
+    period_log= exp(diff_log_product / (double)diff_events);
+  }
+
+  printf("%s Statistics\n", stat->name);
+  printf("%-8s %-8s %-12s %-12s %-10s %-10s %-8s %-10s %-10s %-10s %-10s\n",
+         "Type",
+         "Time(s)",
+         "Ops",
+         "TPS(ops/s)",
+         "Net(M/s)",
+         "Get_miss",
+         "Min(us)",
+         "Max(us)",
+         "Avg(us)",
+         "Std_dev",
+         "Geo_dist");
+
+  printf(
+    "%-8s %-8d %-12llu %-12lld %-10.1f %-10lld %-8lld %-10lld %-10lld %-10.2f %.2f\n",
+    "Period",
+    freq,
+    (long long)diff_events,
+    (long long)period_tps,
+    global_rate,
+    (long long)(stat->get_miss - stat->pre_get_miss),
+    (long long)stat->period_min_time,
+    (long long)stat->period_max_time,
+    (long long)period_average,
+    period_std,
+    period_log);
+
+  printf(
+    "%-8s %-8d %-12llu %-12lld %-10.1f %-10lld %-8lld %-10lld %-10lld %-10.2f %.2f\n\n",
+    "Global",
+    run_time,
+    (long long)events,
+    (long long)global_tps,
+    period_rate,
+    (long long)stat->get_miss,
+    (long long)stat->min_time,
+    (long long)stat->max_time,
+    (long long)global_average,
+    global_std,
+    global_log);
+
+  stat->pre_events= events;
+  stat->pre_squares= (uint64_t)stat->squares;
+  stat->pre_total_time= stat->total_time;
+  stat->pre_log_product= stat->log_product;
+  stat->period_min_time= (uint64_t)-1;
+  stat->period_max_time= 0;
+  stat->pre_get_miss= stat->get_miss;
+} /* ms_dump_format_stats */
diff --git a/src/bin/ms_stats.h b/src/bin/ms_stats.h
new file mode 100644 (file)
index 0000000..5ac88b3
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * File:   ms_stats.h
+ * Author: Mingqiang Zhuang
+ *
+ * Created on March 25, 2009
+ *
+ * (c) Copyright 2009, Schooner Information Technology, Inc.
+ * http://www.schoonerinfotech.com/
+ *
+ */
+#ifndef MS_STAT_H
+#define MS_STAT_H
+
+#include <math.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* statistic structure of response time */
+typedef struct
+{
+  char *name;
+  uint64_t total_time;
+  uint64_t min_time;
+  uint64_t max_time;
+  uint64_t get_miss;
+  uint64_t dist[65];
+  double squares;
+  double log_product;
+
+  uint64_t period_min_time;
+  uint64_t period_max_time;
+  uint64_t pre_get_miss;
+  uint64_t pre_events;
+  uint64_t pre_total_time;
+  uint64_t pre_squares;
+  double pre_log_product;
+} ms_stat_t;
+
+/* initialize statistic */
+void ms_init_stats(ms_stat_t *stat, const char *name);
+
+
+/* record one event */
+void ms_record_event(ms_stat_t *stat, uint64_t time, int get_miss);
+
+
+/* dump the statistics */
+void ms_dump_stats(ms_stat_t *stat);
+
+
+/* dump the format statistics */
+void ms_dump_format_stats(ms_stat_t *stat,
+                          int run_time,
+                          int freq,
+                          int obj_size);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* MS_STAT_H */
diff --git a/src/bin/ms_task.c b/src/bin/ms_task.c
new file mode 100644 (file)
index 0000000..f2cb865
--- /dev/null
@@ -0,0 +1,1110 @@
+/*
+ * File:   ms_task.c
+ * Author: Mingqiang Zhuang
+ *
+ * Created on February 10, 2009
+ *
+ * (c) Copyright 2009, Schooner Information Technology, Inc.
+ * http://www.schoonerinfotech.com/
+ *
+ */
+
+#include "mem_config.h"
+
+#if defined(HAVE_SYS_TIME_H)
+# include <sys/time.h>
+#endif
+
+#if defined(HAVE_TIME_H)
+# include <time.h>
+#endif
+
+#include "ms_thread.h"
+#include "ms_setting.h"
+#include "ms_atomic.h"
+
+/* command distribution adjustment cycle */
+#define CMD_DISTR_ADJUST_CYCLE    1000
+#define DISADJUST_FACTOR          0.03 /**
+                                 * In one adjustment cycle, if undo set or get
+                                 * operations proportion is more than 3% , means
+                                 * there are too many new item or need more new
+                                 * item in the window. This factor shows it.
+                                 */
+
+/* get item from task window */
+static ms_task_item_t *ms_get_cur_opt_item(ms_conn_t *c);
+static ms_task_item_t *ms_get_next_get_item(ms_conn_t *c);
+static ms_task_item_t *ms_get_next_set_item(ms_conn_t *c);
+static ms_task_item_t *ms_get_random_overwrite_item(ms_conn_t *c);
+
+
+/* select next operation to do */
+static void ms_select_opt(ms_conn_t *c, ms_task_t *task);
+
+
+/* set and get speed estimate for controlling and adjustment */
+static bool ms_is_set_too_fast(ms_task_t *task);
+static bool ms_is_get_too_fast(ms_task_t *task);
+static void ms_kick_out_item(ms_task_item_t *item);
+
+
+/* miss rate adjustment */
+static bool ms_need_overwrite_item(ms_task_t *task);
+static bool ms_adjust_opt(ms_conn_t *c, ms_task_t *task);
+
+
+/* deal with data verification initialization */
+static void ms_task_data_verify_init(ms_task_t *task);
+static void ms_task_expire_verify_init(ms_task_t *task);
+
+
+/* select a new task to do */
+static ms_task_t *ms_get_task(ms_conn_t *c, bool warmup);
+
+
+/* run the selected task */
+static void ms_update_set_result(ms_conn_t *c, ms_task_item_t *item);
+static void ms_update_stat_result(ms_conn_t *c);
+static void ms_update_multi_get_result(ms_conn_t *c);
+static void ms_update_single_get_result(ms_conn_t *c, ms_task_item_t *item);
+static void ms_update_task_result(ms_conn_t *c);
+static void ms_single_getset_task_sch(ms_conn_t *c);
+static void ms_multi_getset_task_sch(ms_conn_t *c);
+static void ms_send_signal(ms_sync_lock_t *sync_lock);
+static void ms_warmup_server(ms_conn_t *c);
+static int ms_run_getset_task(ms_conn_t *c);
+
+
+/**
+ * used to get the current operation item(object)
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return ms_task_item_t*, current operating item
+ */
+static ms_task_item_t *ms_get_cur_opt_item(ms_conn_t *c)
+{
+  return c->curr_task.item;
+}
+
+
+/**
+ * used to get the next item to do get operation
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return ms_task_item_t*, the pointer of the next item to do
+ *         get operation
+ */
+static ms_task_item_t *ms_get_next_get_item(ms_conn_t *c)
+{
+  ms_task_item_t *item= NULL;
+
+  if (c->set_cursor <= 0)
+  {
+    /* the first item in the window */
+    item= &c->item_win[0];
+  }
+  else if (c->set_cursor > 0 && c->set_cursor < (uint32_t)c->win_size)
+  {
+    /* random get one item set before */
+    item= &c->item_win[random() % (int64_t)c->set_cursor];
+  }
+  else
+  {
+    /* random get one item from the window */
+    item= &c->item_win[random() % c->win_size];
+  }
+
+  return item;
+} /* ms_get_next_get_item */
+
+
+/**
+ * used to get the next item to do set operation
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return ms_task_item_t*, the pointer of the next item to do
+ *         set operation
+ */
+static ms_task_item_t *ms_get_next_set_item(ms_conn_t *c)
+{
+  /**
+   *  when a set command successes, the cursor will plus 1. If set
+   *  fails, the cursor doesn't change. it isn't necessary to
+   *  increase the cursor here.
+   */
+  return &c->item_win[(int64_t)c->set_cursor % c->win_size];
+}
+
+
+/**
+ * If we need do overwrite, we could select a item set before.
+ * This function is used to get a item set before to do
+ * overwrite.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return ms_task_item_t*, the pointer of the previous item of
+ *         set operation
+ */
+static ms_task_item_t *ms_get_random_overwrite_item(ms_conn_t *c)
+{
+    return ms_get_next_get_item(c);
+} /* ms_get_random_overwrite_item */
+
+/**
+ * According to the proportion of operations(get or set), select
+ * an operation to do.
+ *
+ * @param c, pointer of the concurrency
+ * @param task, pointer of current task in the concurrency
+ */
+static void ms_select_opt(ms_conn_t *c, ms_task_t *task)
+{
+  double get_prop= ms_setting.cmd_distr[CMD_GET].cmd_prop;
+  double set_prop= ms_setting.cmd_distr[CMD_SET].cmd_prop;
+
+  /* update cycle operation number if necessary */
+  if ((task->cycle_undo_get == 0) || (task->cycle_undo_set == 0))
+  {
+    task->cycle_undo_get+= (int)(CMD_DISTR_ADJUST_CYCLE * get_prop);
+    task->cycle_undo_set+= (int)(CMD_DISTR_ADJUST_CYCLE * set_prop);
+  }
+
+  /**
+   *  According to operation distribution to choose doing which
+   *  operation. If it can't set new object to sever, just change
+   *  to do get operation.
+   */
+  if ((set_prop > PROP_ERROR)
+      && ((double)task->get_opt * set_prop >= (double)task->set_opt
+          * get_prop))
+  {
+    task->cmd= CMD_SET;
+    task->item= ms_get_next_set_item(c);
+  }
+  else
+  {
+    task->cmd= CMD_GET;
+    task->item= ms_get_next_get_item(c);
+  }
+} /* ms_select_opt */
+
+
+/**
+ * used to judge whether the number of get operations done is
+ * more than expected number of get operations to do right now.
+ *
+ * @param task, pointer of current task in the concurrency
+ *
+ * @return bool, if get too fast, return true, else return false
+ */
+static bool ms_is_get_too_fast(ms_task_t *task)
+{
+  double get_prop= ms_setting.cmd_distr[CMD_GET].cmd_prop;
+  double set_prop= ms_setting.cmd_distr[CMD_SET].cmd_prop;
+
+  /* no get operation */
+  if (get_prop < PROP_ERROR)
+  {
+    return false;
+  }
+
+  int max_undo_set= (int)(set_prop / get_prop * (1.0 + DISADJUST_FACTOR))
+                    * task->cycle_undo_get;
+
+  if (((double)task->get_opt * set_prop > (double)task->set_opt * get_prop)
+      && (task->cycle_undo_set > max_undo_set))
+  {
+    return true;
+  }
+
+  return false;
+} /* ms_is_get_too_fast */
+
+
+/**
+ * used to judge whether the number of set operations done is
+ * more than expected number of set operations to do right now.
+ *
+ * @param task, pointer of current task in the concurrency
+ *
+ * @return bool, if set too fast, return true, else return false
+ */
+static bool ms_is_set_too_fast(ms_task_t *task)
+{
+  double get_prop= ms_setting.cmd_distr[CMD_GET].cmd_prop;
+  double set_prop= ms_setting.cmd_distr[CMD_SET].cmd_prop;
+
+  /* no set operation */
+  if (set_prop < PROP_ERROR)
+  {
+    return false;
+  }
+
+  /* If it does set operation too fast, skip some */
+  int max_undo_get= (int)((get_prop / set_prop * (1.0 + DISADJUST_FACTOR))
+                          * (double)task->cycle_undo_set);
+
+  if (((double)task->get_opt * set_prop < (double)task->set_opt * get_prop)
+      && (task->cycle_undo_get > max_undo_get))
+  {
+    return true;
+  }
+
+  return false;
+} /* ms_is_set_too_fast */
+
+
+/**
+ * kick out the old item in the window, and add a new item to
+ * overwrite the old item. When we don't want to do overwrite
+ * object, and the current item to do set operation is an old
+ * item, we could kick out the old item and add a new item. Then
+ * we can ensure we set new object every time.
+ *
+ * @param item, pointer of task item which includes the object
+ *            information
+ */
+static void ms_kick_out_item(ms_task_item_t *item)
+{
+  /* allocate a new item */
+  item->key_prefix= ms_get_key_prefix();
+
+  item->key_suffix_offset++;
+  item->value_offset= INVALID_OFFSET;       /* new item use invalid value offset */
+  item->client_time= 0;
+} /* ms_kick_out_item */
+
+
+/**
+ *  used to judge whether we need overwrite object based on the
+ *  options user specified
+ *
+ * @param task, pointer of current task in the concurrency
+ *
+ * @return bool, if need overwrite, return true, else return
+ *         false
+ */
+static bool ms_need_overwrite_item(ms_task_t *task)
+{
+  ms_task_item_t *item= task->item;
+
+  assert(item != NULL);
+  assert(task->cmd == CMD_SET);
+
+  /**
+   *  according to data overwrite percent to determine if do data
+   *  overwrite.
+   */
+  if (task->overwrite_set < (double)task->set_opt
+      * ms_setting.overwrite_percent)
+  {
+    return true;
+  }
+
+  return false;
+} /* ms_need_overwirte_item */
+
+
+/**
+ * used to adjust operation. the function must be called after
+ * select operation. the function change get operation to set
+ * operation, or set operation to get operation based on the
+ * current case.
+ *
+ * @param c, pointer of the concurrency
+ * @param task, pointer of current task in the concurrency
+ *
+ * @return bool, if success, return true, else return false
+ */
+static bool ms_adjust_opt(ms_conn_t *c, ms_task_t *task)
+{
+  ms_task_item_t *item= task->item;
+
+  assert(item != NULL);
+
+  if (task->cmd == CMD_SET)
+  {
+    /* If did set operation too fast, skip some */
+    if (ms_is_set_too_fast(task))
+    {
+      /* get the item instead */
+      if (item->value_offset != INVALID_OFFSET)
+      {
+        task->cmd= CMD_GET;
+        return true;
+      }
+    }
+
+    /* If the current item is not a new item, kick it out */
+    if (item->value_offset != INVALID_OFFSET)
+    {
+      if (ms_need_overwrite_item(task))
+      {
+        /* overwrite */
+        task->overwrite_set++;
+      }
+      else
+      {
+        /* kick out the current item to do set operation */
+        ms_kick_out_item(item);
+      }
+    }
+    else            /* it's a new item */
+    {
+      /* need overwrite */
+      if (ms_need_overwrite_item(task))
+      {
+        /**
+         *  overwrite not use the item with current set cursor, revert
+         *  set cursor.
+         */
+        c->set_cursor--;
+
+        item= ms_get_random_overwrite_item(c);
+        if (item->value_offset != INVALID_OFFSET)
+        {
+          task->item= item;
+          task->overwrite_set++;
+        }
+        else                /* item is a new item */
+        {
+          /* select the item to run, and cancel overwrite */
+          task->item= item;
+        }
+      }
+    }
+    task->cmd= CMD_SET;
+    return true;
+  }
+  else
+  {
+    if (item->value_offset == INVALID_OFFSET)
+    {
+      task->cmd= CMD_SET;
+      return true;
+    }
+
+    /**
+     *  If It does get operation too fast, it will change the
+     *  operation to set.
+     */
+    if (ms_is_get_too_fast(task))
+    {
+      /* don't kick out the first item in the window */
+      if (! ms_is_set_too_fast(task))
+      {
+        ms_kick_out_item(item);
+        task->cmd= CMD_SET;
+        return true;
+      }
+      else
+      {
+        return false;
+      }
+    }
+
+    assert(item->value_offset != INVALID_OFFSET);
+
+    task->cmd= CMD_GET;
+    return true;
+  }
+} /* ms_adjust_opt */
+
+
+/**
+ * used to initialize the task which need verify data.
+ *
+ * @param task, pointer of current task in the concurrency
+ */
+static void ms_task_data_verify_init(ms_task_t *task)
+{
+  ms_task_item_t *item= task->item;
+
+  assert(item != NULL);
+  assert(task->cmd == CMD_GET);
+
+  /**
+   *  according to data verification percent to determine if do
+   *  data verification.
+   */
+  if (task->verified_get < (double)task->get_opt
+      * ms_setting.verify_percent)
+  {
+    /**
+     *  currently it doesn't do verify, just increase the counter,
+     *  and do verification next proper get command
+     */
+    if ((task->item->value_offset != INVALID_OFFSET)
+        && (item->exp_time == 0))
+    {
+      task->verify= true;
+      task->finish_verify= false;
+      task->verified_get++;
+    }
+  }
+} /* ms_task_data_verify_init */
+
+
+/**
+ * used to initialize the task which need verify expire time.
+ *
+ * @param task, pointer of current task in the concurrency
+ */
+static void ms_task_expire_verify_init(ms_task_t *task)
+{
+  ms_task_item_t *item= task->item;
+
+  assert(item != NULL);
+  assert(task->cmd == CMD_GET);
+  assert(item->exp_time > 0);
+
+  task->verify= true;
+  task->finish_verify= false;
+} /* ms_task_expire_verify_init */
+
+
+/**
+ * used to get one task, the function initializes the task
+ * structure.
+ *
+ * @param c, pointer of the concurrency
+ * @param warmup, whether it need warmup
+ *
+ * @return ms_task_t*, pointer of current task in the
+ *         concurrency
+ */
+static ms_task_t *ms_get_task(ms_conn_t *c, bool warmup)
+{
+  ms_task_t *task= &c->curr_task;
+
+  while (1)
+  {
+    task->verify= false;
+    task->finish_verify= true;
+    task->get_miss= true;
+
+    if (warmup)
+    {
+      task->cmd= CMD_SET;
+      task->item= ms_get_next_set_item(c);
+
+      return task;
+    }
+
+    /* according to operation distribution to choose doing which operation */
+    ms_select_opt(c, task);
+
+    if (! ms_adjust_opt(c, task))
+    {
+      continue;
+    }
+
+    if ((ms_setting.verify_percent > 0) && (task->cmd == CMD_GET))
+    {
+      ms_task_data_verify_init(task);
+    }
+
+    if ((ms_setting.exp_ver_per > 0) && (task->cmd == CMD_GET)
+        && (task->item->exp_time > 0))
+    {
+      ms_task_expire_verify_init(task);
+    }
+
+    break;
+  }
+
+  /**
+   *  Only update get and delete counter, set counter will be
+   *  updated after set operation successes.
+   */
+  if (task->cmd == CMD_GET)
+  {
+    task->get_opt++;
+    task->cycle_undo_get--;
+  }
+
+  return task;
+} /* ms_get_task */
+
+
+/**
+ * send a signal to the main monitor thread
+ *
+ * @param sync_lock, pointer of the lock
+ */
+static void ms_send_signal(ms_sync_lock_t *sync_lock)
+{
+  pthread_mutex_lock(&sync_lock->lock);
+  sync_lock->count++;
+  pthread_cond_signal(&sync_lock->cond);
+  pthread_mutex_unlock(&sync_lock->lock);
+} /* ms_send_signal */
+
+
+/**
+ * If user only want to do get operation, but there is no object
+ * in server , so we use this function to warmup the server, and
+ * set some objects to server. It runs at the beginning of task.
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_warmup_server(ms_conn_t *c)
+{
+  ms_task_t *task;
+  ms_task_item_t *item;
+
+  /**
+   * Extra one loop to get the last command returned state.
+   * Normally it gets the previous command returned state.
+   */
+  if ((c->remain_warmup_num >= 0)
+      && (c->remain_warmup_num != c->warmup_num))
+  {
+    item= ms_get_cur_opt_item(c);
+    /* only update the set command result state for data verification */
+    if ((c->precmd.cmd == CMD_SET) && (c->precmd.retstat == MCD_STORED))
+    {
+      item->value_offset= item->key_suffix_offset;
+      /* set success, update counter */
+      c->set_cursor++;
+    }
+    else if (c->precmd.cmd == CMD_SET && c->precmd.retstat != MCD_STORED)
+    {
+      printf("key: %" PRIx64 " didn't set success\n", item->key_prefix);
+    }
+  }
+
+  /* the last time don't run a task */
+  if (c->remain_warmup_num-- > 0)
+  {
+    /* operate next task item */
+    task= ms_get_task(c, true);
+    item= task->item;
+    ms_mcd_set(c, item);
+  }
+
+  /**
+   *  finish warming up server, wait all connects initialize
+   *  complete. Then all connects can start do task at the same
+   *  time.
+   */
+  if (c->remain_warmup_num == -1)
+  {
+    ms_send_signal(&ms_global.warmup_lock);
+    c->remain_warmup_num--;       /* never run the if branch */
+  }
+} /* ms_warmup_server */
+
+
+/**
+ * dispatch single get and set task
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_single_getset_task_sch(ms_conn_t *c)
+{
+  ms_task_t *task;
+  ms_task_item_t *item;
+
+  /* the last time don't run a task */
+  if (c->remain_exec_num-- > 0)
+  {
+    task= ms_get_task(c, false);
+    item= task->item;
+    if (task->cmd == CMD_SET)
+    {
+      ms_mcd_set(c, item);
+    }
+    else if (task->cmd == CMD_GET)
+    {
+      assert(task->cmd == CMD_GET);
+      ms_mcd_get(c, item);
+    }
+  }
+} /* ms_single_getset_task_sch */
+
+
+/**
+ * dispatch multi-get and set task
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_multi_getset_task_sch(ms_conn_t *c)
+{
+  ms_task_t *task;
+  ms_mlget_task_item_t *mlget_item;
+
+  while (1)
+  {
+    if (c->remain_exec_num-- > 0)
+    {
+      task= ms_get_task(c, false);
+      if (task->cmd == CMD_SET)             /* just do it */
+      {
+        ms_mcd_set(c, task->item);
+        break;
+      }
+      else
+      {
+        assert(task->cmd == CMD_GET);
+        mlget_item= &c->mlget_task.mlget_item[c->mlget_task.mlget_num];
+        mlget_item->item= task->item;
+        mlget_item->verify= task->verify;
+        mlget_item->finish_verify= task->finish_verify;
+        mlget_item->get_miss= task->get_miss;
+        c->mlget_task.mlget_num++;
+
+        /* enough multi-get task items can be done */
+        if ((c->mlget_task.mlget_num >= ms_setting.mult_key_num)
+            || ((c->remain_exec_num == 0) && (c->mlget_task.mlget_num > 0)))
+        {
+          ms_mcd_mlget(c);
+          break;
+        }
+      }
+    }
+    else
+    {
+      if ((c->remain_exec_num <= 0) && (c->mlget_task.mlget_num > 0))
+      {
+        ms_mcd_mlget(c);
+      }
+      break;
+    }
+  }
+} /* ms_multi_getset_task_sch */
+
+
+/**
+ * calculate the difference value of two time points
+ *
+ * @param start_time, the start time
+ * @param end_time, the end time
+ *
+ * @return uint64_t, the difference value between start_time and end_time in us
+ */
+int64_t ms_time_diff(struct timeval *start_time, struct timeval *end_time)
+{
+  int64_t endtime= end_time->tv_sec * 1000000 + end_time->tv_usec;
+  int64_t starttime= start_time->tv_sec * 1000000 + start_time->tv_usec;
+
+  assert(endtime >= starttime);
+
+  return endtime - starttime;
+} /* ms_time_diff */
+
+
+/**
+ * after get the response from server for multi-get, the
+ * function update the state of the task and do data verify if
+ * necessary.
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_update_multi_get_result(ms_conn_t *c)
+{
+  ms_mlget_task_item_t *mlget_item;
+  ms_task_item_t *item;
+  char *orignval= NULL;
+  char *orignkey= NULL;
+
+  if (c == NULL)
+  {
+    return;
+  }
+  assert(c != NULL);
+
+  for (int i= 0; i < c->mlget_task.mlget_num; i++)
+  {
+    mlget_item= &c->mlget_task.mlget_item[i];
+    item= mlget_item->item;
+    orignval= &ms_setting.char_block[item->value_offset];
+    orignkey= &ms_setting.char_block[item->key_suffix_offset];
+
+    /* update get miss counter */
+    if (mlget_item->get_miss)
+    {
+      atomic_add_size(&ms_stats.get_misses, 1);
+    }
+
+    /* get nothing from server for this task item */
+    if (mlget_item->verify && ! mlget_item->finish_verify)
+    {
+      /* verify expire time if necessary */
+      if (item->exp_time > 0)
+      {
+        struct timeval curr_time;
+        gettimeofday(&curr_time, NULL);
+
+        /* object doesn't expire but can't get it now */
+        if (curr_time.tv_sec - item->client_time
+            < item->exp_time - EXPIRE_TIME_ERROR)
+        {
+          atomic_add_size(&ms_stats.unexp_unget, 1);
+
+          if (ms_setting.verbose)
+          {
+            char set_time[64];
+            char cur_time[64];
+            strftime(set_time, 64, "%Y-%m-%d %H:%M:%S",
+                     localtime(&item->client_time));
+            strftime(cur_time, 64, "%Y-%m-%d %H:%M:%S",
+                     localtime(&curr_time.tv_sec));
+            fprintf(stderr,
+                    "\n\t<%d expire time verification failed, object "
+                    "doesn't expire but can't get it now\n"
+                    "\tkey len: %d\n"
+                    "\tkey: %" PRIx64 " %.*s\n"
+                    "\tset time: %s current time: %s "
+                    "diff time: %d expire time: %d\n"
+                    "\texpected data len: %d\n"
+                    "\texpected data: %.*s\n"
+                    "\treceived data: \n",
+                    c->sfd,
+                    item->key_size,
+                    item->key_prefix,
+                    item->key_size - (int)KEY_PREFIX_SIZE,
+                    orignkey,
+                    set_time,
+                    cur_time,
+                    (int)(curr_time.tv_sec - item->client_time),
+                    item->exp_time,
+                    item->value_size,
+                    item->value_size,
+                    orignval);
+            fflush(stderr);
+          }
+        }
+      }
+      else
+      {
+        atomic_add_size(&ms_stats.vef_miss, 1);
+
+        if (ms_setting.verbose)
+        {
+          fprintf(stderr, "\n<%d data verification failed\n"
+                          "\tkey len: %d\n"
+                          "\tkey: %" PRIx64 " %.*s\n"
+                          "\texpected data len: %d\n"
+                          "\texpected data: %.*s\n"
+                          "\treceived data: \n",
+                  c->sfd, item->key_size, item->key_prefix,
+                  item->key_size - (int)KEY_PREFIX_SIZE,
+                  orignkey, item->value_size, item->value_size, orignval);
+          fflush(stderr);
+        }
+      }
+    }
+  }
+  c->mlget_task.mlget_num= 0;
+  c->mlget_task.value_index= INVALID_OFFSET;
+} /* ms_update_multi_get_result */
+
+
+/**
+ * after get the response from server for single get, the
+ * function update the state of the task and do data verify if
+ * necessary.
+ *
+ * @param c, pointer of the concurrency
+ * @param item, pointer of task item which includes the object
+ *            information
+ */
+static void ms_update_single_get_result(ms_conn_t *c, ms_task_item_t *item)
+{
+  char *orignval= NULL;
+  char *orignkey= NULL;
+
+  if ((c == NULL) || (item == NULL))
+  {
+    return;
+  }
+  assert(c != NULL);
+  assert(item != NULL);
+
+  orignval= &ms_setting.char_block[item->value_offset];
+  orignkey= &ms_setting.char_block[item->key_suffix_offset];
+
+  /* update get miss counter */
+  if ((c->precmd.cmd == CMD_GET) && c->curr_task.get_miss)
+  {
+    atomic_add_size(&ms_stats.get_misses, 1);
+  }
+
+  /* get nothing from server for this task item */
+  if ((c->precmd.cmd == CMD_GET) && c->curr_task.verify
+      && ! c->curr_task.finish_verify)
+  {
+    /* verify expire time if necessary */
+    if (item->exp_time > 0)
+    {
+      struct timeval curr_time;
+      gettimeofday(&curr_time, NULL);
+
+      /* object doesn't expire but can't get it now */
+      if (curr_time.tv_sec - item->client_time
+          < item->exp_time - EXPIRE_TIME_ERROR)
+      {
+        atomic_add_size(&ms_stats.unexp_unget, 1);
+
+        if (ms_setting.verbose)
+        {
+          char set_time[64];
+          char cur_time[64];
+          strftime(set_time, 64, "%Y-%m-%d %H:%M:%S",
+                   localtime(&item->client_time));
+          strftime(cur_time, 64, "%Y-%m-%d %H:%M:%S",
+                   localtime(&curr_time.tv_sec));
+          fprintf(stderr,
+                  "\n\t<%d expire time verification failed, object "
+                  "doesn't expire but can't get it now\n"
+                  "\tkey len: %d\n"
+                  "\tkey: %" PRIx64 " %.*s\n"
+                  "\tset time: %s current time: %s "
+                  "diff time: %d expire time: %d\n"
+                  "\texpected data len: %d\n"
+                  "\texpected data: %.*s\n"
+                  "\treceived data: \n",
+                  c->sfd,
+                  item->key_size,
+                  item->key_prefix,
+                  item->key_size - (int)KEY_PREFIX_SIZE,
+                  orignkey,
+                  set_time,
+                  cur_time,
+                  (int)(curr_time.tv_sec - item->client_time),
+                  item->exp_time,
+                  item->value_size,
+                  item->value_size,
+                  orignval);
+          fflush(stderr);
+        }
+      }
+    }
+    else
+    {
+      atomic_add_size(&ms_stats.vef_miss, 1);
+
+      if (ms_setting.verbose)
+      {
+        fprintf(stderr, "\n<%d data verification failed\n"
+                        "\tkey len: %d\n"
+                        "\tkey: %" PRIx64 " %.*s\n"
+                        "\texpected data len: %d\n"
+                        "\texpected data: %.*s\n"
+                        "\treceived data: \n",
+                c->sfd, item->key_size, item->key_prefix,
+                item->key_size - (int)KEY_PREFIX_SIZE,
+                orignkey, item->value_size, item->value_size, orignval);
+        fflush(stderr);
+      }
+    }
+  }
+} /* ms_update_single_get_result */
+
+
+/**
+ * after get the response from server for set the function
+ * update the state of the task and do data verify if necessary.
+ *
+ * @param c, pointer of the concurrency
+ * @param item, pointer of task item which includes the object
+ *            information
+ */
+static void ms_update_set_result(ms_conn_t *c, ms_task_item_t *item)
+{
+  if ((c == NULL) || (item == NULL))
+  {
+    return;
+  }
+  assert(c != NULL);
+  assert(item != NULL);
+
+  if (c->precmd.cmd == CMD_SET)
+  {
+    switch (c->precmd.retstat)
+    {
+    case MCD_STORED:
+      if (item->value_offset == INVALID_OFFSET)
+      {
+        /* first set with the same offset of key suffix */
+        item->value_offset= item->key_suffix_offset;
+      }
+      else
+      {
+        /* not first set, just increase the value offset */
+        item->value_offset+= 1;
+      }
+
+      /* set successes, update counter */
+      c->set_cursor++;
+      c->curr_task.set_opt++;
+      c->curr_task.cycle_undo_set--;
+      break;
+
+    case MCD_SERVER_ERROR:
+    default:
+      break;
+    } /* switch */
+  }
+} /* ms_update_set_result */
+
+
+/**
+ * update the response time result
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_update_stat_result(ms_conn_t *c)
+{
+  bool get_miss= false;
+
+  if (c == NULL)
+  {
+    return;
+  }
+  assert(c != NULL);
+
+  gettimeofday(&c->end_time, NULL);
+  uint64_t time_diff= (uint64_t)ms_time_diff(&c->start_time, &c->end_time);
+
+  pthread_mutex_lock(&ms_statistic.stat_mutex);
+
+  switch (c->precmd.cmd)
+  {
+  case CMD_SET:
+    ms_record_event(&ms_statistic.set_stat, time_diff, false);
+    break;
+
+  case CMD_GET:
+    if (c->curr_task.get_miss)
+    {
+      get_miss= true;
+    }
+    ms_record_event(&ms_statistic.get_stat, time_diff, get_miss);
+    break;
+
+  default:
+    break;
+  } /* switch */
+
+  ms_record_event(&ms_statistic.total_stat, time_diff, get_miss);
+  pthread_mutex_unlock(&ms_statistic.stat_mutex);
+} /* ms_update_stat_result */
+
+
+/**
+ * after get response from server for the current operation, and
+ * before doing the next operation, update the state of the
+ * current operation.
+ *
+ * @param c, pointer of the concurrency
+ */
+static void ms_update_task_result(ms_conn_t *c)
+{
+  ms_task_item_t *item;
+
+  if (c == NULL)
+  {
+    return;
+  }
+  assert(c != NULL);
+
+  item= ms_get_cur_opt_item(c);
+  if (item == NULL)
+  {
+    return;
+  }
+  assert(item != NULL);
+
+  ms_update_set_result(c, item);
+
+  if ((ms_setting.stat_freq > 0)
+      && ((c->precmd.cmd == CMD_SET) || (c->precmd.cmd == CMD_GET)))
+  {
+    ms_update_stat_result(c);
+  }
+
+  /* update multi-get task item */
+  if (((ms_setting.mult_key_num > 1)
+       && (c->mlget_task.mlget_num >= ms_setting.mult_key_num))
+      || ((c->remain_exec_num == 0) && (c->mlget_task.mlget_num > 0)))
+  {
+    ms_update_multi_get_result(c);
+  }
+  else
+  {
+    ms_update_single_get_result(c, item);
+  }
+} /* ms_update_task_result */
+
+
+/**
+ * run get and set operation
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_run_getset_task(ms_conn_t *c)
+{
+  /**
+   * extra one loop to get the last command return state. get the
+   * last command return state.
+   */
+  if ((c->remain_exec_num >= 0)
+      && (c->remain_exec_num != c->exec_num))
+  {
+    ms_update_task_result(c);
+  }
+
+  /* multi-get */
+  if (ms_setting.mult_key_num > 1)
+  {
+    /* operate next task item */
+    ms_multi_getset_task_sch(c);
+  }
+  else
+  {
+    /* operate next task item */
+    ms_single_getset_task_sch(c);
+  }
+
+  /* no task to do, exit */
+  if ((c->remain_exec_num == -1) || ms_global.time_out)
+  {
+    return -1;
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_run_getset_task */
+
+
+/**
+ * the state machine call the function to execute task.
+ *
+ * @param c, pointer of the concurrency
+ *
+ * @return int, if success, return EXIT_SUCCESS, else return -1
+ */
+int ms_exec_task(struct conn *c)
+{
+  if (! ms_global.finish_warmup)
+  {
+    ms_warmup_server(c);
+  }
+  else
+  {
+    if (ms_run_getset_task(c) != 0)
+    {
+      return -1;
+    }
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_exec_task */
diff --git a/src/bin/ms_task.h b/src/bin/ms_task.h
new file mode 100644 (file)
index 0000000..c4917d1
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * File:   ms_task.h
+ * Author: Mingqiang Zhuang
+ *
+ * Created on February 10, 2009
+ *
+ * (c) Copyright 2009, Schooner Information Technology, Inc.
+ * http://www.schoonerinfotech.com/
+ *
+ */
+#ifndef MS_TASK_H
+#define MS_TASK_H
+
+#include <sys/types.h>
+#include <stdint.h>
+#if !defined(__cplusplus)
+# include <stdbool.h>
+#endif
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define UNIT_ITEMS_COUNT     1024               /* each window unit has 1024 items */
+#define KEY_PREFIX_SIZE      (sizeof(uint64_t)) /* key prefix length: 8 bytes */
+#define INVALID_OFFSET       (-1)               /* invalid offset in the character table */
+#define FIXED_EXPIRE_TIME    60                 /* default expire time is 60s */
+#define EXPIRE_TIME_ERROR    5                  /* default expire time error is 5s */
+
+/* information of a task item(object) */
+typedef struct task_item
+{
+  uint64_t key_prefix;                  /* prefix of the key, 8 bytes, binary */
+  int key_size;                         /* key size */
+  int key_suffix_offset;                /* suffix offset in the global character table */
+
+  int value_size;                       /* data size */
+  int value_offset;                     /* data offset in the global character table */
+
+  time_t client_time;                   /* the current client time */
+  int exp_time;                         /* expire time */
+} ms_task_item_t;
+
+/* task item for multi-get */
+typedef struct mlget_task_item
+{
+  ms_task_item_t *item;                 /* task item */
+  bool verify;                          /* whether verify data or not */
+  bool finish_verify;                   /* whether finish data verify or not */
+  bool get_miss;                        /* whether get miss or not */
+} ms_mlget_task_item_t;
+
+/* information of multi-get task */
+typedef struct mlget_task
+{
+  ms_mlget_task_item_t *mlget_item;        /* multi-get task array */
+  int mlget_num;                           /* how many tasks in mlget_task array */
+  int value_index;                         /* the nth value received by the connect, for multi-get */
+} ms_mlget_task_t;
+
+/* structure used to store the state of the running task */
+typedef struct task
+{
+  int cmd;                              /* command name */
+  bool verify;                          /* whether verify data or not */
+  bool finish_verify;                   /* whether finish data verify or not */
+  bool get_miss;                        /* whether get miss or not */
+  ms_task_item_t *item;                 /* task item */
+
+  /* counter for command distribution adjustment */
+  uint64_t get_opt;                     /* number of total get operations */
+  uint64_t set_opt;                     /* number of total set operations, no including warmup set count */
+  int cycle_undo_get;                   /* number of undo get in an adjustment cycle */
+  int cycle_undo_set;                   /* number of undo set in an adjustment cycle */
+  uint64_t verified_get;                /* number of total verified get operations */
+  uint64_t overwrite_set;               /* number of total overwrite set operations */
+} ms_task_t;
+
+struct conn;
+
+/* the state machine call the function to execute task.*/
+int ms_exec_task(struct conn *c);
+
+
+/* calculate the difference value of two time points */
+int64_t ms_time_diff(struct timeval *start_time, struct timeval *end_time);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of MS_TASK_H */
diff --git a/src/bin/ms_thread.c b/src/bin/ms_thread.c
new file mode 100644 (file)
index 0000000..f9f52bf
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * File:   ms_thread.c
+ * Author: Mingqiang Zhuang
+ *
+ * Created on February 10, 2009
+ *
+ * (c) Copyright 2009, Schooner Information Technology, Inc.
+ * http://www.schoonerinfotech.com/
+ *
+ */
+
+#include "mem_config.h"
+
+#if defined(HAVE_SYS_TIME_H)
+# include <sys/time.h>
+#endif
+
+#if defined(HAVE_TIME_H)
+# include <time.h>
+#endif
+
+#include "ms_thread.h"
+#include "ms_setting.h"
+#include "ms_atomic.h"
+
+/* global variable */
+pthread_key_t ms_thread_key;
+
+/* array of thread context structure, each thread has a thread context structure */
+static ms_thread_ctx_t *ms_thread_ctx;
+
+/* functions */
+static void ms_set_current_time(void);
+static void ms_check_sock_timeout(void);
+static void ms_clock_handler(const int fd, const short which, void *arg);
+static uint32_t ms_set_thread_cpu_affinity(uint32_t cpu);
+static int ms_setup_thread(ms_thread_ctx_t *thread_ctx);
+static void *ms_worker_libevent(void *arg);
+static void ms_create_worker(void *(*func)(void *), void *arg);
+
+
+/**
+ *  time-sensitive callers can call it by hand with this,
+ *  outside the normal ever-1-second timer
+ */
+static void ms_set_current_time()
+{
+  struct timeval timer;
+  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
+
+  gettimeofday(&timer, NULL);
+  ms_thread->curr_time= (rel_time_t)timer.tv_sec;
+} /* ms_set_current_time */
+
+
+/**
+ *  used to check whether UDP of command are waiting timeout
+ *  by the ever-1-second timer
+ */
+static void ms_check_sock_timeout(void)
+{
+  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
+  ms_conn_t *c= NULL;
+  int time_diff= 0;
+
+  for (uint32_t i= 0; i < ms_thread->thread_ctx->nconns; i++)
+  {
+    c= &ms_thread->conn[i];
+
+    if (c->udp)
+    {
+      time_diff= (int)(ms_thread->curr_time - (rel_time_t)c->start_time.tv_sec);
+
+      /* wait time out */
+      if (time_diff > SOCK_WAIT_TIMEOUT)
+      {
+        /* calculate dropped packets count */
+        if (c->recvpkt > 0)
+        {
+          atomic_add_size(&ms_stats.pkt_drop, c->packets - c->recvpkt);
+        }
+
+        atomic_add_size(&ms_stats.udp_timeout, 1);
+        ms_reset_conn(c, true);
+      }
+    }
+  }
+} /* ms_check_sock_timeout */
+
+
+/* if disconnect, the ever-1-second timer will call this function to reconnect */
+static void ms_reconn_thread_socks(void)
+{
+  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
+  for (uint32_t i= 0; i < ms_thread->thread_ctx->nconns; i++)
+  {
+    ms_reconn_socks(&ms_thread->conn[i]);
+  }
+} /* ms_reconn_thread_socks */
+
+
+/**
+ * the handler of the ever-1-second timer
+ *
+ * @param fd, the descriptors of the socket
+ * @param which, event flags
+ * @param arg, argument
+ */
+static void ms_clock_handler(const int fd, const short which, void *arg)
+{
+  ms_thread_t *ms_thread= pthread_getspecific(ms_thread_key);
+  struct timeval t=
+  {
+    .tv_sec= 1, .tv_usec= 0
+  };
+
+  UNUSED_ARGUMENT(fd);
+  UNUSED_ARGUMENT(which);
+  UNUSED_ARGUMENT(arg);
+
+  ms_set_current_time();
+
+  if (ms_thread->initialized)
+  {
+    /* only delete the event if it's actually there. */
+    evtimer_del(&ms_thread->clock_event);
+    ms_check_sock_timeout();
+  }
+  else
+  {
+    ms_thread->initialized= true;
+  }
+
+  ms_reconn_thread_socks();
+
+  evtimer_set(&ms_thread->clock_event, ms_clock_handler, 0);
+  event_base_set(ms_thread->base, &ms_thread->clock_event);
+  evtimer_add(&ms_thread->clock_event, &t);
+} /* ms_clock_handler */
+
+
+/**
+ * used to bind thread to CPU if the system supports
+ *
+ * @param cpu, cpu index
+ *
+ * @return if success, return EXIT_SUCCESS, else return -1
+ */
+static uint32_t ms_set_thread_cpu_affinity(uint32_t cpu)
+{
+  uint32_t ret= 0;
+
+#ifdef HAVE_CPU_SET_T
+  cpu_set_t cpu_set;
+  CPU_ZERO(&cpu_set);
+  CPU_SET(cpu, &cpu_set);
+
+  if (sched_setaffinity(0, sizeof(cpu_set_t), &cpu_set) == -1)
+  {
+    fprintf(stderr, "WARNING: Could not set CPU Affinity, continuing...\n");
+    ret= 1;
+  }
+#else
+  UNUSED_ARGUMENT(cpu);
+#endif
+
+  return ret;
+} /* ms_set_thread_cpu_affinity */
+
+
+/**
+ * Set up a thread's information.
+ *
+ * @param thread_ctx, pointer of the thread context structure
+ *
+ * @return if success, return EXIT_SUCCESS, else return -1
+ */
+static int ms_setup_thread(ms_thread_ctx_t *thread_ctx)
+{
+
+  ms_thread_t *ms_thread= (ms_thread_t *)calloc(sizeof(*ms_thread), 1);
+  pthread_setspecific(ms_thread_key, (void *)ms_thread);
+
+  ms_thread->thread_ctx= thread_ctx;
+  ms_thread->nactive_conn= thread_ctx->nconns;
+  ms_thread->initialized= false;
+  static ATOMIC uint32_t cnt= 0;
+
+  gettimeofday(&ms_thread->startup_time, NULL);
+
+  ms_thread->base= event_init();
+  if (ms_thread->base == NULL)
+  {
+    if (atomic_add_32_nv(&cnt, 1) == 0)
+    {
+      fprintf(stderr, "Can't allocate event base.\n");
+    }
+
+    return -1;
+  }
+
+  ms_thread->conn=
+    (ms_conn_t *)malloc((size_t)thread_ctx->nconns * sizeof(ms_conn_t));
+  if (ms_thread->conn == NULL)
+  {
+    if (atomic_add_32_nv(&cnt, 1) == 0)
+    {
+      fprintf(
+        stderr,
+        "Can't allocate concurrency structure for thread descriptors.");
+    }
+
+    return -1;
+  }
+  memset(ms_thread->conn, 0, (size_t)thread_ctx->nconns * sizeof(ms_conn_t));
+
+  for (uint32_t i= 0; i < thread_ctx->nconns; i++)
+  {
+    ms_thread->conn[i].conn_idx= i;
+    if (ms_setup_conn(&ms_thread->conn[i]) != 0)
+    {
+      /* only output this error once */
+      if (atomic_add_32_nv(&cnt, 1) == 0)
+      {
+        fprintf(stderr, "Initializing connection failed.\n");
+      }
+
+      return -1;
+    }
+  }
+
+  return EXIT_SUCCESS;
+} /* ms_setup_thread */
+
+
+/**
+ * Worker thread: main event loop
+ *
+ * @param arg, the pointer of argument
+ *
+ * @return void*
+ */
+static void *ms_worker_libevent(void *arg)
+{
+  ms_thread_t *ms_thread= NULL;
+  ms_thread_ctx_t *thread_ctx= (ms_thread_ctx_t *)arg;
+
+  /**
+   * If system has more than one cpu and supports set cpu
+   * affinity, try to bind each thread to a cpu core;
+   */
+  if (ms_setting.ncpu > 1)
+  {
+    ms_set_thread_cpu_affinity(thread_ctx->thd_idx % ms_setting.ncpu);
+  }
+
+  if (ms_setup_thread(thread_ctx) != 0)
+  {
+    exit(1);
+  }
+
+  /* each thread with a timer */
+  ms_clock_handler(0, 0, 0);
+
+  pthread_mutex_lock(&ms_global.init_lock.lock);
+  ms_global.init_lock.count++;
+  pthread_cond_signal(&ms_global.init_lock.cond);
+  pthread_mutex_unlock(&ms_global.init_lock.lock);
+
+  ms_thread= pthread_getspecific(ms_thread_key);
+  event_base_loop(ms_thread->base, 0);
+
+  return NULL;
+} /* ms_worker_libevent */
+
+
+/**
+ * Creates a worker thread.
+ *
+ * @param func, the callback function
+ * @param arg, the argument to pass to the callback function
+ */
+static void ms_create_worker(void *(*func)(void *), void *arg)
+{
+  pthread_t thread;
+  pthread_attr_t attr;
+  int ret;
+
+  pthread_attr_init(&attr);
+
+  if ((ret= pthread_create(&thread, &attr, func, arg)) != 0)
+  {
+    fprintf(stderr, "Can't create thread: %s.\n", strerror(ret));
+    exit(1);
+  }
+} /* ms_create_worker */
+
+
+/* initialize threads */
+void ms_thread_init()
+{
+  ms_thread_ctx=
+    (ms_thread_ctx_t *)malloc(
+      sizeof(ms_thread_ctx_t) * (size_t)ms_setting.nthreads);
+  if (ms_thread_ctx == NULL)
+  {
+    fprintf(stderr, "Can't allocate thread descriptors.");
+    exit(1);
+  }
+
+  for (uint32_t i= 0; i < ms_setting.nthreads; i++)
+  {
+    ms_thread_ctx[i].thd_idx= i;
+    ms_thread_ctx[i].nconns= ms_setting.nconns / ms_setting.nthreads;
+
+    /**
+     *  If only one server, all the connections in all threads
+     *  connects the same server. For support multi-servers, simple
+     *  distribute thread to server.
+     */
+    ms_thread_ctx[i].srv_idx= i % ms_setting.srv_cnt;
+    ms_thread_ctx[i].tps_perconn= ms_setting.expected_tps
+                                  / (int)ms_setting.nconns;
+    ms_thread_ctx[i].exec_num_perconn= ms_setting.exec_num
+                                       / ms_setting.nconns;
+  }
+
+  if (pthread_key_create(&ms_thread_key, NULL))
+  {
+    fprintf(stderr, "Can't create pthread keys. Major malfunction!\n");
+    exit(1);
+  }
+  /* Create threads after we've done all the epoll setup. */
+  for (uint32_t i= 0; i < ms_setting.nthreads; i++)
+  {
+    ms_create_worker(ms_worker_libevent, (void *)&ms_thread_ctx[i]);
+  }
+} /* ms_thread_init */
+
+
+/* cleanup some resource of threads when all the threads exit */
+void ms_thread_cleanup()
+{
+  if (ms_thread_ctx != NULL)
+  {
+    free(ms_thread_ctx);
+  }
+  pthread_key_delete(ms_thread_key);
+} /* ms_thread_cleanup */
diff --git a/src/bin/ms_thread.h b/src/bin/ms_thread.h
new file mode 100644 (file)
index 0000000..8cb98bd
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * File:   ms_thread.h
+ * Author: Mingqiang Zhuang
+ *
+ * Created on February 10, 2009
+ *
+ * (c) Copyright 2009, Schooner Information Technology, Inc.
+ * http://www.schoonerinfotech.com/
+ *
+ */
+
+/**
+ * Asynchronous memslap has the similar implementation of
+ * multi-threads with memcached. Asynchronous memslap creates
+ * one or more self-governed threads; each thread is bound with
+ * one CPU core if the system supports setting CPU core
+ * affinity. And every thread has private variables. There is
+ * less communication or some shared resources among all the
+ * threads. It can improve the performance because there are
+ * fewer locks and competition. In addition, each thread has a
+ * libevent to manage the events of network. Each thread has one
+ * or more self-governed concurrencies; each concurrency has one
+ * or more socket connections. All the concurrencies don't
+ * communicate with each other even though they are in the same
+ * thread.
+ */
+#ifndef MS_THREAD_H
+#define MS_THREAD_H
+
+#include <sched.h>
+#include "ms_conn.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Time relative to server start. Smaller than time_t on 64-bit systems. */
+typedef unsigned int   rel_time_t;
+
+/* Used to store the context of each thread */
+typedef struct thread_ctx
+{
+  uint32_t thd_idx;                          /* the thread index */
+  uint32_t nconns;                           /* how many connections included by the thread */
+  uint32_t srv_idx;                          /* index of the thread */
+  int tps_perconn;                      /* expected throughput per connection */
+  int64_t exec_num_perconn;             /* execute number per connection */
+} ms_thread_ctx_t;
+
+/* Used to store the private variables of each thread */
+typedef struct thread
+{
+  ms_conn_t *conn;                      /* conn array to store all the conn in the thread */
+  uint32_t nactive_conn;                     /* how many connects are active */
+
+  ms_thread_ctx_t *thread_ctx;          /* thread context from the caller */
+  struct event_base *base;              /* libevent handler created by this thread */
+
+  rel_time_t curr_time;                 /* current time */
+  struct event clock_event;             /* clock event to time each one second */
+  bool initialized;                     /* whether clock_event has been initialized */
+
+  struct timeval startup_time;          /* start time of the thread */
+} ms_thread_t;
+
+/* initialize threads */
+void ms_thread_init(void);
+
+
+/* cleanup some resource of threads when all the threads exit */
+void ms_thread_cleanup(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of MS_THREAD_H */
diff --git a/src/bin/utilities.cc b/src/bin/utilities.cc
new file mode 100644 (file)
index 0000000..fe8f501
--- /dev/null
@@ -0,0 +1,197 @@
+/* LibMemcached
+ * Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+#include <mem_config.h>
+
+#include "utilities.h"
+
+#include <cstdio>
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+#include <ctype.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+
+long int timedif(struct timeval a, struct timeval b)
+{
+  long us, s;
+
+  us = (int)(a.tv_usec - b.tv_usec);
+  us /= 1000;
+  s = (int)(a.tv_sec - b.tv_sec);
+  s *= 1000;
+  return s + us;
+}
+
+void version_command(const char *command_name)
+{
+  printf("%s v%u.%u\n", command_name, 1U, 0U);
+  exit(EXIT_SUCCESS);
+}
+
+void close_stdio(void)
+{
+  int fd;
+  if ((fd = open("/dev/null", O_RDWR, 0)) < 0)
+  {
+    return;
+  }
+  else
+  {
+    if (dup2(fd, STDIN_FILENO) < 0)
+    {
+      return;
+    }
+
+    if (dup2(fd, STDOUT_FILENO) < 0)
+    {
+      return;
+    }
+
+    if (dup2(fd, STDERR_FILENO) < 0)
+    {
+      return;
+    }
+
+    if (fd > STDERR_FILENO)
+    {
+      close(fd);
+    }
+  }
+}
+
+
+static const char *lookup_help(memcached_options option)
+{
+  switch (option)
+  {
+  case OPT_SERVERS: return("List which servers you wish to connect to.");
+  case OPT_VERSION: return("Display the version of the application and then exit.");
+  case OPT_HELP: return("Display this message and then exit.");
+  case OPT_VERBOSE: return("Give more details on the progression of the application.");
+  case OPT_QUIET: return("stderr and stdin will be closed at application startup.");
+  case OPT_DEBUG: return("Provide output only useful for debugging.");
+  case OPT_FLAG: return("Provide flag information for storage operation.");
+  case OPT_EXPIRE: return("Set the expire option for the object.");
+  case OPT_SET: return("Use set command with memcached when storing.");
+  case OPT_REPLACE: return("Use replace command with memcached when storing.");
+  case OPT_ADD: return("Use add command with memcached when storing.");
+  case OPT_SLAP_EXECUTE_NUMBER: return("Number of times to execute the given test.");
+  case OPT_SLAP_INITIAL_LOAD: return("Number of key pairs to load before executing tests.");
+  case OPT_SLAP_TEST: return("Test to run (currently \"get\" or \"set\").");
+  case OPT_SLAP_CONCURRENCY: return("Number of users to simulate with load.");
+  case OPT_SLAP_NON_BLOCK: return("Set TCP up to use non-blocking IO.");
+  case OPT_SLAP_TCP_NODELAY: return("Set TCP socket up to use nodelay.");
+  case OPT_FLUSH: return("Flush servers before running tests.");
+  case OPT_HASH: return("Select hash type.");
+  case OPT_BINARY: return("Switch to binary protocol.");
+  case OPT_ANALYZE: return("Analyze the provided servers.");
+  case OPT_UDP: return("Use UDP protocol when communicating with server.");
+  case OPT_BUFFER: return("Enable request buffering.");
+  case OPT_USERNAME: return "Username to use for SASL authentication";
+  case OPT_PASSWD: return "Password to use for SASL authentication";
+  case OPT_FILE: return "Path to file in which to save result";
+  case OPT_STAT_ARGS: return "Argument for statistics";
+  case OPT_SERVER_VERSION: return "Memcached daemon software version";
+  default:
+                      break;
+  };
+
+  assert(0);
+  return "forgot to document this function :)";
+}
+
+void help_command(const char *command_name, const char *description,
+                  const struct option *long_options,
+                  memcached_programs_help_st *options)
+{
+  unsigned int x;
+  (void)options;
+
+  printf("%s v%u.%u\n\n", command_name, 1U, 0U);
+  printf("\t%s\n\n", description);
+  printf("Current options. A '=' means the option takes a value.\n\n");
+
+  for (x= 0; long_options[x].name; x++)
+  {
+    const char *help_message;
+
+    printf("\t --%s%c\n", long_options[x].name,
+           long_options[x].has_arg ? '=' : ' ');
+    if ((help_message= lookup_help(memcached_options(long_options[x].val))))
+      printf("\t\t%s\n", help_message);
+  }
+
+  printf("\n");
+  exit(EXIT_SUCCESS);
+}
+
+void process_hash_option(memcached_st *memc, char *opt_hash)
+{
+  uint64_t set;
+  memcached_return_t rc;
+
+  if (opt_hash == NULL)
+  {
+    return;
+  }
+
+  set= MEMCACHED_HASH_DEFAULT; /* Just here to solve warning */
+  if (!strcasecmp(opt_hash, "CRC"))
+  {
+    set= MEMCACHED_HASH_CRC;
+  }
+  else if (!strcasecmp(opt_hash, "FNV1_64"))
+  {
+    set= MEMCACHED_HASH_FNV1_64;
+  }
+  else if (!strcasecmp(opt_hash, "FNV1A_64"))
+  {
+    set= MEMCACHED_HASH_FNV1A_64;
+  }
+  else if (!strcasecmp(opt_hash, "FNV1_32"))
+  {
+    set= MEMCACHED_HASH_FNV1_32;
+  }
+  else if (!strcasecmp(opt_hash, "FNV1A_32"))
+  {
+    set= MEMCACHED_HASH_FNV1A_32;
+  }
+  else
+  {
+    fprintf(stderr, "hash: type not recognized %s\n", opt_hash);
+    exit(EXIT_FAILURE);
+  }
+
+  rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, set);
+  if (rc != MEMCACHED_SUCCESS)
+  {
+    fprintf(stderr, "hash: memcache error %s\n", memcached_strerror(memc, rc));
+    exit(EXIT_FAILURE);
+  }
+}
+
+void initialize_sockets(void)
+{
+  /* Define the function for all platforms to avoid #ifdefs in each program */
+#if defined(_WIN32)
+  WSADATA wsaData;
+  if (WSAStartup(MAKEWORD(2,0), &wsaData) != 0)
+  {
+    fprintf(stderr, "Socket Initialization Error. Program aborted\n");
+    exit(EXIT_FAILURE);
+  }
+#endif // #if defined(_WIN32)
+}
diff --git a/src/bin/utilities.h b/src/bin/utilities.h
new file mode 100644 (file)
index 0000000..e275fa8
--- /dev/null
@@ -0,0 +1,62 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+#pragma once
+
+#include <getopt.h>
+#include <libmemcached-1.0/memcached.h>
+#include "client_options.h"
+
+#if defined(HAVE_SYS_TIME_H)
+# include <sys/time.h>
+#endif
+
+#if defined(HAVE_TIME_H)
+# include <time.h>
+#endif
+
+
+#ifdef __sun
+  /* For some odd reason the option struct on solaris defines the argument
+   * as char* and not const char*
+   */
+#define OPTIONSTRING char*
+#else
+#define OPTIONSTRING const char*
+#endif
+
+typedef struct memcached_programs_help_st memcached_programs_help_st;
+
+struct memcached_programs_help_st
+{
+  char *not_used_yet;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char *strdup_cleanup(const char *str);
+void cleanup(void);
+long int timedif(struct timeval a, struct timeval b);
+void version_command(const char *command_name) __attribute__ ((noreturn));
+void help_command(const char *command_name, const char *description,
+                  const struct option *long_options,
+                  memcached_programs_help_st *options) __attribute__ ((noreturn));
+void process_hash_option(memcached_st *memc, char *opt_hash);
+bool initialize_sasl(memcached_st *memc, char *user, char *password);
+void shutdown_sasl(void);
+void initialize_sockets(void);
+void close_stdio(void);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/src/libhashkit/CMakeLists.txt b/src/libhashkit/CMakeLists.txt
new file mode 100644 (file)
index 0000000..08c4835
--- /dev/null
@@ -0,0 +1,47 @@
+if(HAVE_HSIEH_HASH)
+    set(HSIEH_CC hsieh.cc)
+else()
+    set(HSIEH_CC nohsieh.cc)
+endif()
+
+add_library(libhashkit SHARED
+        aes.cc
+        algorithm.cc
+        behavior.cc
+        crc32.cc
+        digest.cc
+        encrypt.cc
+        fnv_32.cc
+        fnv_64.cc
+        function.cc
+        has.cc
+        hashkit.cc
+        ${HSIEH_CC}
+        jenkins.cc
+        ketama.cc
+        md5.cc
+        murmur.cc
+        murmur3.cc
+        murmur3_api.cc
+        nohsieh.cc
+        one_at_a_time.cc
+        rijndael.cc
+        str_algorithm.cc
+        strerror.cc
+        string.cc
+        )
+add_library(hashkit ALIAS libhashkit)
+set_target_properties(libhashkit PROPERTIES LIBRARY_OUTPUT_NAME hashkit)
+target_compile_options(libhashkit PRIVATE -DBUILDING_HASHKIT)
+
+configure_file(hashkitcon.h.in hashkitcon.h @ONLY)
+
+set_target_properties(libhashkit PROPERTIES SOVERSION ${LIBHASHKIT_SO_VERSION})
+install(TARGETS libhashkit EXPORT libhashkit
+        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+export(EXPORT libhashkit)
+install(EXPORT libhashkit DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake)
+install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+        FILES_MATCHING PATTERN hashkit.h
+        )
diff --git a/src/libhashkit/aes.cc b/src/libhashkit/aes.cc
new file mode 100644 (file)
index 0000000..12adcae
--- /dev/null
@@ -0,0 +1,185 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libhashkit library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include "libhashkit/common.h"
+
+#include "libhashkit/rijndael.hpp"
+
+#include <cstring>
+
+#define AES_KEY_LENGTH 256               /* 128, 192, 256 */
+#define AES_BLOCK_SIZE 16
+
+enum encrypt_t
+{
+  AES_ENCRYPT,
+  AES_DECRYPT
+};
+
+struct _key_t {
+  int nr;
+  uint32_t rk[4*(AES_MAXNR +1)];
+};
+
+struct aes_key_t {
+  _key_t encode_key;
+  _key_t decode_key;
+};
+
+aes_key_t* aes_create_key(const char *key, const size_t key_length)
+{
+  aes_key_t* _aes_key= (aes_key_t*)(calloc(1, sizeof(aes_key_t)));
+  if (_aes_key)
+  {
+    uint8_t rkey[AES_KEY_LENGTH/8];
+    uint8_t *rkey_end= rkey +AES_KEY_LENGTH/8;
+    const char *key_end= key +key_length;
+
+    memset(rkey, 0, sizeof(rkey));      /* Set initial key  */
+
+    uint8_t *ptr= rkey;
+    const char* sptr= key;
+    for (; sptr < key_end; ptr++,sptr++)
+    {
+      if (ptr == rkey_end)
+      {
+        ptr= rkey;  /*  Just loop over tmp_key until we used all key */
+      }
+      *ptr^= (uint8_t)(*sptr);
+    }
+
+    _aes_key->decode_key.nr= rijndaelKeySetupDec(_aes_key->decode_key.rk, rkey, AES_KEY_LENGTH);
+    _aes_key->encode_key.nr= rijndaelKeySetupEnc(_aes_key->encode_key.rk, rkey, AES_KEY_LENGTH);
+  }
+
+  return _aes_key;
+}
+
+aes_key_t* aes_clone_key(aes_key_t *_aes_key)
+{
+  if (_aes_key == NULL)
+  {
+    return NULL;
+  }
+
+  aes_key_t* _aes_clone_key= (aes_key_t*)(calloc(1, sizeof(aes_key_t)));
+  if (_aes_clone_key)
+  {
+    memcpy(_aes_clone_key, _aes_key, sizeof(aes_key_t));
+  }
+
+  return _aes_clone_key;
+}
+
+hashkit_string_st* aes_encrypt(aes_key_t *_aes_key,
+                               const char* source, size_t source_length)
+{
+  if (_aes_key == NULL)
+  {
+    return NULL;
+  }
+
+  size_t num_blocks= source_length/AES_BLOCK_SIZE;
+
+  hashkit_string_st* destination= hashkit_string_create(source_length);
+  if (destination)
+  {
+    char *dest= hashkit_string_c_str_mutable(destination);
+
+    for (size_t x= num_blocks; x > 0; x--)   /* Encode complete blocks */
+    { 
+      rijndaelEncrypt(_aes_key->encode_key.rk, _aes_key->encode_key.nr, (const uint8_t*)(source),
+                      (uint8_t*) (dest));
+      source+= AES_BLOCK_SIZE;
+      dest+= AES_BLOCK_SIZE;
+    }
+
+    uint8_t block[AES_BLOCK_SIZE];
+    char pad_len= AES_BLOCK_SIZE - (source_length - AES_BLOCK_SIZE*num_blocks);
+    memcpy(block, source, 16 -pad_len);
+    memset(block + AES_BLOCK_SIZE -pad_len, pad_len, pad_len);
+    rijndaelEncrypt(_aes_key->encode_key.rk, _aes_key->encode_key.nr, block, (uint8_t*) (dest));
+    hashkit_string_set_length(destination, AES_BLOCK_SIZE*(num_blocks + 1));
+  }
+
+  return destination;
+}
+
+hashkit_string_st* aes_decrypt(aes_key_t *_aes_key,
+                               const char* source, size_t source_length)
+{
+  if (_aes_key == NULL)
+  {
+    return NULL;
+  }
+
+  size_t num_blocks= source_length/AES_BLOCK_SIZE;
+  if ((source_length != num_blocks*AES_BLOCK_SIZE) or num_blocks ==0 )
+  {
+    return NULL;
+  }
+
+  hashkit_string_st* destination= hashkit_string_create(source_length);
+  if (destination)
+  {
+    char *dest= hashkit_string_c_str_mutable(destination);
+
+    for (size_t x = num_blocks-1; x > 0; x--)
+    {
+      rijndaelDecrypt(_aes_key->decode_key.rk, _aes_key->decode_key.nr, (const uint8_t*) (source), (uint8_t*)(dest));
+      source+= AES_BLOCK_SIZE;
+      dest+= AES_BLOCK_SIZE;
+    }
+
+    uint8_t block[AES_BLOCK_SIZE];
+    rijndaelDecrypt(_aes_key->decode_key.rk, _aes_key->decode_key.nr, (const uint8_t*)(source), block);
+    /* Use last char in the block as size */
+    unsigned int pad_len= (unsigned int) (unsigned char)(block[AES_BLOCK_SIZE-1]);
+    if (pad_len > AES_BLOCK_SIZE)
+    {
+      hashkit_string_free(destination);
+      return NULL;
+    }
+
+    /* We could also check whole padding but we do not really need this */
+
+    memcpy(dest, block, AES_BLOCK_SIZE - pad_len);
+    hashkit_string_set_length(destination, AES_BLOCK_SIZE*num_blocks - pad_len);
+  }
+
+  return destination;
+}
diff --git a/src/libhashkit/aes.h b/src/libhashkit/aes.h
new file mode 100644 (file)
index 0000000..c46ffa2
--- /dev/null
@@ -0,0 +1,49 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+struct aes_key_t;
+
+hashkit_string_st* aes_encrypt(aes_key_t* _aes_key,
+                               const char* source, size_t source_length);
+
+hashkit_string_st* aes_decrypt(aes_key_t* _aes_key,
+                               const char* source, size_t source_length);
+
+aes_key_t* aes_create_key(const char *key, const size_t key_length);
+
+aes_key_t* aes_clone_key(aes_key_t* _aes_key);
diff --git a/src/libhashkit/algorithm.cc b/src/libhashkit/algorithm.cc
new file mode 100644 (file)
index 0000000..3eb28d6
--- /dev/null
@@ -0,0 +1,98 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  HashKit library
+ *
+ *  Copyright (C) 2006-2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libhashkit/common.h"
+
+uint32_t libhashkit_one_at_a_time(const char *key, size_t key_length)
+{
+  return hashkit_one_at_a_time(key, key_length, NULL);
+}
+
+uint32_t libhashkit_fnv1_64(const char *key, size_t key_length)
+{
+  return hashkit_fnv1_64(key, key_length, NULL);
+}
+
+uint32_t libhashkit_fnv1a_64(const char *key, size_t key_length)
+{
+  return hashkit_fnv1a_64(key, key_length, NULL);
+}
+
+uint32_t libhashkit_fnv1_32(const char *key, size_t key_length)
+{
+  return hashkit_fnv1_32(key, key_length, NULL);
+}
+
+uint32_t libhashkit_fnv1a_32(const char *key, size_t key_length)
+{
+  return hashkit_fnv1a_32(key, key_length, NULL);
+}
+
+uint32_t libhashkit_crc32(const char *key, size_t key_length)
+{
+  return hashkit_crc32(key, key_length, NULL);
+}
+
+uint32_t libhashkit_hsieh(const char *key, size_t key_length)
+{
+  return hashkit_hsieh(key, key_length, NULL);
+}
+
+uint32_t libhashkit_murmur3(const char *key, size_t key_length)
+{
+  return hashkit_murmur3(key, key_length, NULL);
+}
+
+uint32_t libhashkit_murmur(const char *key, size_t key_length)
+{
+  return hashkit_murmur(key, key_length, NULL);
+}
+
+uint32_t libhashkit_jenkins(const char *key, size_t key_length)
+{
+  return hashkit_jenkins(key, key_length, NULL);
+}
+
+uint32_t libhashkit_md5(const char *key, size_t key_length)
+{
+  return hashkit_md5(key, key_length, NULL);
+}
+
+void libhashkit_md5_signature(const unsigned char *key, size_t length, unsigned char *result)
+{
+  md5_signature(key, (uint32_t)length, result);
+}
+
diff --git a/src/libhashkit/algorithm.h b/src/libhashkit/algorithm.h
new file mode 100644 (file)
index 0000000..93cdc1d
--- /dev/null
@@ -0,0 +1,66 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+/**
+ * @file
+ * @brief HashKit Header
+ */
+
+#pragma once
+
+uint32_t hashkit_one_at_a_time(const char *key, size_t key_length, void *context);
+
+uint32_t hashkit_fnv1_64(const char *key, size_t key_length, void *context);
+
+uint32_t hashkit_fnv1a_64(const char *key, size_t key_length, void *context);
+
+uint32_t hashkit_fnv1_32(const char *key, size_t key_length, void *context);
+
+uint32_t hashkit_fnv1a_32(const char *key, size_t key_length, void *context);
+
+uint32_t hashkit_crc32(const char *key, size_t key_length, void *context);
+
+uint32_t hashkit_hsieh(const char *key, size_t key_length, void *context);
+
+uint32_t hashkit_murmur(const char *key, size_t key_length, void *context);
+
+uint32_t hashkit_murmur3(const char *key, size_t key_length, void *context);
+
+uint32_t hashkit_jenkins(const char *key, size_t key_length, void *context);
+
+uint32_t hashkit_md5(const char *key, size_t key_length, void *context);
diff --git a/src/libhashkit/behavior.cc b/src/libhashkit/behavior.cc
new file mode 100644 (file)
index 0000000..6c7a9ac
--- /dev/null
@@ -0,0 +1,38 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  HashKit library
+ *
+ *  Copyright (C) 2009-2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libhashkit/common.h>
diff --git a/src/libhashkit/common.h b/src/libhashkit/common.h
new file mode 100644 (file)
index 0000000..d32d31b
--- /dev/null
@@ -0,0 +1,70 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#include "libhashkit/hashkitcon.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#ifndef __WORDSIZE
+# ifdef __MINGW32__
+#  define __WORDSIZE 32
+# endif
+#endif
+
+#include <libhashkit-1.0/hashkit.h>
+#include "libhashkit/algorithm.h"
+#include "libhashkit/is.h"
+#include "libhashkit/string.h"
+#include "libhashkit/aes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void md5_signature(const unsigned char *key, unsigned int length, unsigned char *result);
+
+int update_continuum(hashkit_st *hashkit);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/libhashkit/crc32.cc b/src/libhashkit/crc32.cc
new file mode 100644 (file)
index 0000000..fe9fe71
--- /dev/null
@@ -0,0 +1,122 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  HashKit library
+ *
+ *  Copyright (C) 2009-2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* The crc32 functions and data was originally written by Spencer
+ * Garrett <srg@quick.com> and was gleaned from the PostgreSQL source
+ * tree via the files contrib/ltree/crc32.[ch] and from FreeBSD at
+ * src/usr.bin/cksum/crc32.c.
+ */
+
+#include <libhashkit/common.h>
+
+static const uint32_t crc32tab[256] = {
+  0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+  0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+  0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+  0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+  0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+  0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+  0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+  0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+  0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+  0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+  0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+  0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+  0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+  0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+  0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+  0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+  0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+  0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+  0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+  0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+  0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+  0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+  0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+  0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+  0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+  0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+  0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+  0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+  0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+  0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+  0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+  0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+  0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+  0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+  0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+  0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+  0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+  0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+  0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+  0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+  0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+  0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+  0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+  0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+  0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+  0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+  0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+  0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+  0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+  0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+  0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+  0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+  0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+  0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+  0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+  0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+  0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+  0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+  0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+  0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+  0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+  0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+  0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+uint32_t hashkit_crc32(const char *key, size_t key_length, void *context)
+{
+  uint64_t x;
+  uint32_t crc= UINT32_MAX;
+  (void)context;
+
+  for (x= 0; x < key_length; x++)
+     crc= (crc >> 8) ^ crc32tab[(crc ^ (uint64_t)key[x]) & 0xff];
+
+  return ((~crc) >> 16) & 0x7fff;
+}
diff --git a/src/libhashkit/digest.cc b/src/libhashkit/digest.cc
new file mode 100644 (file)
index 0000000..2300293
--- /dev/null
@@ -0,0 +1,93 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  HashKit library
+ *
+ *  Copyright (C) 2010-2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libhashkit/common.h>
+
+uint32_t hashkit_digest(const hashkit_st *self, const char *key, size_t key_length)
+{
+  return self->base_hash.function(key, key_length, self->base_hash.context);
+}
+
+uint32_t libhashkit_digest(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm)
+{
+  switch (hash_algorithm)
+  {
+  case HASHKIT_HASH_DEFAULT:
+    return libhashkit_one_at_a_time(key, key_length);
+  case HASHKIT_HASH_MD5:
+    return libhashkit_md5(key, key_length);
+  case HASHKIT_HASH_CRC:
+    return libhashkit_crc32(key, key_length);
+  case HASHKIT_HASH_FNV1_64:
+    return libhashkit_fnv1_64(key, key_length);
+  case HASHKIT_HASH_FNV1A_64:
+    return libhashkit_fnv1a_64(key, key_length);
+  case HASHKIT_HASH_FNV1_32:
+    return libhashkit_fnv1_32(key, key_length);
+  case HASHKIT_HASH_FNV1A_32:
+    return libhashkit_fnv1a_32(key, key_length);
+  case HASHKIT_HASH_HSIEH:
+#ifdef HAVE_HSIEH_HASH
+    return libhashkit_hsieh(key, key_length);
+#else
+    return 1;
+#endif
+  case HASHKIT_HASH_MURMUR3:
+    return libhashkit_murmur3(key, key_length);
+
+  case HASHKIT_HASH_MURMUR:
+#ifdef HAVE_MURMUR_HASH
+    return libhashkit_murmur(key, key_length);
+#else
+    return 1;
+#endif
+  case HASHKIT_HASH_JENKINS:
+    return libhashkit_jenkins(key, key_length);
+  case HASHKIT_HASH_CUSTOM:
+  case HASHKIT_HASH_MAX:
+  default:
+    if (DEBUG)
+    {
+      fprintf(stderr, "hashkit_hash_t was extended but libhashkit_generate_value was not updated\n");
+      fflush(stderr);
+      assert(0);
+    }
+    break;
+  }
+
+  return 1;
+}
diff --git a/src/libhashkit/encrypt.cc b/src/libhashkit/encrypt.cc
new file mode 100644 (file)
index 0000000..95475d7
--- /dev/null
@@ -0,0 +1,63 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libhashkit library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libhashkit/common.h>
+
+hashkit_string_st *hashkit_encrypt(hashkit_st *kit,
+                                   const char* source, size_t source_length)
+{
+  return aes_encrypt(static_cast<aes_key_t*>(kit->_key), source, source_length);
+}
+
+hashkit_string_st *hashkit_decrypt(hashkit_st *kit,
+                                   const char* source, size_t source_length)
+{
+  return aes_decrypt(static_cast<aes_key_t*>(kit->_key), source, source_length);
+}
+
+bool hashkit_key(hashkit_st *kit, const char *key, const size_t key_length)
+{
+  if (kit->_key)
+  {
+    free(kit->_key);
+  }
+
+  kit->_key= aes_create_key(key, key_length);
+  
+  return bool(kit->_key);
+}
+
diff --git a/src/libhashkit/fnv_32.cc b/src/libhashkit/fnv_32.cc
new file mode 100644 (file)
index 0000000..52eea80
--- /dev/null
@@ -0,0 +1,73 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libhashkit/common.h>
+
+/* FNV hash'es lifted from Dustin Sallings work */
+static uint32_t FNV_32_INIT= 2166136261UL;
+static uint32_t FNV_32_PRIME= 16777619;
+
+uint32_t hashkit_fnv1_32(const char *key, size_t key_length, void *context)
+{
+  uint32_t hash= FNV_32_INIT;
+  (void)context;
+
+  for (size_t x= 0; x < key_length; x++)
+  {
+    uint32_t val= (uint32_t)key[x];
+    hash *= FNV_32_PRIME;
+    hash ^= val;
+  }
+
+  return hash;
+}
+
+uint32_t hashkit_fnv1a_32(const char *key, size_t key_length, void *context)
+{
+  uint32_t hash= FNV_32_INIT;
+  (void)context;
+
+  for (size_t x= 0; x < key_length; x++)
+  {
+    uint32_t val= (uint32_t)key[x];
+    hash ^= val;
+    hash *= FNV_32_PRIME;
+  }
+
+  return hash;
+}
diff --git a/src/libhashkit/fnv_64.cc b/src/libhashkit/fnv_64.cc
new file mode 100644 (file)
index 0000000..68e4dd0
--- /dev/null
@@ -0,0 +1,85 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libhashkit/common.h>
+
+#if __WORDSIZE == 64 && defined(HAVE_FNV64_HASH)
+
+/* FNV hash'es lifted from Dustin Sallings work */
+static uint64_t FNV_64_INIT= 0xcbf29ce484222325;
+static uint64_t FNV_64_PRIME= 0x100000001b3;
+
+uint32_t hashkit_fnv1_64(const char *key, size_t key_length, void *)
+{
+  /* Thanks to pierre@demartines.com for the pointer */
+  uint64_t hash= FNV_64_INIT;
+
+  for (size_t x= 0; x < key_length; x++)
+  {
+    hash *= FNV_64_PRIME;
+    hash ^= (uint64_t)key[x];
+  }
+
+  return (uint32_t)hash;
+}
+
+uint32_t hashkit_fnv1a_64(const char *key, size_t key_length, void *)
+{
+  uint32_t hash= (uint32_t) FNV_64_INIT;
+
+  for (size_t x= 0; x < key_length; x++)
+  {
+    uint32_t val= (uint32_t)key[x];
+    hash ^= val;
+    hash *= (uint32_t) FNV_64_PRIME;
+  }
+
+  return hash;
+}
+
+#else
+uint32_t hashkit_fnv1_64(const char *, size_t, void *)
+{
+  return 0;
+}
+
+uint32_t hashkit_fnv1a_64(const char *, size_t, void *)
+{
+  return 0;
+}
+#endif
diff --git a/src/libhashkit/function.cc b/src/libhashkit/function.cc
new file mode 100644 (file)
index 0000000..3d530ae
--- /dev/null
@@ -0,0 +1,213 @@
+/* HashKit
+ * Copyright (C) 2010 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ */
+
+#include <libhashkit/common.h>
+
+static hashkit_return_t _set_function(struct hashkit_st::hashkit_function_st *self, hashkit_hash_algorithm_t hash_algorithm)
+{
+  if (self == NULL)
+  {
+    return HASHKIT_INVALID_ARGUMENT;
+  }
+
+  switch (hash_algorithm)
+  {
+  case HASHKIT_HASH_MD5:
+    self->function= hashkit_md5;
+    break;
+
+  case HASHKIT_HASH_CRC:
+    self->function= hashkit_crc32;
+    break;
+
+  case HASHKIT_HASH_FNV1_64:
+    if (libhashkit_has_algorithm(HASHKIT_HASH_FNV1_64))
+    {
+      self->function= hashkit_fnv1_64;
+      break;
+    }
+    return HASHKIT_INVALID_ARGUMENT;
+
+  case HASHKIT_HASH_FNV1A_64:
+    if (libhashkit_has_algorithm(HASHKIT_HASH_FNV1_64))
+    {
+      self->function= hashkit_fnv1a_64;
+      break;
+    }
+    return HASHKIT_INVALID_ARGUMENT;
+
+  case HASHKIT_HASH_FNV1_32:
+    self->function= hashkit_fnv1_32;
+    break;
+
+  case HASHKIT_HASH_FNV1A_32:
+    self->function= hashkit_fnv1a_32;
+    break;
+
+  case HASHKIT_HASH_HSIEH:
+    if (libhashkit_has_algorithm(HASHKIT_HASH_HSIEH))
+    {
+      self->function= hashkit_hsieh;
+      break;    
+    }
+    return HASHKIT_INVALID_ARGUMENT;
+
+  case HASHKIT_HASH_MURMUR3:
+    if (libhashkit_has_algorithm(HASHKIT_HASH_MURMUR3))
+    {
+      self->function= hashkit_murmur3;
+      break;
+    }
+    return HASHKIT_INVALID_ARGUMENT;
+  case HASHKIT_HASH_MURMUR:
+    if (libhashkit_has_algorithm(HASHKIT_HASH_MURMUR))
+    {
+      self->function= hashkit_murmur;
+      break;    
+    }
+    return HASHKIT_INVALID_ARGUMENT;
+
+  case HASHKIT_HASH_JENKINS:
+    self->function= hashkit_jenkins;
+    break;    
+
+  case HASHKIT_HASH_CUSTOM:
+    return HASHKIT_INVALID_ARGUMENT;
+
+  case HASHKIT_HASH_DEFAULT:
+    self->function= hashkit_one_at_a_time;
+    break;
+
+  case HASHKIT_HASH_MAX:
+    self->function= hashkit_one_at_a_time;
+    return HASHKIT_INVALID_HASH;
+  }
+
+  self->context= NULL;
+
+  return HASHKIT_SUCCESS;
+}
+
+hashkit_return_t hashkit_set_function(hashkit_st *self, hashkit_hash_algorithm_t hash_algorithm)
+{
+  return _set_function(&self->base_hash, hash_algorithm);
+}
+
+hashkit_return_t hashkit_set_distribution_function(hashkit_st *self, hashkit_hash_algorithm_t hash_algorithm)
+{
+  return _set_function(&self->distribution_hash, hash_algorithm);
+}
+
+static hashkit_return_t _set_custom_function(struct hashkit_st::hashkit_function_st *self, hashkit_hash_fn function, void *context)
+{
+  if (self == NULL)
+  {
+    return HASHKIT_INVALID_ARGUMENT;
+  }
+
+  if (function)
+  {
+    self->function= function;
+    self->context= context;
+
+    return HASHKIT_SUCCESS;
+  }
+
+  return HASHKIT_FAILURE;
+}
+
+hashkit_return_t hashkit_set_custom_function(hashkit_st *self, hashkit_hash_fn function, void *context)
+{
+  if (self == NULL)
+  {
+    return HASHKIT_INVALID_ARGUMENT;
+  }
+
+
+  return _set_custom_function(&self->base_hash, function, context);
+}
+
+hashkit_return_t hashkit_set_custom_distribution_function(hashkit_st *self, hashkit_hash_fn function, void *context)
+{
+  if (self == NULL)
+  {
+    return HASHKIT_INVALID_ARGUMENT;
+  }
+
+  return _set_custom_function(&self->distribution_hash, function, context);
+}
+
+static hashkit_hash_algorithm_t get_function_type(const hashkit_hash_fn function)
+{
+  if (function == hashkit_one_at_a_time)
+  {
+    return HASHKIT_HASH_DEFAULT;
+  }
+  else if (function == hashkit_md5)
+  {
+    return HASHKIT_HASH_MD5;
+  }
+  else if (function == hashkit_crc32)
+  {
+    return HASHKIT_HASH_CRC;
+  }
+  else if (function == hashkit_fnv1_64)
+  {
+    return HASHKIT_HASH_FNV1_64;
+  }
+  else if (function == hashkit_fnv1a_64)
+  {
+    return HASHKIT_HASH_FNV1A_64;
+  }
+  else if (function == hashkit_fnv1_32)
+  {
+    return HASHKIT_HASH_FNV1_32;
+  }
+  else if (function == hashkit_fnv1a_32)
+  {
+    return HASHKIT_HASH_FNV1A_32;
+  }
+  else if (function == hashkit_hsieh)
+  {
+    return HASHKIT_HASH_HSIEH;
+  }
+  else if (function == hashkit_murmur)
+  {
+    return HASHKIT_HASH_MURMUR;
+  }
+  else if (function == hashkit_murmur3)
+  {
+    return HASHKIT_HASH_MURMUR3;
+  }
+  else if (function == hashkit_jenkins)
+  {
+    return HASHKIT_HASH_JENKINS;
+  }
+
+  return HASHKIT_HASH_CUSTOM;
+}
+
+hashkit_hash_algorithm_t hashkit_get_function(const hashkit_st *self)
+{
+  if (self == NULL)
+  {
+    return HASHKIT_HASH_DEFAULT;
+  }
+
+  return get_function_type(self->base_hash.function);
+}
+
+hashkit_hash_algorithm_t hashkit_get_distribution_function(const hashkit_st *self)
+{
+  if (self == NULL)
+  {
+    return HASHKIT_HASH_DEFAULT;
+  }
+
+  return get_function_type(self->distribution_hash.function);
+}
diff --git a/src/libhashkit/has.cc b/src/libhashkit/has.cc
new file mode 100644 (file)
index 0000000..843e32e
--- /dev/null
@@ -0,0 +1,82 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libhashkit/common.h>
+
+bool libhashkit_has_algorithm(const hashkit_hash_algorithm_t algo)
+{
+  switch (algo)
+  {
+  case HASHKIT_HASH_FNV1_64:
+  case HASHKIT_HASH_FNV1A_64:
+#if __WORDSIZE == 64 && defined(HAVE_FNV64_HASH)
+    return true;
+#else
+    return false;
+#endif
+
+  case HASHKIT_HASH_HSIEH:
+#ifdef HAVE_HSIEH_HASH
+    return true;
+#else
+    return false;
+#endif
+
+  case HASHKIT_HASH_MURMUR3:
+  case HASHKIT_HASH_MURMUR:
+#ifdef HAVE_MURMUR_HASH
+    return true;
+#else
+    return false;
+#endif
+
+  case HASHKIT_HASH_FNV1_32:
+  case HASHKIT_HASH_FNV1A_32:
+  case HASHKIT_HASH_DEFAULT:
+  case HASHKIT_HASH_MD5:
+  case HASHKIT_HASH_CRC:
+  case HASHKIT_HASH_JENKINS:
+  case HASHKIT_HASH_CUSTOM:
+    return true;
+
+  case HASHKIT_HASH_MAX:
+    break;
+  }
+
+  return false;
+}
diff --git a/src/libhashkit/hashkit.cc b/src/libhashkit/hashkit.cc
new file mode 100644 (file)
index 0000000..e2528b9
--- /dev/null
@@ -0,0 +1,140 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libhashkit/common.h>
+
+static inline void _hashkit_init(hashkit_st *self)
+{
+  self->base_hash.function= hashkit_one_at_a_time;
+  self->base_hash.context= NULL;
+
+  self->distribution_hash.function= hashkit_one_at_a_time;
+  self->distribution_hash.context= NULL;
+
+  self->flags.is_base_same_distributed= true;
+  self->_key= NULL;
+}
+
+static inline hashkit_st *_hashkit_create(hashkit_st *self)
+{
+  if (self)
+  {
+    self->options.is_allocated= false;
+  }
+  else
+  {
+    self= (hashkit_st*)calloc(1, sizeof(hashkit_st));
+    if (self == NULL)
+    {
+      return NULL;
+    }
+
+    self->options.is_allocated= true;
+  }
+
+  return self;
+}
+
+hashkit_st *hashkit_create(hashkit_st *self)
+{
+  self= _hashkit_create(self);
+  if (self == NULL)
+  {
+    return NULL;
+  }
+
+  _hashkit_init(self);
+
+  return self;
+}
+
+
+void hashkit_free(hashkit_st *self)
+{
+  if (self and self->_key)
+  {
+    free(self->_key);
+    self->_key= NULL;
+  }
+
+  if (hashkit_is_allocated(self))
+  {
+    free(self);
+  }
+}
+
+hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *source)
+{
+  if (source == NULL)
+  {
+    return hashkit_create(destination);
+  }
+
+  /* new_clone will be a pointer to destination */ 
+  destination= _hashkit_create(destination);
+
+  // Should only happen on allocation failure.
+  if (destination == NULL)
+  {
+    return NULL;
+  }
+
+  destination->base_hash= source->base_hash;
+  destination->distribution_hash= source->distribution_hash;
+  destination->flags= source->flags;
+  destination->_key= aes_clone_key(static_cast<aes_key_t*>(source->_key));
+
+  return destination;
+}
+
+bool hashkit_compare(const hashkit_st *first, const hashkit_st *second)
+{
+  if (not first or not second)
+    return false;
+
+  if (first->base_hash.function == second->base_hash.function and
+      first->base_hash.context == second->base_hash.context and
+      first->distribution_hash.function == second->distribution_hash.function and
+      first->distribution_hash.context == second->distribution_hash.context and
+      first->flags.is_base_same_distributed == second->flags.is_base_same_distributed)
+  {
+    return true;
+  }
+
+  return false;
+}
diff --git a/src/libhashkit/hashkit.h b/src/libhashkit/hashkit.h
new file mode 100644 (file)
index 0000000..692d591
--- /dev/null
@@ -0,0 +1,40 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#include <libhashkit-1.0/hashkit.h>
diff --git a/src/libhashkit/hashkitcon.h.in b/src/libhashkit/hashkitcon.h.in
new file mode 100644 (file)
index 0000000..9834962
--- /dev/null
@@ -0,0 +1,40 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  HashKit library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#include "@AUTOHEADER_FILE@"
diff --git a/src/libhashkit/hsieh.cc b/src/libhashkit/hsieh.cc
new file mode 100644 (file)
index 0000000..ca88f8d
--- /dev/null
@@ -0,0 +1,113 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* By Paul Hsieh (C) 2004, 2005.  Covered under the Paul Hsieh
+ * derivative license.
+ * See: http://www.azillionmonkeys.com/qed/weblicense.html for license
+ * details.
+ * http://www.azillionmonkeys.com/qed/hash.html
+*/
+
+#include <libhashkit/common.h>
+
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__))
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
+                      +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+
+#ifdef HAVE_HSIEH_HASH
+uint32_t hashkit_hsieh(const char *key, size_t key_length, void *)
+{
+  uint32_t hash = 0, tmp;
+  int rem;
+
+  if (key_length <= 0 || key == NULL)
+    return 0;
+
+  rem = key_length & 3;
+  key_length >>= 2;
+
+  /* Main loop */
+  for (;key_length > 0; key_length--)
+  {
+    hash  += get16bits (key);
+    tmp    = (get16bits (key+2) << 11) ^ hash;
+    hash   = (hash << 16) ^ tmp;
+    key  += 2*sizeof (uint16_t);
+    hash  += hash >> 11;
+  }
+
+  /* Handle end cases */
+  switch (rem)
+  {
+  case 3: hash += get16bits (key);
+          hash ^= hash << 16;
+          hash ^= (uint32_t)key[sizeof (uint16_t)] << 18;
+          hash += hash >> 11;
+          break;
+  case 2: hash += get16bits (key);
+          hash ^= hash << 11;
+          hash += hash >> 17;
+          break;
+  case 1: hash += (unsigned char)(*key);
+          hash ^= hash << 10;
+          hash += hash >> 1;
+  default:
+          break;
+  }
+
+  /* Force "avalanching" of final 127 bits */
+  hash ^= hash << 3;
+  hash += hash >> 5;
+  hash ^= hash << 4;
+  hash += hash >> 17;
+  hash ^= hash << 25;
+  hash += hash >> 6;
+
+  return hash;
+}
+#else
+uint32_t hashkit_hsieh(const char *, size_t , void *)
+{
+  return 0;
+}
+#endif
diff --git a/src/libhashkit/is.h b/src/libhashkit/is.h
new file mode 100644 (file)
index 0000000..e8e5772
--- /dev/null
@@ -0,0 +1,43 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+#pragma once
+
+#define hashkit_is_allocated(__object) ((__object)->options.is_allocated)
+#define hashkit_is_initialized(__object) ((__object)->options.is_initialized)
+
diff --git a/src/libhashkit/jenkins.cc b/src/libhashkit/jenkins.cc
new file mode 100644 (file)
index 0000000..3c6558a
--- /dev/null
@@ -0,0 +1,268 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+*
+* By Bob Jenkins, 2006.  bob_jenkins@burtleburtle.net.  You may use this
+* code any way you wish, private, educational, or commercial.  It's free.
+* Use for hash table lookup, or anything where one collision in 2^^32 is
+* acceptable.  Do NOT use for cryptographic purposes.
+* http://burtleburtle.net/bob/hash/index.html
+*
+* Modified by Brian Pontz for libmemcached
+* TODO:
+* Add big endian support
+*/
+
+#include <libhashkit/common.h>
+
+#define hashsize(n) ((uint32_t)1<<(n))
+#define hashmask(n) (hashsize(n)-1)
+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
+
+#define mix(a,b,c) \
+{ \
+  a -= c;  a ^= rot(c, 4);  c += b; \
+  b -= a;  b ^= rot(a, 6);  a += c; \
+  c -= b;  c ^= rot(b, 8);  b += a; \
+  a -= c;  a ^= rot(c,16);  c += b; \
+  b -= a;  b ^= rot(a,19);  a += c; \
+  c -= b;  c ^= rot(b, 4);  b += a; \
+}
+
+#define final(a,b,c) \
+{ \
+  c ^= b; c -= rot(b,14); \
+  a ^= c; a -= rot(c,11); \
+  b ^= a; b -= rot(a,25); \
+  c ^= b; c -= rot(b,16); \
+  a ^= c; a -= rot(c,4);  \
+  b ^= a; b -= rot(a,14); \
+  c ^= b; c -= rot(b,24); \
+}
+
+#define JENKINS_INITVAL 13
+
+/*
+jenkins_hash() -- hash a variable-length key into a 32-bit value
+  k       : the key (the unaligned variable-length array of bytes)
+  length  : the length of the key, counting by bytes
+  initval : can be any 4-byte value
+Returns a 32-bit value.  Every bit of the key affects every bit of
+the return value.  Two keys differing by one or two bits will have
+totally different hash values.
+
+The best hash table sizes are powers of 2.  There is no need to do
+mod a prime (mod is sooo slow!).  If you need less than 32 bits,
+use a bitmask.  For example, if you need only 10 bits, do
+  h = (h & hashmask(10));
+In which case, the hash table should have hashsize(10) elements.
+*/
+
+uint32_t hashkit_jenkins(const char *key, size_t length, void *)
+{
+  uint32_t a,b,c;                                          /* internal state */
+#ifndef WORDS_BIGENDIAN
+  union { const void *ptr; size_t i; } u;
+  u.ptr = key;
+#endif
+
+  /* Set up the internal state */
+  a = b = c = 0xdeadbeef + ((uint32_t)length) + JENKINS_INITVAL;
+
+#ifndef WORDS_BIGENDIAN
+  if ((u.i & 0x3) == 0)
+  {
+    const uint32_t *k = (const uint32_t *)key;         /* read 32-bit chunks */
+
+    /*------ all but last block: aligned reads and affect 32 bits of (a,b,c) */
+    while (length > 12)
+    {
+      a += k[0];
+      b += k[1];
+      c += k[2];
+      mix(a,b,c);
+      length -= 12;
+      k += 3;
+    }
+
+    /*----------------------------- handle the last (probably partial) block */
+    /*
+     * "k[2]&0xffffff" actually reads beyond the end of the string, but
+     * then masks off the part it's not allowed to read.  Because the
+     * string is aligned, the masked-off tail is in the same word as the
+     * rest of the string.  Every machine with memory protection I've seen
+     * does it on word boundaries, so is OK with this.  But VALGRIND will
+     * still catch it and complain.  The masking trick does make the hash
+     * noticably faster for short strings (like English words).
+     */
+    switch(length)
+    {
+    case 12: c+=k[2]; b+=k[1]; a+=k[0]; break;
+    case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break;
+    case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break;
+    case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break;
+    case 8 : b+=k[1]; a+=k[0]; break;
+    case 7 : b+=k[1]&0xffffff; a+=k[0]; break;
+    case 6 : b+=k[1]&0xffff; a+=k[0]; break;
+    case 5 : b+=k[1]&0xff; a+=k[0]; break;
+    case 4 : a+=k[0]; break;
+    case 3 : a+=k[0]&0xffffff; break;
+    case 2 : a+=k[0]&0xffff; break;
+    case 1 : a+=k[0]&0xff; break;
+    case 0 : return c;              /* zero length strings require no mixing */
+    default: return c;
+    }
+
+  }
+  else if ((u.i & 0x1) == 0)
+  {
+    const uint16_t *k = (const uint16_t *)key;         /* read 16-bit chunks */
+    const uint8_t  *k8;
+
+    /*--------------- all but last block: aligned reads and different mixing */
+    while (length > 12)
+    {
+      a += k[0] + (((uint32_t)k[1])<<16);
+      b += k[2] + (((uint32_t)k[3])<<16);
+      c += k[4] + (((uint32_t)k[5])<<16);
+      mix(a,b,c);
+      length -= 12;
+      k += 6;
+    }
+
+    /*----------------------------- handle the last (probably partial) block */
+    k8 = (const uint8_t *)k;
+    switch(length)
+    {
+    case 12: c+=k[4]+(((uint32_t)k[5])<<16);
+             b+=k[2]+(((uint32_t)k[3])<<16);
+             a+=k[0]+(((uint32_t)k[1])<<16);
+             break;
+    case 11: c+=((uint32_t)k8[10])<<16;
+             /* fall through */
+    case 10: c+=k[4];
+             b+=k[2]+(((uint32_t)k[3])<<16);
+             a+=k[0]+(((uint32_t)k[1])<<16);
+             break;
+    case 9 : c+=k8[8];
+             /* fall through */
+    case 8 : b+=k[2]+(((uint32_t)k[3])<<16);
+             a+=k[0]+(((uint32_t)k[1])<<16);
+             break;
+    case 7 : b+=((uint32_t)k8[6])<<16;
+             /* fall through */
+    case 6 : b+=k[2];
+             a+=k[0]+(((uint32_t)k[1])<<16);
+             break;
+    case 5 : b+=k8[4];
+             /* fall through */
+    case 4 : a+=k[0]+(((uint32_t)k[1])<<16);
+             break;
+    case 3 : a+=((uint32_t)k8[2])<<16;
+             /* fall through */
+    case 2 : a+=k[0];
+             break;
+    case 1 : a+=k8[0];
+             break;
+    case 0 : return c;                     /* zero length requires no mixing */
+    default: return c;
+    }
+
+  }
+  else
+  {                        /* need to read the key one byte at a time */
+#endif /* little endian */
+    const uint8_t *k = (const uint8_t *)key;
+
+    /*--------------- all but the last block: affect some 32 bits of (a,b,c) */
+    while (length > 12)
+    {
+      a += k[0];
+      a += ((uint32_t)k[1])<<8;
+      a += ((uint32_t)k[2])<<16;
+      a += ((uint32_t)k[3])<<24;
+      b += k[4];
+      b += ((uint32_t)k[5])<<8;
+      b += ((uint32_t)k[6])<<16;
+      b += ((uint32_t)k[7])<<24;
+      c += k[8];
+      c += ((uint32_t)k[9])<<8;
+      c += ((uint32_t)k[10])<<16;
+      c += ((uint32_t)k[11])<<24;
+      mix(a,b,c);
+      length -= 12;
+      k += 12;
+    }
+
+    /*-------------------------------- last block: affect all 32 bits of (c) */
+    switch(length)                   /* all the case statements fall through */
+    {
+    case 12: c+=((uint32_t)k[11])<<24;
+             /* fall through */
+    case 11: c+=((uint32_t)k[10])<<16;
+             /* fall through */
+    case 10: c+=((uint32_t)k[9])<<8;
+             /* fall through */
+    case 9 : c+=k[8];
+             /* fall through */
+    case 8 : b+=((uint32_t)k[7])<<24;
+             /* fall through */
+    case 7 : b+=((uint32_t)k[6])<<16;
+             /* fall through */
+    case 6 : b+=((uint32_t)k[5])<<8;
+             /* fall through */
+    case 5 : b+=k[4];
+             /* fall through */
+    case 4 : a+=((uint32_t)k[3])<<24;
+             /* fall through */
+    case 3 : a+=((uint32_t)k[2])<<16;
+             /* fall through */
+    case 2 : a+=((uint32_t)k[1])<<8;
+             /* fall through */
+    case 1 : a+=k[0];
+             break;
+    case 0 : return c;
+    default : return c;
+    }
+#ifndef WORDS_BIGENDIAN
+  }
+#endif
+
+  final(a,b,c);
+  return c;
+}
diff --git a/src/libhashkit/ketama.cc b/src/libhashkit/ketama.cc
new file mode 100644 (file)
index 0000000..eaa8442
--- /dev/null
@@ -0,0 +1,194 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libhashkit/common.h>
+#include <math.h>
+
+#if 0
+static uint32_t ketama_server_hash(const char *key, unsigned int key_length, int alignment)
+{
+  unsigned char results[16];
+
+  md5_signature((unsigned char*)key, key_length, results);
+  return ((uint32_t) (results[3 + alignment * 4] & 0xFF) << 24)
+    | ((uint32_t) (results[2 + alignment * 4] & 0xFF) << 16)
+    | ((uint32_t) (results[1 + alignment * 4] & 0xFF) << 8)
+    | (results[0 + alignment * 4] & 0xFF);
+}
+
+static int continuum_points_cmp(const void *t1, const void *t2)
+{
+  hashkit_continuum_point_st *ct1= (hashkit_continuum_point_st *)t1;
+  hashkit_continuum_point_st *ct2= (hashkit_continuum_point_st *)t2;
+
+  if (ct1->value == ct2->value)
+    return 0;
+  else if (ct1->value > ct2->value)
+    return 1;
+  else
+    return -1;
+}
+
+int update_continuum(hashkit_st *hashkit)
+{
+  uint32_t count;
+  uint32_t continuum_index= 0;
+  uint32_t value;
+  uint32_t points_index;
+  uint32_t points_count= 0;
+  uint32_t points_per_server;
+  uint32_t points_per_hash;
+  uint64_t total_weight= 0;
+  uint32_t live_servers;
+  uint8_t *context;
+
+  if (hashkit->active_fn != NULL || hashkit->weight_fn != NULL)
+  {
+    live_servers= 0;
+
+    for (count= 0, context= hashkit->list; count < hashkit->list_size;
+         count++, context+= hashkit->context_size)
+    {
+      if (hashkit->active_fn != NULL)
+      {
+        if (hashkit->active_fn(context))
+          live_servers++;
+        else
+          continue;
+      }
+
+      if (hashkit->weight_fn != NULL)
+        total_weight+= hashkit->weight_fn(context);
+    }
+  }
+
+  if (hashkit->active_fn == NULL)
+    live_servers= (uint32_t)hashkit->list_size;
+
+  if (live_servers == 0)
+    return 0;
+
+  if (hashkit->weight_fn == NULL)
+  {
+    points_per_server= HASHKIT_POINTS_PER_NODE;
+    points_per_hash= 1;
+  }
+  else
+  {
+    points_per_server= HASHKIT_POINTS_PER_NODE_WEIGHTED;
+    points_per_hash= 4;
+  }
+
+  if (live_servers > hashkit->continuum_count)
+  {
+    hashkit_continuum_point_st *new_continuum;
+
+    new_continuum= realloc(hashkit->continuum,
+                           sizeof(hashkit_continuum_point_st) *
+                           (live_servers + HASHKIT_CONTINUUM_ADDITION) *
+                           points_per_server);
+
+    if (new_continuum == NULL)
+      return ENOMEM;
+
+    hashkit->continuum= new_continuum;
+    hashkit->continuum_count= live_servers + HASHKIT_CONTINUUM_ADDITION;
+  }
+
+  for (count= 0, context= hashkit->list; count < hashkit->list_size;
+       count++, context+= hashkit->context_size)
+  {
+    if (hashkit->active_fn != NULL && hashkit->active_fn(context) == false)
+      continue;
+
+    if (hashkit->weight_fn != NULL)
+    {
+        float pct = (float)hashkit->weight_fn(context) / (float)total_weight;
+        points_per_server= (uint32_t) ((floorf((float) (pct * HASHKIT_POINTS_PER_NODE_WEIGHTED / 4 * (float)live_servers + 0.0000000001))) * 4);
+    }
+
+    for (points_index= 0;
+         points_index < points_per_server / points_per_hash;
+         points_index++)
+    {
+      char sort_host[HASHKIT_CONTINUUM_KEY_SIZE]= "";
+      size_t sort_host_length;
+
+      if (hashkit->continuum_key_fn == NULL)
+      {
+        sort_host_length= (size_t) snprintf(sort_host, HASHKIT_CONTINUUM_KEY_SIZE, "%u",
+                                            points_index);
+      }
+      else
+      {
+        sort_host_length= hashkit->continuum_key_fn(sort_host, HASHKIT_CONTINUUM_KEY_SIZE,
+                                                 points_index, context);
+      }
+
+      if (hashkit->weight_fn == NULL)
+      {
+        if (hashkit->continuum_hash_fn == NULL)
+          value= hashkit_default(sort_host, sort_host_length);
+        else
+          value= hashkit->continuum_hash_fn(sort_host, sort_host_length);
+
+        hashkit->continuum[continuum_index].index= count;
+        hashkit->continuum[continuum_index++].value= value;
+      }
+      else
+      {
+        unsigned int i;
+        for (i = 0; i < points_per_hash; i++)
+        {
+           value= ketama_server_hash(sort_host, (uint32_t) sort_host_length, (int) i);
+           hashkit->continuum[continuum_index].index= count;
+           hashkit->continuum[continuum_index++].value= value;
+        }
+      }
+    }
+
+    points_count+= points_per_server;
+  }
+
+  hashkit->continuum_points_count= points_count;
+  qsort(hashkit->continuum, hashkit->continuum_points_count, sizeof(hashkit_continuum_point_st),
+        continuum_points_cmp);
+
+  return 0;
+}
+#endif
diff --git a/src/libhashkit/md5.cc b/src/libhashkit/md5.cc
new file mode 100644 (file)
index 0000000..ef86776
--- /dev/null
@@ -0,0 +1,412 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+  This Library has been modified from its original form by
+  Brian Aker (brian@tangent.org)
+
+  See below for original Copyright.
+*/
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+rights reserved.
+
+License to copy and use this software is granted provided that it
+is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+Algorithm" in all material mentioning or referencing this software
+or this function.
+
+License is also granted to make and use derivative works provided
+that such works are identified as "derived from the RSA Data
+Security, Inc. MD5 Message-Digest Algorithm" in all material
+mentioning or referencing the derived work.
+
+RSA Data Security, Inc. makes no representations concerning either
+the merchantability of this software or the suitability of this
+software for any particular purpose. It is provided "as is"
+without express or implied warranty of any kind.
+
+These notices must be retained in any copies of any part of this
+documentation and/or software.
+*/
+
+#include <libhashkit/common.h>
+
+#include <string.h>
+#include <sys/types.h>
+
+#define GCC_VERSION (__GNUC__ * 10000 \
+                     + __GNUC_MINOR__ * 100 \
+                     + __GNUC_PATCHLEVEL__)
+
+#if GCC_VERSION > 40600
+# pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"
+#endif
+
+/* POINTER defines a generic pointer type */
+typedef unsigned char *POINTER;
+typedef const unsigned char *CONST_POINTER;
+
+
+/* UINT4 defines a four byte word */
+typedef unsigned int UINT4;
+
+
+/* MD5 context. */
+typedef struct {
+  UINT4 state[4];                                   /* state (ABCD) */
+  UINT4 count[2];        /* number of bits, modulo 2^64 (lsb first) */
+  unsigned char buffer[64];                         /* input buffer */
+} MD5_CTX;
+
+static void MD5Init (MD5_CTX *context);      /* context */
+static void MD5Update ( MD5_CTX *context,                                        /* context */
+                        const unsigned char *input,                              /* input block */
+                        unsigned int inputLen);                     /* length of input block */
+static void MD5Final ( unsigned char digest[16],                         /* message digest */
+                       MD5_CTX *context);                              /* context */
+
+/* Constants for MD5Transform routine. */
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+
+static void MD5Transform (UINT4 state[4],
+                          const unsigned char block[64]);
+static void Encode (unsigned char *output,
+                    UINT4 *input,
+                    unsigned int len);
+static void Decode(UINT4 *output, const unsigned char *input, unsigned int len);
+
+static unsigned char PADDING[64] = {
+  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+  }
+
+
+/*
+  Just a simple method for getting the signature
+  result must be == 16
+*/
+void md5_signature(const unsigned char *key, unsigned int length, unsigned char *result)
+{
+    MD5_CTX my_md5;
+
+    MD5Init(&my_md5);
+    (void)MD5Update(&my_md5, key, length);
+    MD5Final(result, &my_md5);
+}
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+static void MD5Init (MD5_CTX *context)      /* context */
+{
+  context->count[0] = context->count[1] = 0;
+  /* Load magic initialization constants.
+*/
+  context->state[0] = 0x67452301;
+  context->state[1] = 0xefcdab89;
+  context->state[2] = 0x98badcfe;
+  context->state[3] = 0x10325476;
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+  operation, processing another message block, and updating the
+  context.
+ */
+
+static void MD5Update (
+                       MD5_CTX *context,                                        /* context */
+                       const unsigned char *input,                              /* input block */
+                       unsigned int inputLen)                     /* length of input block */
+{
+  unsigned int i, idx, partLen;
+
+  /* Compute number of bytes mod 64 */
+  idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+
+  /* Update number of bits */
+  if ((context->count[0] += ((UINT4)inputLen << 3))
+      < ((UINT4)inputLen << 3))
+    context->count[1]++;
+  context->count[1] += ((UINT4)inputLen >> 29);
+
+  partLen = 64 - idx;
+
+  /* Transform as many times as possible.
+*/
+  if (inputLen >= partLen) {
+    memcpy((POINTER)&context->buffer[idx], (CONST_POINTER)input, partLen);
+    MD5Transform(context->state, context->buffer);
+
+    for (i = partLen; i + 63 < inputLen; i += 64)
+      MD5Transform (context->state, (CONST_POINTER)&input[i]);
+
+    idx = 0;
+  }
+  else
+    i = 0;
+
+  /* Buffer remaining input */
+  memcpy((POINTER)&context->buffer[idx], (CONST_POINTER)&input[i],
+         inputLen-i);
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+  the message digest and zeroizing the context.
+ */
+
+static void MD5Final (
+                      unsigned char digest[16],                         /* message digest */
+                      MD5_CTX *context)                              /* context */
+{
+  unsigned char bits[8];
+  unsigned int idx, padLen;
+
+  /* Save number of bits */
+  Encode (bits, context->count, 8);
+
+  /* Pad out to 56 mod 64.
+*/
+  idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
+  padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+  MD5Update (context, PADDING, padLen);
+
+  /* Append length (before padding) */
+  MD5Update (context, bits, 8);
+
+  /* Store state in digest */
+  Encode (digest, context->state, 16);
+
+  /* Zeroize sensitive information.
+*/
+  memset((POINTER)context, 0, sizeof (*context));
+}
+
+/* MD5 basic transformation. Transforms state based on block.
+ */
+static void MD5Transform (
+                          UINT4 state[4],
+                          const unsigned char block[64])
+{
+  UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
+
+  Decode (x, block, 64);
+
+  /* Round 1 */
+  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
+  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
+  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
+  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
+  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
+  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
+  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
+  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
+  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
+  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
+  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
+  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
+  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
+  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
+  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
+  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
+  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
+  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
+  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
+  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
+  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
+  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+  /* Round 3 */
+  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
+  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
+  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
+  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
+  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
+  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
+  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
+  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
+  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
+  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
+
+  /* Round 4 */
+  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
+  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
+  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
+  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
+  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
+  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
+  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
+  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
+  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
+  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
+
+
+  state[0] += a;
+  state[1] += b;
+  state[2] += c;
+  state[3] += d;
+
+  /* Zeroize sensitive information.
+*/
+  memset((POINTER)x, 0, sizeof (x));
+}
+
+/* Encodes input (UINT4) into output (unsigned char). Assumes len is
+  a multiple of 4.
+ */
+static void Encode (
+unsigned char *output,
+UINT4 *input,
+unsigned int len)
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4) {
+ output[j] = (unsigned char)(input[i] & 0xff);
+ output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
+ output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
+ output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
+  }
+}
+
+
+/* Decodes input (unsigned char) into output (UINT4). Assumes len is
+  a multiple of 4.
+ */
+static void Decode (
+                    UINT4 *output,
+                    const unsigned char *input,
+                    unsigned int len)
+{
+  unsigned int i, j;
+
+  for (i = 0, j = 0; j < len; i++, j += 4)
+    output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
+      (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
+}
+
+uint32_t hashkit_md5(const char *key, size_t key_length, void *context)
+{
+  unsigned char results[16];
+  (void)context;
+
+  md5_signature((unsigned char*)key, (unsigned int)key_length, results);
+
+  return ((uint32_t) (results[3] & 0xFF) << 24)
+    | ((uint32_t) (results[2] & 0xFF) << 16)
+    | ((uint32_t) (results[1] & 0xFF) << 8)
+    | (results[0] & 0xFF);
+}
diff --git a/src/libhashkit/murmur.cc b/src/libhashkit/murmur.cc
new file mode 100644 (file)
index 0000000..f3e8fe6
--- /dev/null
@@ -0,0 +1,126 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+  "Murmur" hash provided by Austin, tanjent@gmail.com
+  http://murmurhash.googlepages.com/
+
+  Note - This code makes a few assumptions about how your machine behaves -
+
+  1. We can read a 4-byte value from any address without crashing
+  2. sizeof(int) == 4
+
+  And it has a few limitations -
+  1. It will not work incrementally.
+  2. It will not produce the same results on little-endian and big-endian
+  machines.
+
+  Updated to murmur2 hash - BP
+*/
+
+#include <libhashkit/common.h>
+
+#ifdef HAVE_MURMUR_HASH
+
+#include <cstring>
+
+uint32_t hashkit_murmur(const char *key, size_t length, void *context)
+{
+  /*
+    'm' and 'r' are mixing constants generated offline.  They're not
+    really 'magic', they just happen to work well.
+  */
+
+  const unsigned int m= 0x5bd1e995;
+  const uint32_t seed= (0xdeadbeef * (uint32_t)length);
+  const int r= 24;
+
+
+  // Initialize the hash to a 'random' value
+
+  uint32_t h= seed ^ (uint32_t)length;
+
+  // Mix 4 bytes at a time into the hash
+
+  const unsigned char * data= (const unsigned char *)key;
+  (void)context;
+
+  while(length >= 4)
+  {
+    unsigned int k;
+    memcpy(&k, data, sizeof(unsigned int));
+
+    k *= m;
+    k ^= k >> r;
+    k *= m;
+
+    h *= m;
+    h ^= k;
+
+    data += 4;
+    length -= 4;
+  }
+
+  // Handle the last few bytes of the input array
+
+  switch(length)
+  {
+  case 3: h ^= ((uint32_t)data[2]) << 16;   /* fall through */
+  case 2: h ^= ((uint32_t)data[1]) << 8;    /* fall through */
+  case 1: h ^= data[0];
+          h *= m;
+  default: break;
+  };
+
+  /*
+    Do a few final mixes of the hash to ensure the last few bytes are
+    well-incorporated.
+  */
+
+  h ^= h >> 13;
+  h *= m;
+  h ^= h >> 15;
+
+  return h;
+}
+
+#else
+uint32_t hashkit_murmur(const char *, size_t , void *)
+{
+  return 0;
+}
+#endif
diff --git a/src/libhashkit/murmur3.cc b/src/libhashkit/murmur3.cc
new file mode 100644 (file)
index 0000000..254b509
--- /dev/null
@@ -0,0 +1,349 @@
+//-----------------------------------------------------------------------------
+//MurmurHash3 was written by Austin Appleby, and is placed in the public
+//domain. The author hereby disclaims copyright to this source code.
+
+// Note - The x86 and x64 versions do _not_ produce the same results, as the
+// algorithms are optimized for their respective platforms. You can still
+// compile and run any of them on any platform, but your performance with the
+// non-native version will be less than optimal.
+
+#include "libhashkit/hashkitcon.h"
+
+#include "libhashkit/murmur3.h"
+
+//-----------------------------------------------------------------------------
+// Platform-specific functions and macros
+
+#ifdef __GNUC__
+#define FORCE_INLINE __attribute__((always_inline)) inline
+#else
+#define FORCE_INLINE inline
+#endif
+
+static FORCE_INLINE uint32_t rotl32 ( uint32_t x, int8_t r )
+{
+  return (x << r) | (x >> (32 - r));
+}
+
+static FORCE_INLINE uint64_t rotl64 ( uint64_t x, int8_t r )
+{
+  return (x << r) | (x >> (64 - r));
+}
+
+#define        ROTL32(x,y)     rotl32(x,y)
+#define ROTL64(x,y)    rotl64(x,y)
+
+#define BIG_CONSTANT(x) (x##LLU)
+
+//-----------------------------------------------------------------------------
+// Block read - if your platform needs to do endian-swapping or can only
+// handle aligned reads, do the conversion here
+
+#include <cstring>
+template <typename T>
+static inline T getblock(const T *blocks, int i) {
+  T b;
+  memcpy(&b, ((const uint8_t *) blocks) + i * sizeof(T), sizeof(T));
+  return b;
+}
+
+//-----------------------------------------------------------------------------
+// Finalization mix - force all bits of a hash block to avalanche
+
+static FORCE_INLINE uint32_t fmix32 ( uint32_t h )
+{
+  h ^= h >> 16;
+  h *= 0x85ebca6b;
+  h ^= h >> 13;
+  h *= 0xc2b2ae35;
+  h ^= h >> 16;
+
+  return h;
+}
+
+//----------
+
+static FORCE_INLINE uint64_t fmix64 ( uint64_t k )
+{
+  k ^= k >> 33;
+  k *= BIG_CONSTANT(0xff51afd7ed558ccd);
+  k ^= k >> 33;
+  k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
+  k ^= k >> 33;
+
+  return k;
+}
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x86_32 ( const void * key, int len,
+                          uint32_t seed, void * out )
+{
+  const uint8_t * data = (const uint8_t*)key;
+  const int nblocks = len / 4;
+  int i;
+
+  uint32_t h1 = seed;
+
+  uint32_t c1 = 0xcc9e2d51;
+  uint32_t c2 = 0x1b873593;
+
+  //----------
+  // body
+
+  const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
+
+  for(i = -nblocks; i; i++)
+  {
+    uint32_t k1 = getblock(blocks,i);
+
+    k1 *= c1;
+    k1 = ROTL32(k1,15);
+    k1 *= c2;
+    
+    h1 ^= k1;
+    h1 = ROTL32(h1,13); 
+    h1 = h1*5+0xe6546b64;
+  }
+
+  //----------
+  // tail
+
+  const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
+
+  uint32_t k1 = 0;
+
+  switch(len & 3)
+  {
+  case 3: k1 ^= tail[2] << 16;
+          /* fall through */
+  case 2: k1 ^= tail[1] << 8;
+          /* fall through */
+  case 1: k1 ^= tail[0];
+          k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
+  };
+
+  //----------
+  // finalization
+
+  h1 ^= len;
+
+  h1 = fmix32(h1);
+
+  *(uint32_t*)out = h1;
+} 
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x86_128 ( const void * key, const int len,
+                           uint32_t seed, void * out )
+{
+  const uint8_t * data = (const uint8_t*)key;
+  const int nblocks = len / 16;
+  int i;
+
+  uint32_t h1 = seed;
+  uint32_t h2 = seed;
+  uint32_t h3 = seed;
+  uint32_t h4 = seed;
+
+  uint32_t c1 = 0x239b961b; 
+  uint32_t c2 = 0xab0e9789;
+  uint32_t c3 = 0x38b34ae5; 
+  uint32_t c4 = 0xa1e38b93;
+
+  //----------
+  // body
+
+  const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
+
+  for(i = -nblocks; i; i++)
+  {
+    uint32_t k1 = getblock(blocks,i*4+0);
+    uint32_t k2 = getblock(blocks,i*4+1);
+    uint32_t k3 = getblock(blocks,i*4+2);
+    uint32_t k4 = getblock(blocks,i*4+3);
+
+    k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
+
+    h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
+
+    k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
+
+    h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
+
+    k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
+
+    h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
+
+    k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
+
+    h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
+  }
+
+  //----------
+  // tail
+
+  const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
+
+  uint32_t k1 = 0;
+  uint32_t k2 = 0;
+  uint32_t k3 = 0;
+  uint32_t k4 = 0;
+
+  switch(len & 15)
+  {
+  case 15: k4 ^= tail[14] << 16;
+           /* fall through */
+  case 14: k4 ^= tail[13] << 8;
+           /* fall through */
+  case 13: k4 ^= tail[12] << 0;
+           k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
+           /* fall through */
+  case 12: k3 ^= tail[11] << 24;
+           /* fall through */
+  case 11: k3 ^= tail[10] << 16;
+           /* fall through */
+  case 10: k3 ^= tail[ 9] << 8;
+           /* fall through */
+  case  9: k3 ^= tail[ 8] << 0;
+           k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
+           /* fall through */
+  case  8: k2 ^= tail[ 7] << 24;
+           /* fall through */
+  case  7: k2 ^= tail[ 6] << 16;
+           /* fall through */
+  case  6: k2 ^= tail[ 5] << 8;
+           /* fall through */
+  case  5: k2 ^= tail[ 4] << 0;
+           k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
+           /* fall through */
+  case  4: k1 ^= tail[ 3] << 24;
+           /* fall through */
+  case  3: k1 ^= tail[ 2] << 16;
+           /* fall through */
+  case  2: k1 ^= tail[ 1] << 8;
+           /* fall through */
+  case  1: k1 ^= tail[ 0] << 0;
+           k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
+  };
+
+  //----------
+  // finalization
+
+  h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
+
+  h1 += h2; h1 += h3; h1 += h4;
+  h2 += h1; h3 += h1; h4 += h1;
+
+  h1 = fmix32(h1);
+  h2 = fmix32(h2);
+  h3 = fmix32(h3);
+  h4 = fmix32(h4);
+
+  h1 += h2; h1 += h3; h1 += h4;
+  h2 += h1; h3 += h1; h4 += h1;
+
+  ((uint32_t*)out)[0] = h1;
+  ((uint32_t*)out)[1] = h2;
+  ((uint32_t*)out)[2] = h3;
+  ((uint32_t*)out)[3] = h4;
+}
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x64_128 ( const void * key, const int len,
+                           const uint32_t seed, void * out )
+{
+  const uint8_t * data = (const uint8_t*)key;
+  const int nblocks = len / 16;
+  int i;
+
+  uint64_t h1 = seed;
+  uint64_t h2 = seed;
+
+  uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
+  uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
+
+  //----------
+  // body
+
+  const uint64_t * blocks = (const uint64_t *)(data);
+
+  for(i = 0; i < nblocks; i++)
+  {
+    uint64_t k1 = getblock(blocks,i*2+0);
+    uint64_t k2 = getblock(blocks,i*2+1);
+
+    k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
+
+    h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
+
+    k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
+
+    h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
+  }
+
+  //----------
+  // tail
+
+  const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
+
+  uint64_t k1 = 0;
+  uint64_t k2 = 0;
+
+  switch(len & 15)
+  {
+  case 15: k2 ^= (uint64_t)(tail[14]) << 48;
+           /* fall through */
+  case 14: k2 ^= (uint64_t)(tail[13]) << 40;
+           /* fall through */
+  case 13: k2 ^= (uint64_t)(tail[12]) << 32;
+           /* fall through */
+  case 12: k2 ^= (uint64_t)(tail[11]) << 24;
+           /* fall through */
+  case 11: k2 ^= (uint64_t)(tail[10]) << 16;
+           /* fall through */
+  case 10: k2 ^= (uint64_t)(tail[ 9]) << 8;
+           /* fall through */
+  case  9: k2 ^= (uint64_t)(tail[ 8]) << 0;
+           k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
+           /* fall through */
+  case  8: k1 ^= (uint64_t)(tail[ 7]) << 56;
+           /* fall through */
+  case  7: k1 ^= (uint64_t)(tail[ 6]) << 48;
+           /* fall through */
+  case  6: k1 ^= (uint64_t)(tail[ 5]) << 40;
+           /* fall through */
+  case  5: k1 ^= (uint64_t)(tail[ 4]) << 32;
+           /* fall through */
+  case  4: k1 ^= (uint64_t)(tail[ 3]) << 24;
+           /* fall through */
+  case  3: k1 ^= (uint64_t)(tail[ 2]) << 16;
+           /* fall through */
+  case  2: k1 ^= (uint64_t)(tail[ 1]) << 8;
+           /* fall through */
+  case  1: k1 ^= (uint64_t)(tail[ 0]) << 0;
+           k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
+  };
+
+  //----------
+  // finalization
+
+  h1 ^= len; h2 ^= len;
+
+  h1 += h2;
+  h2 += h1;
+
+  h1 = fmix64(h1);
+  h2 = fmix64(h2);
+
+  h1 += h2;
+  h2 += h1;
+
+  ((uint64_t*)out)[0] = h1;
+  ((uint64_t*)out)[1] = h2;
+}
+
+//-----------------------------------------------------------------------------
+
diff --git a/src/libhashkit/murmur3.h b/src/libhashkit/murmur3.h
new file mode 100644 (file)
index 0000000..4eb4fa6
--- /dev/null
@@ -0,0 +1,16 @@
+//-----------------------------------------------------------------------------
+// MurmurHash3 was written by Austin Appleby, and is placed in the
+// public domain. The author hereby disclaims copyright to this source
+// code.
+
+#pragma once
+
+//-----------------------------------------------------------------------------
+
+void MurmurHash3_x86_32 (const void *key, int len, uint32_t seed, void *out);
+
+void MurmurHash3_x86_128(const void *key, int len, uint32_t seed, void *out);
+
+void MurmurHash3_x64_128(const void *key, int len, uint32_t seed, void *out);
+
+//-----------------------------------------------------------------------------
diff --git a/src/libhashkit/murmur3_api.cc b/src/libhashkit/murmur3_api.cc
new file mode 100644 (file)
index 0000000..db35700
--- /dev/null
@@ -0,0 +1,49 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libhashkit/common.h"
+#include "libhashkit/murmur3.h"
+
+uint32_t hashkit_murmur3(const char *key, size_t length, void *)
+{
+  const uint32_t seed= (0xdeadbeef * (uint32_t)length);
+
+  uint32_t ret;
+  MurmurHash3_x86_32(key, int(length), seed, &ret);
+
+  return ret;
+}
diff --git a/src/libhashkit/nohsieh.cc b/src/libhashkit/nohsieh.cc
new file mode 100644 (file)
index 0000000..8def993
--- /dev/null
@@ -0,0 +1,46 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  HashKit library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libhashkit/common.h>
+
+#ifdef HAVE_HSIEH_HASH
+#error "not supported"
+#else
+uint32_t hashkit_hsieh(const char *, size_t , void *)
+{
+  return 0;
+}
+#endif
diff --git a/src/libhashkit/one_at_a_time.cc b/src/libhashkit/one_at_a_time.cc
new file mode 100644 (file)
index 0000000..647f3c1
--- /dev/null
@@ -0,0 +1,64 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+/*
+  This has is Jenkin's "One at A time Hash".
+http://en.wikipedia.org/wiki/Jenkins_hash_function
+*/
+
+#include <libhashkit/common.h>
+
+uint32_t hashkit_one_at_a_time(const char *key, size_t key_length, void *context)
+{
+  const char *ptr= key;
+  uint32_t value= 0;
+  (void)context;
+
+  while (key_length--)
+  {
+    uint32_t val= (uint32_t) *ptr++;
+    value += val;
+    value += (value << 10);
+    value ^= (value >> 6);
+  }
+  value += (value << 3);
+  value ^= (value >> 11);
+  value += (value << 15);
+
+  return value;
+}
diff --git a/src/libhashkit/rijndael.cc b/src/libhashkit/rijndael.cc
new file mode 100644 (file)
index 0000000..93997cc
--- /dev/null
@@ -0,0 +1,1437 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+/**
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <assert.h>
+#include <stdlib.h>
+
+#include "libhashkit/rijndael.hpp"
+
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+static const u32 Te0[256] = {
+    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+static const u32 Te1[256] = {
+    0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+    0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+    0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+    0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+    0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+    0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+    0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+    0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+    0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+    0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+    0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+    0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+    0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+    0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+    0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+    0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+    0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+    0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+    0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+    0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+    0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+    0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+    0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+    0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+    0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+    0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+    0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+    0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+    0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+    0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+    0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+    0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+    0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+    0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+    0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+    0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+    0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+    0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+    0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+    0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+    0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+    0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+    0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+    0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+    0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+    0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+    0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+    0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+    0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+    0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+    0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+    0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+    0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+    0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+    0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+    0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+    0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+    0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+    0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+    0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+    0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+    0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+    0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+    0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+static const u32 Te2[256] = {
+    0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+    0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+    0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+    0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+    0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+    0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+    0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+    0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+    0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+    0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+    0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+    0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+    0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+    0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+    0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+    0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+    0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+    0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+    0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+    0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+    0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+    0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+    0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+    0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+    0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+    0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+    0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+    0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+    0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+    0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+    0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+    0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+    0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+    0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+    0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+    0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+    0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+    0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+    0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+    0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+    0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+    0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+    0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+    0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+    0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+    0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+    0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+    0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+    0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+    0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+    0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+    0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+    0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+    0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+    0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+    0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+    0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+    0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+    0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+    0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+    0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+    0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+    0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+    0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+static const u32 Te3[256] = {
+
+    0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+    0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+    0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+    0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+    0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+    0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+    0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+    0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+    0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+    0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+    0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+    0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+    0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+    0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+    0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+    0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+    0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+    0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+    0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+    0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+    0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+    0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+    0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+    0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+    0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+    0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+    0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+    0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+    0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+    0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+    0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+    0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+    0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+    0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+    0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+    0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+    0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+    0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+    0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+    0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+    0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+    0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+    0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+    0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+    0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+    0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+    0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+    0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+    0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+    0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+    0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+    0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+    0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+    0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+    0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+    0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+    0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+    0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+    0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+    0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+    0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+    0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+    0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+    0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+static const u32 Te4[256] = {
+    0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+    0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+    0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+    0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+    0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+    0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+    0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+    0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+    0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+    0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+    0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+    0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+    0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+    0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+    0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+    0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+    0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+    0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+    0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+    0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+    0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+    0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+    0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+    0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+    0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+    0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+    0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+    0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+    0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+    0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+    0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
+    0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
+    0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
+    0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
+    0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
+    0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
+    0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
+    0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
+    0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
+    0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
+    0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
+    0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
+    0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
+    0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
+    0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
+    0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
+    0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
+    0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
+    0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
+    0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
+    0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
+    0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
+    0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
+    0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
+    0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
+    0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
+    0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
+    0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
+    0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
+    0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
+    0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
+    0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
+    0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
+    0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
+};
+static const u32 Td0[256] = {
+    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+static const u32 Td1[256] = {
+    0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+    0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+    0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+    0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+    0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+    0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+    0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+    0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+    0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+    0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+    0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+    0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+    0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+    0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+    0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+    0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+    0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+    0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+    0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+    0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+    0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+    0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+    0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+    0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+    0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+    0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+    0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+    0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+    0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+    0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+    0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+    0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+    0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+    0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+    0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+    0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+    0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+    0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+    0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+    0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+    0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+    0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+    0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+    0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+    0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+    0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+    0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+    0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+    0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+    0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+    0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+    0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+    0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+    0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+    0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+    0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+    0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+    0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+    0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+    0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+    0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+    0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+    0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+    0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+static const u32 Td2[256] = {
+    0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+    0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+    0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+    0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+    0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+    0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+    0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+    0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+    0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+    0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+    0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+    0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+    0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+    0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+    0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+    0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+    0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+    0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+    0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+    0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+
+    0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+    0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+    0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+    0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+    0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+    0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+    0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+    0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+    0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+    0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+    0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+    0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+    0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+    0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+    0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+    0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+    0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+    0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+    0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+    0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+    0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+    0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+    0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+    0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+    0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+    0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+    0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+    0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+    0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+    0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+    0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+    0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+    0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+    0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+    0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+    0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+    0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+    0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+    0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+    0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+    0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+    0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+    0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+    0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+static const u32 Td3[256] = {
+    0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+    0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+    0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+    0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+    0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+    0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+    0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+    0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+    0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+    0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+    0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+    0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+    0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+    0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+    0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+    0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+    0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+    0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+    0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+    0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+    0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+    0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+    0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+    0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+    0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+    0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+    0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+    0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+    0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+    0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+    0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+    0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+    0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+    0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+    0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+    0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+    0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+    0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+    0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+    0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+    0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+    0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+    0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+    0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+    0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+    0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+    0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+    0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+    0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+    0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+    0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+    0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+    0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+    0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+    0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+    0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+    0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+    0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+    0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+    0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+    0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+    0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+    0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+    0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+static const u32 Td4[256] = {
+    0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
+    0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
+    0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
+    0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
+    0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
+    0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
+    0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
+    0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
+    0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
+    0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
+    0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
+    0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
+    0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
+    0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
+    0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
+    0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
+    0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
+    0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
+    0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
+    0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
+    0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
+    0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
+    0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
+    0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
+    0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
+    0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
+    0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
+    0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
+    0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
+    0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
+    0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
+    0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
+    0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
+    0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
+    0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
+    0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
+    0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
+    0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
+    0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
+    0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
+    0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
+    0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
+    0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
+    0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
+    0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
+    0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
+    0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
+    0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
+    0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
+    0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
+    0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
+    0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
+    0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
+    0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
+    0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
+    0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
+    0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
+    0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
+    0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
+    0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
+    0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
+    0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
+    0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
+    0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
+};
+static const u32 rcon[] = {
+       0x01000000, 0x02000000, 0x04000000, 0x08000000,
+       0x10000000, 0x20000000, 0x40000000, 0x80000000,
+       0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
+
+#ifdef _MSC_VER
+#define GETU32(p) SWAP(*((u32 *)(p)))
+#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
+#else
+#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
+#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
+#endif
+
+/**
+ * Expand the cipher key into the encryption key schedule.
+ *
+ * @return     the number of rounds for the given cipher key size.
+ */
+int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
+       int i = 0;
+       u32 temp;
+
+       rk[0] = GETU32(cipherKey     );
+       rk[1] = GETU32(cipherKey +  4);
+       rk[2] = GETU32(cipherKey +  8);
+       rk[3] = GETU32(cipherKey + 12);
+       if (keyBits == 128) {
+               for (;;) {
+                       temp  = rk[3];
+                       rk[4] = rk[0] ^
+                               (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+                               (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
+                               (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
+                               (Te4[(temp >> 24)       ] & 0x000000ff) ^
+                               rcon[i];
+                       rk[5] = rk[1] ^ rk[4];
+                       rk[6] = rk[2] ^ rk[5];
+                       rk[7] = rk[3] ^ rk[6];
+                       if (++i == 10) {
+                               return 10;
+                       }
+                       rk += 4;
+               }
+       }
+       rk[4] = GETU32(cipherKey + 16);
+       rk[5] = GETU32(cipherKey + 20);
+       if (keyBits == 192) {
+               for (;;) {
+                       temp = rk[ 5];
+                       rk[ 6] = rk[ 0] ^
+                               (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+                               (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
+                               (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
+                               (Te4[(temp >> 24)       ] & 0x000000ff) ^
+                               rcon[i];
+                       rk[ 7] = rk[ 1] ^ rk[ 6];
+                       rk[ 8] = rk[ 2] ^ rk[ 7];
+                       rk[ 9] = rk[ 3] ^ rk[ 8];
+                       if (++i == 8) {
+                               return 12;
+                       }
+                       rk[10] = rk[ 4] ^ rk[ 9];
+                       rk[11] = rk[ 5] ^ rk[10];
+                       rk += 6;
+               }
+       }
+       rk[6] = GETU32(cipherKey + 24);
+       rk[7] = GETU32(cipherKey + 28);
+       if (keyBits == 256) {
+        for (;;) {
+               temp = rk[ 7];
+               rk[ 8] = rk[ 0] ^
+                       (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+                       (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
+                       (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
+                       (Te4[(temp >> 24)       ] & 0x000000ff) ^
+                       rcon[i];
+               rk[ 9] = rk[ 1] ^ rk[ 8];
+               rk[10] = rk[ 2] ^ rk[ 9];
+               rk[11] = rk[ 3] ^ rk[10];
+                       if (++i == 7) {
+                               return 14;
+                       }
+               temp = rk[11];
+               rk[12] = rk[ 4] ^
+                       (Te4[(temp >> 24)       ] & 0xff000000) ^
+                       (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
+                       (Te4[(temp >>  8) & 0xff] & 0x0000ff00) ^
+                       (Te4[(temp      ) & 0xff] & 0x000000ff);
+               rk[13] = rk[ 5] ^ rk[12];
+               rk[14] = rk[ 6] ^ rk[13];
+               rk[15] = rk[ 7] ^ rk[14];
+
+                       rk += 8;
+        }
+       }
+       return 0;
+}
+
+/**
+ * Expand the cipher key into the decryption key schedule.
+ *
+ * @return     the number of rounds for the given cipher key size.
+ */
+int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
+       int Nr, i, j;
+       u32 temp;
+
+       /* expand the cipher key: */
+       Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
+       /* invert the order of the round keys: */
+       for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
+               temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
+               temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+               temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+               temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+       }
+       /* apply the inverse MixColumn transform to all round keys but the first and the last: */
+       for (i = 1; i < Nr; i++) {
+               rk += 4;
+               rk[0] =
+                       Td0[Te4[(rk[0] >> 24)       ] & 0xff] ^
+                       Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
+                       Td2[Te4[(rk[0] >>  8) & 0xff] & 0xff] ^
+                       Td3[Te4[(rk[0]      ) & 0xff] & 0xff];
+               rk[1] =
+                       Td0[Te4[(rk[1] >> 24)       ] & 0xff] ^
+                       Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
+                       Td2[Te4[(rk[1] >>  8) & 0xff] & 0xff] ^
+                       Td3[Te4[(rk[1]      ) & 0xff] & 0xff];
+               rk[2] =
+                       Td0[Te4[(rk[2] >> 24)       ] & 0xff] ^
+                       Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
+                       Td2[Te4[(rk[2] >>  8) & 0xff] & 0xff] ^
+                       Td3[Te4[(rk[2]      ) & 0xff] & 0xff];
+               rk[3] =
+                       Td0[Te4[(rk[3] >> 24)       ] & 0xff] ^
+                       Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
+                       Td2[Te4[(rk[3] >>  8) & 0xff] & 0xff] ^
+                       Td3[Te4[(rk[3]      ) & 0xff] & 0xff];
+       }
+       return Nr;
+}
+
+void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) {
+       u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+    int r;
+#endif /* ?FULL_UNROLL */
+
+    /*
+        * map byte array block to cipher state
+        * and add initial round key:
+        */
+       s0 = GETU32(pt     ) ^ rk[0];
+       s1 = GETU32(pt +  4) ^ rk[1];
+       s2 = GETU32(pt +  8) ^ rk[2];
+       s3 = GETU32(pt + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+    /* round 1: */
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
+       /* round 2: */
+       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
+       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
+       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
+       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
+    /* round 3: */
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
+       /* round 4: */
+       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
+       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
+       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
+       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
+    /* round 5: */
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
+       /* round 6: */
+       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
+       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
+       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
+       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
+    /* round 7: */
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
+       /* round 8: */
+       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
+       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
+       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
+       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
+    /* round 9: */
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
+    if (Nr > 10) {
+        /* round 10: */
+        s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
+        s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
+        s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
+        s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
+        /* round 11: */
+        t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
+        t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
+        t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
+        t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
+        if (Nr > 12) {
+            /* round 12: */
+            s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
+            s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
+            s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
+            s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
+            /* round 13: */
+            t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
+            t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
+            t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
+            t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
+        }
+    }
+    rk += Nr << 2;
+#else  /* !FULL_UNROLL */
+    /*
+        * Nr - 1 full rounds:
+        */
+    r = Nr >> 1;
+    for (;;) {
+        t0 =
+            Te0[(s0 >> 24)       ] ^
+            Te1[(s1 >> 16) & 0xff] ^
+            Te2[(s2 >>  8) & 0xff] ^
+            Te3[(s3      ) & 0xff] ^
+            rk[4];
+        t1 =
+            Te0[(s1 >> 24)       ] ^
+            Te1[(s2 >> 16) & 0xff] ^
+            Te2[(s3 >>  8) & 0xff] ^
+            Te3[(s0      ) & 0xff] ^
+            rk[5];
+        t2 =
+            Te0[(s2 >> 24)       ] ^
+            Te1[(s3 >> 16) & 0xff] ^
+            Te2[(s0 >>  8) & 0xff] ^
+            Te3[(s1      ) & 0xff] ^
+            rk[6];
+        t3 =
+            Te0[(s3 >> 24)       ] ^
+            Te1[(s0 >> 16) & 0xff] ^
+            Te2[(s1 >>  8) & 0xff] ^
+            Te3[(s2      ) & 0xff] ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+        s0 =
+            Te0[(t0 >> 24)       ] ^
+            Te1[(t1 >> 16) & 0xff] ^
+            Te2[(t2 >>  8) & 0xff] ^
+            Te3[(t3      ) & 0xff] ^
+            rk[0];
+        s1 =
+            Te0[(t1 >> 24)       ] ^
+            Te1[(t2 >> 16) & 0xff] ^
+            Te2[(t3 >>  8) & 0xff] ^
+            Te3[(t0      ) & 0xff] ^
+            rk[1];
+        s2 =
+            Te0[(t2 >> 24)       ] ^
+            Te1[(t3 >> 16) & 0xff] ^
+            Te2[(t0 >>  8) & 0xff] ^
+            Te3[(t1      ) & 0xff] ^
+            rk[2];
+        s3 =
+            Te0[(t3 >> 24)       ] ^
+            Te1[(t0 >> 16) & 0xff] ^
+            Te2[(t1 >>  8) & 0xff] ^
+            Te3[(t2      ) & 0xff] ^
+            rk[3];
+    }
+#endif /* ?FULL_UNROLL */
+    /*
+        * apply last round and
+        * map cipher state to byte array block:
+        */
+       s0 =
+               (Te4[(t0 >> 24)       ] & 0xff000000) ^
+               (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+               (Te4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
+               (Te4[(t3      ) & 0xff] & 0x000000ff) ^
+               rk[0];
+       PUTU32(ct     , s0);
+       s1 =
+               (Te4[(t1 >> 24)       ] & 0xff000000) ^
+               (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+               (Te4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
+               (Te4[(t0      ) & 0xff] & 0x000000ff) ^
+               rk[1];
+       PUTU32(ct +  4, s1);
+       s2 =
+               (Te4[(t2 >> 24)       ] & 0xff000000) ^
+               (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+               (Te4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
+               (Te4[(t1      ) & 0xff] & 0x000000ff) ^
+               rk[2];
+       PUTU32(ct +  8, s2);
+       s3 =
+               (Te4[(t3 >> 24)       ] & 0xff000000) ^
+               (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+               (Te4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
+               (Te4[(t2      ) & 0xff] & 0x000000ff) ^
+               rk[3];
+       PUTU32(ct + 12, s3);
+}
+
+void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) {
+       u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+    int r;
+#endif /* ?FULL_UNROLL */
+
+    /*
+        * map byte array block to cipher state
+        * and add initial round key:
+        */
+    s0 = GETU32(ct     ) ^ rk[0];
+    s1 = GETU32(ct +  4) ^ rk[1];
+    s2 = GETU32(ct +  8) ^ rk[2];
+    s3 = GETU32(ct + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+    /* round 1: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
+    /* round 2: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
+    /* round 3: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
+    /* round 4: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
+    /* round 5: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
+    /* round 6: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
+    /* round 7: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
+    /* round 8: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
+    /* round 9: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
+    if (Nr > 10) {
+        /* round 10: */
+        s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
+        s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
+        s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
+        s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
+        /* round 11: */
+        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
+        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
+        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
+        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
+        if (Nr > 12) {
+            /* round 12: */
+            s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
+            s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
+            s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
+            s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
+            /* round 13: */
+            t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
+            t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
+            t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
+            t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
+        }
+    }
+       rk += Nr << 2;
+#else  /* !FULL_UNROLL */
+    /*
+     * Nr - 1 full rounds:
+     */
+    r = Nr >> 1;
+    for (;;) {
+        t0 =
+            Td0[(s0 >> 24)       ] ^
+            Td1[(s3 >> 16) & 0xff] ^
+            Td2[(s2 >>  8) & 0xff] ^
+            Td3[(s1      ) & 0xff] ^
+            rk[4];
+        t1 =
+            Td0[(s1 >> 24)       ] ^
+            Td1[(s0 >> 16) & 0xff] ^
+            Td2[(s3 >>  8) & 0xff] ^
+            Td3[(s2      ) & 0xff] ^
+            rk[5];
+        t2 =
+            Td0[(s2 >> 24)       ] ^
+            Td1[(s1 >> 16) & 0xff] ^
+            Td2[(s0 >>  8) & 0xff] ^
+            Td3[(s3      ) & 0xff] ^
+            rk[6];
+        t3 =
+            Td0[(s3 >> 24)       ] ^
+            Td1[(s2 >> 16) & 0xff] ^
+            Td2[(s1 >>  8) & 0xff] ^
+            Td3[(s0      ) & 0xff] ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+        s0 =
+            Td0[(t0 >> 24)       ] ^
+            Td1[(t3 >> 16) & 0xff] ^
+            Td2[(t2 >>  8) & 0xff] ^
+            Td3[(t1      ) & 0xff] ^
+            rk[0];
+        s1 =
+            Td0[(t1 >> 24)       ] ^
+            Td1[(t0 >> 16) & 0xff] ^
+            Td2[(t3 >>  8) & 0xff] ^
+            Td3[(t2      ) & 0xff] ^
+            rk[1];
+        s2 =
+            Td0[(t2 >> 24)       ] ^
+            Td1[(t1 >> 16) & 0xff] ^
+            Td2[(t0 >>  8) & 0xff] ^
+            Td3[(t3      ) & 0xff] ^
+            rk[2];
+        s3 =
+            Td0[(t3 >> 24)       ] ^
+            Td1[(t2 >> 16) & 0xff] ^
+            Td2[(t1 >>  8) & 0xff] ^
+            Td3[(t0      ) & 0xff] ^
+            rk[3];
+    }
+#endif /* ?FULL_UNROLL */
+    /*
+        * apply last round and
+        * map cipher state to byte array block:
+        */
+       s0 =
+               (Td4[(t0 >> 24)       ] & 0xff000000) ^
+               (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+               (Td4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
+               (Td4[(t1      ) & 0xff] & 0x000000ff) ^
+               rk[0];
+       PUTU32(pt     , s0);
+       s1 =
+               (Td4[(t1 >> 24)       ] & 0xff000000) ^
+               (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+               (Td4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
+               (Td4[(t2      ) & 0xff] & 0x000000ff) ^
+               rk[1];
+       PUTU32(pt +  4, s1);
+       s2 =
+               (Td4[(t2 >> 24)       ] & 0xff000000) ^
+               (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+               (Td4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
+               (Td4[(t3      ) & 0xff] & 0x000000ff) ^
+               rk[2];
+       PUTU32(pt +  8, s2);
+       s3 =
+               (Td4[(t3 >> 24)       ] & 0xff000000) ^
+               (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+               (Td4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
+               (Td4[(t0      ) & 0xff] & 0x000000ff) ^
+               rk[3];
+       PUTU32(pt + 12, s3);
+}
+
+#ifdef INTERMEDIATE_VALUE_KAT
+
+void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) {
+       int r;
+       u32 s0, s1, s2, s3, t0, t1, t2, t3;
+
+    /*
+        * map byte array block to cipher state
+        * and add initial round key:
+        */
+       s0 = GETU32(block     ) ^ rk[0];
+       s1 = GETU32(block +  4) ^ rk[1];
+       s2 = GETU32(block +  8) ^ rk[2];
+       s3 = GETU32(block + 12) ^ rk[3];
+    rk += 4;
+
+    /*
+        * Nr - 1 full rounds:
+        */
+       for (r = (rounds < Nr ? rounds : Nr - 1); r > 0; r--) {
+               t0 =
+                       Te0[(s0 >> 24)       ] ^
+                       Te1[(s1 >> 16) & 0xff] ^
+                       Te2[(s2 >>  8) & 0xff] ^
+                       Te3[(s3      ) & 0xff] ^
+                       rk[0];
+               t1 =
+                       Te0[(s1 >> 24)       ] ^
+                       Te1[(s2 >> 16) & 0xff] ^
+                       Te2[(s3 >>  8) & 0xff] ^
+                       Te3[(s0      ) & 0xff] ^
+                       rk[1];
+               t2 =
+                       Te0[(s2 >> 24)       ] ^
+                       Te1[(s3 >> 16) & 0xff] ^
+                       Te2[(s0 >>  8) & 0xff] ^
+                       Te3[(s1      ) & 0xff] ^
+                       rk[2];
+               t3 =
+                       Te0[(s3 >> 24)       ] ^
+                       Te1[(s0 >> 16) & 0xff] ^
+                       Te2[(s1 >>  8) & 0xff] ^
+                       Te3[(s2      ) & 0xff] ^
+                       rk[3];
+
+               s0 = t0;
+               s1 = t1;
+               s2 = t2;
+               s3 = t3;
+               rk += 4;
+
+    }
+
+    /*
+        * apply last round and
+        * map cipher state to byte array block:
+        */
+       if (rounds == Nr) {
+       t0 =
+               (Te4[(s0 >> 24)       ] & 0xff000000) ^
+               (Te4[(s1 >> 16) & 0xff] & 0x00ff0000) ^
+               (Te4[(s2 >>  8) & 0xff] & 0x0000ff00) ^
+               (Te4[(s3      ) & 0xff] & 0x000000ff) ^
+               rk[0];
+       t1 =
+               (Te4[(s1 >> 24)       ] & 0xff000000) ^
+               (Te4[(s2 >> 16) & 0xff] & 0x00ff0000) ^
+               (Te4[(s3 >>  8) & 0xff] & 0x0000ff00) ^
+               (Te4[(s0      ) & 0xff] & 0x000000ff) ^
+               rk[1];
+       t2 =
+               (Te4[(s2 >> 24)       ] & 0xff000000) ^
+               (Te4[(s3 >> 16) & 0xff] & 0x00ff0000) ^
+               (Te4[(s0 >>  8) & 0xff] & 0x0000ff00) ^
+               (Te4[(s1      ) & 0xff] & 0x000000ff) ^
+               rk[2];
+       t3 =
+               (Te4[(s3 >> 24)       ] & 0xff000000) ^
+               (Te4[(s0 >> 16) & 0xff] & 0x00ff0000) ^
+               (Te4[(s1 >>  8) & 0xff] & 0x0000ff00) ^
+               (Te4[(s2      ) & 0xff] & 0x000000ff) ^
+               rk[3];
+               
+               s0 = t0;
+               s1 = t1;
+               s2 = t2;
+               s3 = t3;
+       }
+
+       PUTU32(block     , s0);
+       PUTU32(block +  4, s1);
+       PUTU32(block +  8, s2);
+       PUTU32(block + 12, s3);
+}
+
+void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds) {
+       int r;
+       u32 s0, s1, s2, s3, t0, t1, t2, t3;
+
+    /*
+        * map byte array block to cipher state
+        * and add initial round key:
+        */
+       s0 = GETU32(block     ) ^ rk[0];
+       s1 = GETU32(block +  4) ^ rk[1];
+       s2 = GETU32(block +  8) ^ rk[2];
+       s3 = GETU32(block + 12) ^ rk[3];
+    rk += 4;
+
+    /*
+        * Nr - 1 full rounds:
+        */
+       for (r = (rounds < Nr ? rounds : Nr) - 1; r > 0; r--) {
+               t0 =
+                       Td0[(s0 >> 24)       ] ^
+                       Td1[(s3 >> 16) & 0xff] ^
+                       Td2[(s2 >>  8) & 0xff] ^
+                       Td3[(s1      ) & 0xff] ^
+                       rk[0];
+               t1 =
+                       Td0[(s1 >> 24)       ] ^
+                       Td1[(s0 >> 16) & 0xff] ^
+                       Td2[(s3 >>  8) & 0xff] ^
+                       Td3[(s2      ) & 0xff] ^
+                       rk[1];
+               t2 =
+                       Td0[(s2 >> 24)       ] ^
+                       Td1[(s1 >> 16) & 0xff] ^
+                       Td2[(s0 >>  8) & 0xff] ^
+                       Td3[(s3      ) & 0xff] ^
+                       rk[2];
+               t3 =
+                       Td0[(s3 >> 24)       ] ^
+                       Td1[(s2 >> 16) & 0xff] ^
+                       Td2[(s1 >>  8) & 0xff] ^
+                       Td3[(s0      ) & 0xff] ^
+                       rk[3];
+
+               s0 = t0;
+               s1 = t1;
+               s2 = t2;
+               s3 = t3;
+               rk += 4;
+
+    }
+
+    /*
+        * complete the last round and
+        * map cipher state to byte array block:
+        */
+       t0 =
+               (Td4[(s0 >> 24)       ] & 0xff000000) ^
+               (Td4[(s3 >> 16) & 0xff] & 0x00ff0000) ^
+               (Td4[(s2 >>  8) & 0xff] & 0x0000ff00) ^
+               (Td4[(s1      ) & 0xff] & 0x000000ff);
+       t1 =
+               (Td4[(s1 >> 24)       ] & 0xff000000) ^
+               (Td4[(s0 >> 16) & 0xff] & 0x00ff0000) ^
+               (Td4[(s3 >>  8) & 0xff] & 0x0000ff00) ^
+               (Td4[(s2      ) & 0xff] & 0x000000ff);
+       t2 =
+               (Td4[(s2 >> 24)       ] & 0xff000000) ^
+               (Td4[(s1 >> 16) & 0xff] & 0x00ff0000) ^
+               (Td4[(s0 >>  8) & 0xff] & 0x0000ff00) ^
+               (Td4[(s3      ) & 0xff] & 0x000000ff);
+       t3 =
+               (Td4[(s3 >> 24)       ] & 0xff000000) ^
+               (Td4[(s2 >> 16) & 0xff] & 0x00ff0000) ^
+               (Td4[(s1 >>  8) & 0xff] & 0x0000ff00) ^
+               (Td4[(s0      ) & 0xff] & 0x000000ff);
+
+       if (rounds == Nr) {
+           t0 ^= rk[0];
+           t1 ^= rk[1];
+           t2 ^= rk[2];
+           t3 ^= rk[3];
+       }
+
+       PUTU32(block     , t0);
+       PUTU32(block +  4, t1);
+       PUTU32(block +  8, t2);
+       PUTU32(block + 12, t3);
+}
+
+#endif /* INTERMEDIATE_VALUE_KAT */
diff --git a/src/libhashkit/rijndael.hpp b/src/libhashkit/rijndael.hpp
new file mode 100644 (file)
index 0000000..1d3aec6
--- /dev/null
@@ -0,0 +1,49 @@
+/**
+ * rijndael-alg-fst.h
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#define MAXKC  (256/32)
+#define MAXKB  (256/8)
+#define MAXNR  14
+
+#define AES_MAXKC MAXKC
+#define AES_MAXKB MAXKB
+#define AES_MAXNR MAXNR
+
+typedef unsigned char  u8;     
+typedef unsigned short u16;    
+typedef unsigned int   u32;
+
+int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
+int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits);
+void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]);
+void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]);
+
+#ifdef INTERMEDIATE_VALUE_KAT
+void rijndaelEncryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds);
+void rijndaelDecryptRound(const u32 rk[/*4*(Nr + 1)*/], int Nr, u8 block[16], int rounds);
+#endif /* INTERMEDIATE_VALUE_KAT */
diff --git a/src/libhashkit/str_algorithm.cc b/src/libhashkit/str_algorithm.cc
new file mode 100644 (file)
index 0000000..b84a0bb
--- /dev/null
@@ -0,0 +1,58 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libhashkit/common.h>
+
+const char * libhashkit_string_hash(hashkit_hash_algorithm_t type)
+{
+  switch(type)
+  {
+  case HASHKIT_HASH_DEFAULT: return "DEFAULT";
+  case HASHKIT_HASH_MD5: return "MD5";
+  case HASHKIT_HASH_CRC: return "CRC";
+  case HASHKIT_HASH_FNV1_64: return "FNV1_64";
+  case HASHKIT_HASH_FNV1A_64: return "FNV1A_64";
+  case HASHKIT_HASH_FNV1_32: return "FNV1_32";
+  case HASHKIT_HASH_FNV1A_32: return "FNV1A_32";
+  case HASHKIT_HASH_HSIEH: return "HSIEH";
+  case HASHKIT_HASH_MURMUR: return "MURMUR";
+  case HASHKIT_HASH_MURMUR3: return "MURMUR3";
+  case HASHKIT_HASH_JENKINS: return "JENKINS";
+  case HASHKIT_HASH_CUSTOM: return "CUSTOM";
+  default:
+  case HASHKIT_HASH_MAX: return "INVALID";
+  }
+}
diff --git a/src/libhashkit/strerror.cc b/src/libhashkit/strerror.cc
new file mode 100644 (file)
index 0000000..f67e5c5
--- /dev/null
@@ -0,0 +1,56 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  HashKit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2009 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+#include <libhashkit/common.h>
+
+const char *hashkit_strerror(hashkit_st *ptr, hashkit_return_t rc)
+{
+  (void)ptr;
+  switch (rc)
+  {
+  case HASHKIT_SUCCESS: return "SUCCESS";
+  case HASHKIT_FAILURE: return "FAILURE";
+  case HASHKIT_MEMORY_ALLOCATION_FAILURE: return "MEMORY ALLOCATION FAILURE";
+  case HASHKIT_INVALID_ARGUMENT: return "INVALID ARGUMENT";
+  case HASHKIT_INVALID_HASH: return "INVALID hashkit_hash_algorithm_t";
+  case HASHKIT_MAXIMUM_RETURN:
+  default:
+    return "INVALID hashkit_return_t";
+  }
+}
diff --git a/src/libhashkit/string.cc b/src/libhashkit/string.cc
new file mode 100644 (file)
index 0000000..05bbdc5
--- /dev/null
@@ -0,0 +1,247 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libhashkit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libhashkit/common.h>
+
+#include <cassert>
+#include <cstring>
+
+#define HASHKIT_BLOCK_SIZE 1024
+
+struct hashkit_string_st {
+  char *end;
+  size_t current_size;
+  char *string;
+};
+
+inline static bool _string_check(hashkit_string_st *string, size_t need)
+{
+  if (need and need > (size_t)(string->current_size - (size_t)(string->end - string->string)))
+  {
+    size_t current_offset= (size_t) (string->end - string->string);
+
+    /* This is the block multiplier. To keep it larger and surive division errors we must round it up */
+    size_t adjust= (need - (size_t)(string->current_size - (size_t)(string->end - string->string))) / HASHKIT_BLOCK_SIZE;
+    adjust++;
+
+    size_t new_size= sizeof(char) * (size_t)((adjust * HASHKIT_BLOCK_SIZE) + string->current_size);
+    /* Test for overflow */
+    if (new_size < need)
+    {
+      return false;
+    }
+
+    char *new_value= (char*)realloc(string->string, new_size);
+
+    if (new_value == NULL)
+    {
+      return false;
+    }
+
+    string->string= new_value;
+    string->end= string->string + current_offset;
+
+    string->current_size+= (HASHKIT_BLOCK_SIZE * adjust);
+  }
+
+  return true;
+}
+
+static inline void _init_string(hashkit_string_st *self)
+{
+  self->current_size= 0;
+  self->end= self->string= NULL;
+}
+
+hashkit_string_st *hashkit_string_create(size_t initial_size)
+{
+  hashkit_string_st* self= (hashkit_string_st*)calloc(1, sizeof(hashkit_string_st));
+
+  if (self)
+  {
+    if (_string_check(self, initial_size) == false)
+    {
+      free(self);
+
+      return NULL;
+    }
+  }
+
+  return self;
+}
+
+#if 0
+static bool hashkit_string_append_null(hashkit_string_st *string)
+{
+  if (_string_check(string, 1) == false)
+  {
+    return false;
+  }
+
+  *string->end= 0;
+
+  return true;
+}
+#endif
+
+bool hashkit_string_append_character(hashkit_string_st *string,
+                                     char character)
+{
+  if (_string_check(string, 1) == false)
+  {
+    return false;
+  }
+
+  *string->end= character;
+  string->end++;
+
+  return true;
+}
+
+bool hashkit_string_append(hashkit_string_st *string,
+                           const char *value, size_t length)
+{
+  if (_string_check(string, length) == false)
+  {
+    return false;
+  }
+
+  assert(length <= string->current_size);
+  assert(string->string);
+  assert(string->end >= string->string);
+
+  memcpy(string->end, value, length);
+  string->end+= length;
+
+  return true;
+}
+
+char *hashkit_string_c_copy(hashkit_string_st *string)
+{
+  if (hashkit_string_length(string) == 0)
+  {
+    return NULL;
+  }
+
+  char *c_ptr= static_cast<char *>(malloc((hashkit_string_length(string)+1) * sizeof(char)));
+  if (c_ptr == NULL)
+  {
+    return NULL;
+  }
+
+  memcpy(c_ptr, hashkit_string_c_str(string), hashkit_string_length(string));
+  c_ptr[hashkit_string_length(string)]= 0;
+
+  return c_ptr;
+}
+
+void hashkit_string_reset(hashkit_string_st *string)
+{
+  string->end= string->string;
+}
+
+void hashkit_string_free(hashkit_string_st *ptr)
+{
+  if (ptr == NULL)
+  {
+    return;
+  }
+
+  if (ptr->string)
+  {
+    free(ptr->string);
+  }
+  free(ptr);
+}
+
+bool hashkit_string_resize(hashkit_string_st& string, const size_t need)
+{
+  return _string_check(&string, need);
+}
+
+size_t hashkit_string_length(const hashkit_string_st *self)
+{
+  return size_t(self->end -self->string);
+}
+
+size_t hashkit_string_max_size(const hashkit_string_st *self)
+{
+  return self->current_size;
+}
+
+char *hashkit_string_take(hashkit_string_st *self)
+{
+  assert(self);
+  if (self == NULL)
+  {
+    return NULL;
+  }
+  char *value= self->string;
+
+  _init_string(self);
+
+  return value;
+}
+
+char *hashkit_string_c_str_mutable(hashkit_string_st *self)
+{
+  assert(self);
+  if (self == NULL)
+  {
+    return NULL;
+  }
+  return self->string;
+}
+
+const char *hashkit_string_c_str(const hashkit_string_st* self)
+{
+  assert(self);
+  if (self == NULL)
+  {
+    return NULL;
+  }
+  return self->string;
+}
+
+void hashkit_string_set_length(hashkit_string_st *self, size_t length)
+{
+  assert(self);
+  if (self and _string_check(self, length))
+  {
+    self->end= self->string +length;
+  }
+}
diff --git a/src/libhashkit/string.h b/src/libhashkit/string.h
new file mode 100644 (file)
index 0000000..8aee89e
--- /dev/null
@@ -0,0 +1,57 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Hashkit library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+hashkit_string_st *hashkit_string_create(size_t initial_size);
+
+bool hashkit_string_append_character(hashkit_string_st *string, char character);
+
+bool hashkit_string_append(hashkit_string_st *string, const char *value, size_t length);
+
+char *hashkit_string_c_copy(hashkit_string_st *string);
+
+void hashkit_string_reset(hashkit_string_st *string);
+
+bool hashkit_string_resize(hashkit_string_st& string, const size_t need);
+
+size_t hashkit_string_max_size(const hashkit_string_st *self);
+
+char *hashkit_string_take(hashkit_string_st *self);
+
+char *hashkit_string_c_str_mutable(hashkit_string_st *self);
+
+void hashkit_string_set_length(hashkit_string_st *self, size_t length);
diff --git a/src/libmemcached/CMakeLists.txt b/src/libmemcached/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e39c2f6
--- /dev/null
@@ -0,0 +1,96 @@
+
+find_package(FLEX)
+find_package(BISON)
+
+file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/csl)
+bison_target(CSL_PARSER csl/parser.yy ${CMAKE_CURRENT_BINARY_DIR}/csl/parser.cc
+        DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/csl/parser.h
+        )
+flex_target(CSL_SCANNER csl/scanner.l ${CMAKE_CURRENT_BINARY_DIR}/csl/scanner.cc
+        DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/csl/scanner.h
+        )
+add_flex_bison_dependency(CSL_SCANNER CSL_PARSER)
+
+set(LIBMEMCACHED_SOURCES
+        csl/context.cc
+        ${BISON_CSL_PARSER_OUTPUTS}
+        ${FLEX_CSL_SCANNER_OUTPUTS}
+        allocators.cc
+        analyze.cc
+        array.c
+        auto.cc
+        backtrace.cc
+        behavior.cc
+        byteorder.cc
+        callback.cc
+        connect.cc
+        delete.cc
+        do.cc
+        dump.cc
+        encoding_key.cc
+        error.cc
+        exist.cc
+        fetch.cc
+        flag.cc
+        flush.cc
+        flush_buffers.cc
+        get.cc
+        hash.cc
+        hosts.cc
+        initialize_query.cc
+        instance.cc
+        io.cc
+        key.cc
+        memcached.cc
+        namespace.cc
+        options.cc
+        parse.cc
+        poll.cc
+        purge.cc
+        quit.cc
+        response.cc
+        result.cc
+        sasl.cc
+        server.cc
+        server_list.cc
+        stats.cc
+        storage.cc
+        strerror.cc
+        string.cc
+        touch.cc
+        udp.cc
+        verbosity.cc
+        version.cc
+        virtual_bucket.c)
+
+add_library(libmemcached SHARED
+        ${LIBMEMCACHED_SOURCES})
+add_library(memcached ALIAS libmemcached)
+set_target_properties(libmemcached PROPERTIES LIBRARY_OUTPUT_NAME memcached)
+target_link_libraries(libmemcached libhashkit Threads::Threads ${LIBSASL_LIBRARIES} ${CMAKE_DL_LIBS})
+target_include_directories(libmemcached PRIVATE ${LIBSASL_INCLUDEDIR})
+target_compile_definitions(libmemcached PRIVATE -DBUILDING_LIBMEMCACHED)
+
+set_target_properties(libmemcached PROPERTIES SOVERSION ${LIBMEMCACHED_SO_VERSION})
+install(TARGETS libmemcached EXPORT libmemcached
+        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+export(EXPORT libmemcached)
+install(EXPORT libmemcached DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake)
+
+install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
+        FILES_MATCHING REGEX "(memcached|util)\\.h(pp)?"
+        PATTERN csl EXCLUDE
+        PATTERN memcached EXCLUDE
+        PATTERN util EXCLUDE
+        )
+
+# FIXME: dtrace
+
+add_library(libmemcachedinternal STATIC
+        ${LIBMEMCACHED_SOURCES})
+add_library(memcachedinternal ALIAS libmemcachedinternal)
+set_target_properties(libmemcachedinternal PROPERTIES LIBRARY_OUTPUT_NAME memcachedinternal)
+target_link_libraries(libmemcachedinternal libhashkit Threads::Threads ${LIBSASL_LIBRARIES} ${CMAKE_DL_LIBS})
+target_include_directories(libmemcachedinternal PRIVATE ${LIBSASL_INCLUDEDIR})
+target_compile_definitions(libmemcachedinternal PRIVATE -DBUILDING_LIBMEMCACHEDINTERNAL)
diff --git a/src/libmemcached/allocators.cc b/src/libmemcached/allocators.cc
new file mode 100644 (file)
index 0000000..f1caf71
--- /dev/null
@@ -0,0 +1,154 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+void _libmemcached_free(const memcached_st*, void *mem, void*)
+{
+  if (mem)
+  {
+    std::free(mem);
+  }
+}
+
+void *_libmemcached_malloc(const memcached_st *, size_t size, void *)
+{
+  return std::malloc(size);
+}
+
+void *_libmemcached_realloc(const memcached_st*, void *mem, size_t size, void *)
+{
+  return std::realloc(mem, size);
+}
+
+void *_libmemcached_calloc(const memcached_st *self, size_t nelem, size_t size, void *context)
+{
+  if (self->allocators.malloc != _libmemcached_malloc)
+  {
+     void *ret= _libmemcached_malloc(self, nelem * size, context);
+     if (ret)
+     {
+       memset(ret, 0, nelem * size);
+     }
+
+     return ret;
+  }
+
+  return std::calloc(nelem, size);
+}
+
+struct memcached_allocator_t memcached_allocators_return_default(void)
+{
+  static struct memcached_allocator_t global_default_allocator= { _libmemcached_calloc, _libmemcached_free, _libmemcached_malloc, _libmemcached_realloc, 0 };
+  return global_default_allocator;
+}
+
+memcached_return_t memcached_set_memory_allocators(memcached_st *shell,
+                                                   memcached_malloc_fn mem_malloc,
+                                                   memcached_free_fn mem_free,
+                                                   memcached_realloc_fn mem_realloc,
+                                                   memcached_calloc_fn mem_calloc,
+                                                   void *context)
+{
+  Memcached* self= memcached2Memcached(shell);
+  if (self == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  /* All should be set, or none should be set */
+  if (mem_malloc == NULL and mem_free == NULL and mem_realloc == NULL and mem_calloc == NULL) 
+  {
+    self->allocators= memcached_allocators_return_default();
+  }
+  else if (mem_malloc == NULL or mem_free == NULL or mem_realloc == NULL or mem_calloc == NULL)
+  {
+    return memcached_set_error(*self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("NULL parameter provided for one or more allocators"));
+  }
+  else
+  {
+    self->allocators.malloc= mem_malloc;
+    self->allocators.free= mem_free;
+    self->allocators.realloc= mem_realloc;
+    self->allocators.calloc= mem_calloc;
+    self->allocators.context= context;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+void *memcached_get_memory_allocators_context(const memcached_st *shell)
+{
+  const Memcached* self= memcached2Memcached(shell);
+  if (self)
+  {
+    return self->allocators.context;
+  }
+
+  return NULL;
+}
+
+void memcached_get_memory_allocators(const memcached_st *shell,
+                                     memcached_malloc_fn *mem_malloc,
+                                     memcached_free_fn *mem_free,
+                                     memcached_realloc_fn *mem_realloc,
+                                     memcached_calloc_fn *mem_calloc)
+{
+  const Memcached* self= memcached2Memcached(shell);
+  if (self)
+  {
+    if (mem_malloc)
+    {
+      *mem_malloc= self->allocators.malloc;
+    }
+
+    if (mem_free)
+    {
+      *mem_free= self->allocators.free;
+    }
+
+    if (mem_realloc)
+    {
+      *mem_realloc= self->allocators.realloc;
+    }
+
+    if (mem_calloc)
+    {
+      *mem_calloc= self->allocators.calloc;
+    }
+  }
+}
diff --git a/src/libmemcached/allocators.hpp b/src/libmemcached/allocators.hpp
new file mode 100644 (file)
index 0000000..8f19624
--- /dev/null
@@ -0,0 +1,47 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+void _libmemcached_free(const memcached_st *ptr, void *mem, void *context);
+
+void *_libmemcached_malloc(const memcached_st *ptr, const size_t size, void *context);
+
+void *_libmemcached_realloc(const memcached_st *ptr, void *mem, const size_t size, void *context);
+
+void *_libmemcached_calloc(const memcached_st *ptr, size_t nelem, size_t size, void *context);
+
+struct memcached_allocator_t memcached_allocators_return_default(void);
diff --git a/src/libmemcached/analyze.cc b/src/libmemcached/analyze.cc
new file mode 100644 (file)
index 0000000..c6ac15c
--- /dev/null
@@ -0,0 +1,120 @@
+#include <libmemcached/common.h>
+
+static void calc_largest_consumption(memcached_analysis_st *result,
+                                     const uint32_t server_num,
+                                     const uint64_t nbytes)
+{
+  if (result->most_used_bytes < nbytes)
+  {
+    result->most_used_bytes= nbytes;
+    result->most_consumed_server= server_num;
+  }
+}
+
+static void calc_oldest_node(memcached_analysis_st *result,
+                             const uint32_t server_num,
+                             const uint32_t uptime)
+{
+  if (result->longest_uptime < uptime)
+  {
+    result->longest_uptime= uptime;
+    result->oldest_server= server_num;
+  }
+}
+
+static void calc_least_free_node(memcached_analysis_st *result,
+                                 const uint32_t server_num,
+                                 const uint64_t max_allowed_bytes,
+                                 const uint64_t used_bytes)
+{
+  uint64_t remaining_bytes= max_allowed_bytes - used_bytes;
+
+  if (result->least_remaining_bytes == 0 ||
+      remaining_bytes < result->least_remaining_bytes)
+  {
+    result->least_remaining_bytes= remaining_bytes;
+    result->least_free_server= server_num;
+  }
+}
+
+static void calc_average_item_size(memcached_analysis_st *result,
+                                   const uint64_t total_items,
+                                   const uint64_t total_bytes)
+{
+  if (total_items > 0 && total_bytes > 0)
+  {
+    result->average_item_size= (uint32_t) (total_bytes / total_items);
+  }
+}
+
+static void calc_hit_ratio(memcached_analysis_st *result,
+                           const uint64_t total_get_hits,
+                           const uint64_t total_get_cmds)
+{
+  if (total_get_hits == 0 || total_get_cmds == 0)
+  {
+    result->pool_hit_ratio= 0;
+    return;
+  }
+
+  double temp= double(total_get_hits) / total_get_cmds;
+  result->pool_hit_ratio= temp * 100;
+}
+
+memcached_analysis_st *memcached_analyze(memcached_st *shell,
+                                         memcached_stat_st *memc_stat,
+                                         memcached_return_t *error)
+{
+  Memcached* memc= memcached2Memcached(shell);
+  uint64_t total_items= 0, total_bytes= 0;
+  uint64_t total_get_cmds= 0, total_get_hits= 0;
+
+  if (memc == NULL or memc_stat == NULL)
+  {
+    return NULL;
+  }
+
+  memcached_return_t not_used;
+  if (error == NULL)
+  {
+    error= &not_used;
+  }
+
+  *error= MEMCACHED_SUCCESS;
+  uint32_t server_count= memcached_server_count(memc);
+  memcached_analysis_st *result= (memcached_analysis_st*)libmemcached_xcalloc(memc,
+                                                                              memcached_server_count(memc),
+                                                                              memcached_analysis_st);
+
+  if (result == NULL)
+  {
+    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return NULL;
+  }
+
+  result->root= memc;
+
+  for (uint32_t x= 0; x < server_count; x++)
+  {
+    calc_largest_consumption(result, x, memc_stat[x].bytes);
+    calc_oldest_node(result, x, uint32_t(memc_stat[x].uptime));
+    calc_least_free_node(result, x,
+                         memc_stat[x].limit_maxbytes,
+                         memc_stat[x].bytes);
+
+    total_get_hits+= memc_stat[x].get_hits;
+    total_get_cmds+= memc_stat[x].cmd_get;
+    total_items+= memc_stat[x].curr_items;
+    total_bytes+= memc_stat[x].bytes;
+  }
+
+  calc_average_item_size(result, total_items, total_bytes);
+  calc_hit_ratio(result, total_get_hits, total_get_cmds);
+
+  return result;
+}
+
+void memcached_analyze_free(memcached_analysis_st *ptr)
+{
+  libmemcached_free(ptr->root, ptr);
+}
diff --git a/src/libmemcached/array.c b/src/libmemcached/array.c
new file mode 100644 (file)
index 0000000..cd472c3
--- /dev/null
@@ -0,0 +1,128 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+#include <assert.h>
+#include <iso646.h>
+
+struct memcached_array_st
+{
+  Memcached *root;
+  size_t size;
+  char c_str[];
+};
+
+
+memcached_array_st *memcached_array_clone(Memcached *memc, const memcached_array_st *original)
+{
+  if (original)
+  {
+    return memcached_strcpy(memc, original->c_str, original->size);
+  }
+
+  return NULL;
+}
+
+memcached_array_st *memcached_strcpy(Memcached *memc, const char *str, size_t str_length)
+{
+  assert(memc);
+  assert(str);
+  assert(str_length);
+
+  memcached_array_st *array= (struct memcached_array_st *)libmemcached_malloc(memc, sizeof(struct memcached_array_st) +str_length +1);
+
+  if (array)
+  {
+    array->root= memc;
+    array->size= str_length; // We don't count the NULL ending
+    memcpy(array->c_str, str, str_length);
+    array->c_str[str_length]= 0;
+  }
+
+  return array;
+}
+
+bool memcached_array_is_null(memcached_array_st *array)
+{
+  if (array)
+  {
+    return false;
+  }
+
+  return true;
+}
+
+memcached_string_t memcached_array_to_string(memcached_array_st *array)
+{
+  assert(array);
+  assert(array->c_str);
+  assert(array->size);
+  memcached_string_t tmp;
+  tmp.c_str= array->c_str;
+  tmp.size= array->size;
+
+  return tmp;
+}
+
+void memcached_array_free(memcached_array_st *array)
+{
+  if (array)
+  {
+    WATCHPOINT_ASSERT(array->root);
+    libmemcached_free(array->root, array);
+  }
+}
+
+size_t memcached_array_size(memcached_array_st *array)
+{
+  if (array)
+  {
+    return array->size;
+  }
+
+  return 0;
+}
+
+const char *memcached_array_string(memcached_array_st *array)
+{
+  if (array)
+  {
+    return array->c_str;
+  }
+
+  return NULL;
+}
diff --git a/src/libmemcached/array.h b/src/libmemcached/array.h
new file mode 100644 (file)
index 0000000..afb3f91
--- /dev/null
@@ -0,0 +1,68 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+memcached_array_st *memcached_array_clone(Memcached* memc, const memcached_array_st *original);
+
+memcached_array_st *memcached_strcpy(Memcached* memc, const char *str, size_t str_length);
+
+void memcached_array_free(memcached_array_st *array);
+
+size_t memcached_array_size(memcached_array_st *array);
+
+const char *memcached_array_string(memcached_array_st *array);
+
+memcached_string_t memcached_array_to_string(memcached_array_st *array);
+
+bool memcached_array_is_null(memcached_array_st *array);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#ifdef __cplusplus
+#define memcached_print_array(X) static_cast<int>(memcached_array_size(X)), memcached_array_string(X)
+#define memcached_param_array(X) memcached_array_string(X), memcached_array_size(X)
+#else
+#define memcached_print_array(X) (int)memcached_array_size((X)), memcached_array_string((X))
+#define memcached_param_array(X) memcached_array_string(X), memcached_array_size(X)
+#endif
diff --git a/src/libmemcached/assert.hpp b/src/libmemcached/assert.hpp
new file mode 100644 (file)
index 0000000..cd4a194
--- /dev/null
@@ -0,0 +1,93 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libmcachedd client library.
+ *
+ *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+# include <cassert>
+#else
+# include <assert.h>
+#endif // __cplusplus
+
+#ifdef NDEBUG
+# define assert_msg(__expr, __mesg) (void)(__expr); (void)(__mesg);
+# define assert_vmsg(__expr, __mesg, ...) (void)(__expr); (void)(__mesg);
+#else
+
+# ifdef _WIN32
+#  include <malloc.h>
+# else
+#  include <alloca.h>
+# endif
+
+#ifdef __cplusplus
+# include <cstdarg>
+# include <cstdio>
+#else
+# include <stdarg.h>
+# include <stdio.h>
+#endif
+
+# include <libmemcached/backtrace.hpp>
+
+# define assert_msg(__expr, __mesg) \
+do \
+{ \
+  if (not (__expr)) \
+  { \
+    fprintf(stderr, "\n%s:%d Assertion \"%s\" failed for function \"%s\" likely for %s\n", __FILE__, __LINE__, #__expr, __func__, (#__mesg));\
+    custom_backtrace(); \
+    abort(); \
+  } \
+} while (0)
+
+# define assert_vmsg(__expr, __mesg, ...) \
+do \
+{ \
+  if (not (__expr)) \
+  { \
+    size_t ask= snprintf(0, 0, (__mesg), __VA_ARGS__); \
+    ask++; \
+    char *_error_message= (char*)alloca(sizeof(char) * ask); \
+    size_t _error_message_size= snprintf(_error_message, ask, (__mesg), __VA_ARGS__); \
+    fprintf(stderr, "\n%s:%d Assertion '%s' failed for function '%s' [ %.*s ]\n", __FILE__, __LINE__, #__expr, __func__, int(_error_message_size), _error_message);\
+    custom_backtrace(); \
+    abort(); \
+  } \
+} while (0)
+
+#endif // NDEBUG
diff --git a/src/libmemcached/auto.cc b/src/libmemcached/auto.cc
new file mode 100644 (file)
index 0000000..06e7ab6
--- /dev/null
@@ -0,0 +1,385 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+static void auto_response(memcached_instance_st* instance, const bool reply,  memcached_return_t& rc, uint64_t* value)
+{
+  // If the message was successfully sent, then get the response, otherwise
+  // fail.
+  if (memcached_success(rc))
+  {
+    if (reply == false)
+    {
+      *value= UINT64_MAX;
+      return;
+    }
+
+    rc= memcached_response(instance, &instance->root->result);
+  }
+
+  if (memcached_fatal(rc))
+  {
+    assert(memcached_last_error(instance->root) != MEMCACHED_SUCCESS);
+    *value= UINT64_MAX;
+  }
+  else if (memcached_failed(rc))
+  {
+    *value= UINT64_MAX;
+  }
+  else
+  {
+    assert(memcached_last_error(instance->root) != MEMCACHED_NOTFOUND);
+    *value= instance->root->result.numeric_value;
+  }
+}
+
+static memcached_return_t text_incr_decr(memcached_instance_st* instance,
+                                         const bool is_incr,
+                                         const char *key, size_t key_length,
+                                         const uint64_t offset,
+                                         const bool reply)
+{
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+
+  int send_length= snprintf(buffer, sizeof(buffer), " %" PRIu64, offset);
+  if (size_t(send_length) >= sizeof(buffer) or send_length < 0)
+  {
+    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                               memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
+  }
+
+  libmemcached_io_vector_st vector[]=
+  {
+    { NULL, 0 },
+    { memcached_literal_param("incr ") },
+    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+    { key, key_length },
+    { buffer, size_t(send_length) },
+    { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
+    { memcached_literal_param("\r\n") }
+  };
+
+  if (is_incr == false)
+  {
+    vector[1].buffer= "decr ";
+  }
+
+  return memcached_vdo(instance, vector, 7, true);
+}
+
+static memcached_return_t binary_incr_decr(memcached_instance_st* instance,
+                                           protocol_binary_command cmd,
+                                           const char *key, const size_t key_length,
+                                           const uint64_t offset,
+                                           const uint64_t initial,
+                                           const uint32_t expiration,
+                                           const bool reply)
+{
+  if (reply == false)
+  {
+    if(cmd == PROTOCOL_BINARY_CMD_DECREMENT)
+    {
+      cmd= PROTOCOL_BINARY_CMD_DECREMENTQ;
+    }
+
+    if(cmd == PROTOCOL_BINARY_CMD_INCREMENT)
+    {
+      cmd= PROTOCOL_BINARY_CMD_INCREMENTQ;
+    }
+  }
+  protocol_binary_request_incr request= {}; // = {.bytes= {0}};
+
+  initialize_binary_request(instance, request.message.header);
+
+  request.message.header.request.opcode= cmd;
+  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(instance->root->_namespace)));
+  request.message.header.request.extlen= 20;
+  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+  request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(instance->root->_namespace) +request.message.header.request.extlen));
+  request.message.body.delta= memcached_htonll(offset);
+  request.message.body.initial= memcached_htonll(initial);
+  request.message.body.expiration= htonl((uint32_t) expiration);
+
+  libmemcached_io_vector_st vector[]=
+  {
+    { NULL, 0 },
+    { request.bytes, sizeof(request.bytes) },
+    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+    { key, key_length }
+  };
+
+  return memcached_vdo(instance, vector, 4, true);
+}
+
+memcached_return_t memcached_increment(memcached_st *memc,
+                                       const char *key, size_t key_length,
+                                       uint32_t offset,
+                                       uint64_t *value)
+{
+  return memcached_increment_by_key(memc, key, key_length, key, key_length, offset, value);
+}
+
+static memcached_return_t increment_decrement_by_key(const protocol_binary_command command,
+                                                     Memcached *memc,
+                                                     const char *group_key, size_t group_key_length,
+                                                     const char *key, size_t key_length,
+                                                     uint64_t offset,
+                                                     uint64_t *value)
+{
+  uint64_t local_value;
+  if (value == NULL)
+  {
+    value= &local_value;
+  }
+
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(memc, true)))
+  {
+    return rc;
+  }
+
+  if (memcached_is_encrypted(memc))
+  {
+    return memcached_set_error(*memc, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, 
+                               memcached_literal_param("Operation not allowed while encyrption is enabled"));
+  }
+
+  if (memcached_failed(rc= memcached_key_test(*memc, (const char **)&key, &key_length, 1)))
+  {
+    return memcached_last_error(memc);
+  }
+
+  uint32_t server_key= memcached_generate_hash_with_redistribution(memc, group_key, group_key_length);
+  memcached_instance_st* instance= memcached_instance_fetch(memc, server_key);
+
+  bool reply= memcached_is_replying(instance->root);
+
+  if (memcached_is_binary(memc))
+  {
+    rc= binary_incr_decr(instance, command,
+                         key, key_length,
+                         uint64_t(offset), 0, MEMCACHED_EXPIRATION_NOT_ADD,
+                         reply);
+  }
+  else
+  {
+    rc= text_incr_decr(instance,
+                       command == PROTOCOL_BINARY_CMD_INCREMENT ? true : false,
+                       key, key_length,
+                       offset, reply);
+  }
+
+  auto_response(instance, reply, rc, value);
+
+  return rc;
+}
+
+static memcached_return_t increment_decrement_with_initial_by_key(const protocol_binary_command command,
+                                                                  Memcached *memc,
+                                                                  const char *group_key,
+                                                                  size_t group_key_length,
+                                                                  const char *key,
+                                                                  size_t key_length,
+                                                                  uint64_t offset,
+                                                                  uint64_t initial,
+                                                                  time_t expiration,
+                                                                  uint64_t *value)
+{
+  uint64_t local_value;
+  if (value == NULL)
+  {
+    value= &local_value;
+  }
+
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(memc, true)))
+  {
+    return rc;
+  }
+
+  if (memcached_is_encrypted(memc))
+  {
+    return memcached_set_error(*memc, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, 
+                               memcached_literal_param("Operation not allowed while encryption is enabled"));
+  }
+
+  if (memcached_failed(rc= memcached_key_test(*memc, (const char **)&key, &key_length, 1)))
+  {
+    return memcached_last_error(memc);
+  }
+
+  uint32_t server_key= memcached_generate_hash_with_redistribution(memc, group_key, group_key_length);
+  memcached_instance_st* instance= memcached_instance_fetch(memc, server_key);
+
+  bool reply= memcached_is_replying(instance->root);
+
+  if (memcached_is_binary(memc))
+  {
+    rc= binary_incr_decr(instance, command,
+                         key, key_length,
+                         offset, initial, uint32_t(expiration),
+                         reply);
+        
+  }
+  else
+  {
+    rc=  memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                             memcached_literal_param("memcached_increment_with_initial_by_key() is not supported via the ASCII protocol"));
+  }
+
+  auto_response(instance, reply, rc, value);
+
+  return rc;
+}
+
+memcached_return_t memcached_decrement(memcached_st *memc,
+                                       const char *key, size_t key_length,
+                                       uint32_t offset,
+                                       uint64_t *value)
+{
+  return memcached_decrement_by_key(memc, key, key_length, key, key_length, offset, value);
+}
+
+
+memcached_return_t memcached_increment_by_key(memcached_st *shell,
+                                              const char *group_key, size_t group_key_length,
+                                              const char *key, size_t key_length,
+                                              uint64_t offset,
+                                              uint64_t *value)
+{
+  Memcached* memc= memcached2Memcached(shell);
+  LIBMEMCACHED_MEMCACHED_INCREMENT_START();
+  memcached_return_t rc= increment_decrement_by_key(PROTOCOL_BINARY_CMD_INCREMENT,
+                                                    memc,
+                                                    group_key, group_key_length,
+                                                    key, key_length,
+                                                    offset, value);
+
+  LIBMEMCACHED_MEMCACHED_INCREMENT_END();
+
+  return rc;
+}
+
+memcached_return_t memcached_decrement_by_key(memcached_st *shell,
+                                              const char *group_key, size_t group_key_length,
+                                              const char *key, size_t key_length,
+                                              uint64_t offset,
+                                              uint64_t *value)
+{
+  Memcached* memc= memcached2Memcached(shell);
+  LIBMEMCACHED_MEMCACHED_DECREMENT_START();
+  memcached_return_t rc= increment_decrement_by_key(PROTOCOL_BINARY_CMD_DECREMENT,
+                                                    memc,
+                                                    group_key, group_key_length,
+                                                    key, key_length,
+                                                    offset, value);
+  LIBMEMCACHED_MEMCACHED_DECREMENT_END();
+
+  return rc;
+}
+
+memcached_return_t memcached_increment_with_initial(memcached_st *memc,
+                                                    const char *key,
+                                                    size_t key_length,
+                                                    uint64_t offset,
+                                                    uint64_t initial,
+                                                    time_t expiration,
+                                                    uint64_t *value)
+{
+  return memcached_increment_with_initial_by_key(memc, key, key_length,
+                                                 key, key_length,
+                                                 offset, initial, expiration, value);
+}
+
+memcached_return_t memcached_increment_with_initial_by_key(memcached_st *shell,
+                                                           const char *group_key,
+                                                           size_t group_key_length,
+                                                           const char *key,
+                                                           size_t key_length,
+                                                           uint64_t offset,
+                                                           uint64_t initial,
+                                                           time_t expiration,
+                                                           uint64_t *value)
+{
+  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
+  Memcached* memc= memcached2Memcached(shell);
+  memcached_return_t rc= increment_decrement_with_initial_by_key(PROTOCOL_BINARY_CMD_INCREMENT, 
+                                                                 memc,
+                                                                 group_key, group_key_length,
+                                                                 key, key_length,
+                                                                 offset, initial, expiration, value);
+  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
+
+  return rc;
+}
+
+memcached_return_t memcached_decrement_with_initial(memcached_st *memc,
+                                                    const char *key,
+                                                    size_t key_length,
+                                                    uint64_t offset,
+                                                    uint64_t initial,
+                                                    time_t expiration,
+                                                    uint64_t *value)
+{
+  return memcached_decrement_with_initial_by_key(memc, key, key_length,
+                                                 key, key_length,
+                                                 offset, initial, expiration, value);
+}
+
+memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *shell,
+                                                           const char *group_key,
+                                                           size_t group_key_length,
+                                                           const char *key,
+                                                           size_t key_length,
+                                                           uint64_t offset,
+                                                           uint64_t initial,
+                                                           time_t expiration,
+                                                           uint64_t *value)
+{
+  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
+  Memcached* memc= memcached2Memcached(shell);
+  memcached_return_t rc= increment_decrement_with_initial_by_key(PROTOCOL_BINARY_CMD_DECREMENT, 
+                                                                 memc,
+                                                                 group_key, group_key_length,
+                                                                 key, key_length,
+                                                                 offset, initial, expiration, value);
+
+  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
+
+  return rc;
+}
diff --git a/src/libmemcached/backtrace.cc b/src/libmemcached/backtrace.cc
new file mode 100644 (file)
index 0000000..e171fbe
--- /dev/null
@@ -0,0 +1,131 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached client library.
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "mem_config.h"
+
+#include "libmemcached/backtrace.hpp"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#if defined(HAVE_SHARED_ENABLED) && HAVE_SHARED_ENABLED
+
+#ifdef HAVE_EXECINFO_H
+#include <execinfo.h>
+#endif
+
+#ifdef HAVE_GCC_ABI_DEMANGLE
+# include <cxxabi.h>
+# define USE_DEMANGLE 1
+#else
+# define USE_DEMANGLE 0
+#endif
+
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+#endif   
+
+const int MAX_DEPTH= 50;
+
+void custom_backtrace(void)
+{
+#ifdef HAVE_EXECINFO_H
+  void *backtrace_buffer[MAX_DEPTH +1];
+
+  int stack_frames= backtrace(backtrace_buffer, MAX_DEPTH);
+  if (stack_frames)
+  {
+    char **symbollist= backtrace_symbols(backtrace_buffer, stack_frames);
+    if (symbollist)
+    {
+      for (int x= 0; x < stack_frames; x++) 
+      {
+        bool was_demangled= false;
+
+        if (USE_DEMANGLE)
+        {
+#ifdef HAVE_DLFCN_H
+          Dl_info dlinfo;
+          if (dladdr(backtrace_buffer[x], &dlinfo))
+          {
+            char demangled_buffer[1024];
+            const char *called_in= "<unresolved>";
+            if (dlinfo.dli_sname)
+            {
+              size_t demangled_size= sizeof(demangled_buffer);
+              int status;
+              char* demangled;
+              if ((demangled= abi::__cxa_demangle(dlinfo.dli_sname, demangled_buffer, &demangled_size, &status)))
+              {
+                called_in= demangled;
+                fprintf(stderr, "---> demangled: %s -> %s\n", demangled_buffer, demangled);
+              }
+              else
+              {
+                called_in= dlinfo.dli_sname;
+              }
+
+              was_demangled= true;
+              fprintf(stderr, "#%d  %p in %s at %s\n",
+                      x, backtrace_buffer[x],
+                      called_in,
+                      dlinfo.dli_fname);
+            }
+          }
+#endif
+        }
+
+        if (was_demangled == false)
+        {
+          fprintf(stderr, "?%d  %p in %s\n", x, backtrace_buffer[x], symbollist[x]);
+        }
+      }
+
+      ::free(symbollist);
+    }
+  }
+#endif // HAVE_EXECINFO_H
+}
+
+#else // HAVE_SHARED_ENABLED
+
+void custom_backtrace(void)
+{
+  fprintf(stderr, "Backtrace null function called\n");
+}
+#endif // AX_ENABLE_BACKTRACE
diff --git a/src/libmemcached/backtrace.hpp b/src/libmemcached/backtrace.hpp
new file mode 100644 (file)
index 0000000..a83d3ea
--- /dev/null
@@ -0,0 +1,48 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libmcachedd client library.
+ *
+ *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void custom_backtrace(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/libmemcached/behavior.cc b/src/libmemcached/behavior.cc
new file mode 100644 (file)
index 0000000..7536248
--- /dev/null
@@ -0,0 +1,727 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+#include <libmemcached/options.hpp>
+#include <libmemcached/virtual_bucket.h>
+
+#include <ctime>
+#include <sys/types.h>
+
+bool memcached_is_consistent_distribution(const Memcached* memc)
+{
+  switch (memc->distribution)
+  {
+  case MEMCACHED_DISTRIBUTION_CONSISTENT:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED:
+    return true;
+
+  case MEMCACHED_DISTRIBUTION_MODULA:
+  case MEMCACHED_DISTRIBUTION_RANDOM:
+  case MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX:
+    break;
+  }
+
+  return false;
+}
+
+/*
+  This function is used to modify the behavior of running client.
+
+  We quit all connections so we can reset the sockets.
+*/
+
+memcached_return_t memcached_behavior_set(memcached_st *shell,
+                                          const memcached_behavior_t flag,
+                                          uint64_t data)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  if (ptr == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  switch (flag)
+  {
+  case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
+    ptr->number_of_replicas= (uint32_t)data;
+    break;
+
+  case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK:
+    ptr->io_msg_watermark= (uint32_t) data;
+    break;
+
+  case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK:
+    ptr->io_bytes_watermark= (uint32_t)data;
+    break;
+
+  case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH:
+    ptr->io_key_prefetch = (uint32_t)data;
+    break;
+
+  case MEMCACHED_BEHAVIOR_SND_TIMEOUT:
+    ptr->snd_timeout= (int32_t)data;
+    break;
+
+  case MEMCACHED_BEHAVIOR_RCV_TIMEOUT:
+    ptr->rcv_timeout= (int32_t)data;
+    break;
+
+  case MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS:
+    ptr->flags.auto_eject_hosts= bool(data);
+    break;
+
+  case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
+    if (data == 0)
+    {
+      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                                        memcached_literal_param("MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT requires a value greater then zero."));
+    }
+    ptr->server_failure_limit= uint32_t(data);
+    break;
+
+  case MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT:
+    ptr->server_timeout_limit= uint32_t(data);
+    break;
+
+  case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL:
+    send_quit(ptr); // We need t shutdown all of the connections to make sure we do the correct protocol
+    if (data)
+    {
+      ptr->flags.verify_key= false;
+    }
+    ptr->flags.binary_protocol= bool(data);
+    break;
+
+  case MEMCACHED_BEHAVIOR_SUPPORT_CAS:
+    ptr->flags.support_cas= bool(data);
+    break;
+
+  case MEMCACHED_BEHAVIOR_NO_BLOCK:
+    ptr->flags.no_block= bool(data);
+    send_quit(ptr);
+    break;
+
+  case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS:
+    if (memcached_is_udp(ptr))
+    {
+      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                                 memcached_literal_param("MEMCACHED_BEHAVIOR_BUFFER_REQUESTS cannot be set while MEMCACHED_BEHAVIOR_USE_UDP is enabled."));
+    }
+    ptr->flags.buffer_requests= bool(data);
+    send_quit(ptr);
+    break;
+
+  case MEMCACHED_BEHAVIOR_USE_UDP:
+    send_quit(ptr); // We need t shutdown all of the connections to make sure we do the correct protocol
+    ptr->flags.use_udp= bool(data);
+    if (bool(data))
+    {
+      ptr->flags.reply= false;
+      ptr->flags.buffer_requests= false;
+    }
+    else
+    {
+      ptr->flags.reply= true;
+    }
+    break;
+
+  case MEMCACHED_BEHAVIOR_TCP_NODELAY:
+    ptr->flags.tcp_nodelay= bool(data);
+    send_quit(ptr);
+    break;
+
+  case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE:
+    ptr->flags.tcp_keepalive= bool(data);
+    send_quit(ptr);
+    break;
+
+  case MEMCACHED_BEHAVIOR_DISTRIBUTION:
+    return memcached_behavior_set_distribution(ptr, (memcached_server_distribution_t)data);
+
+  case MEMCACHED_BEHAVIOR_KETAMA:
+    {
+      if (data) // Turn on
+      {
+        return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA);
+      }
+
+      return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_MODULA);
+    }
+
+  case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED:
+    {
+      if (bool(data) == false)
+      {
+        return memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_KETAMA, true);
+      }
+
+      (void)memcached_behavior_set_key_hash(ptr, MEMCACHED_HASH_MD5);
+      (void)memcached_behavior_set_distribution_hash(ptr, MEMCACHED_HASH_MD5);
+      /**
+        @note We try to keep the same distribution going. This should be deprecated and rewritten.
+      */
+      return memcached_behavior_set_distribution(ptr, MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED);
+    }
+
+  case MEMCACHED_BEHAVIOR_HASH:
+    return memcached_behavior_set_key_hash(ptr, (memcached_hash_t)(data));
+
+  case MEMCACHED_BEHAVIOR_KETAMA_HASH:
+    return memcached_behavior_set_distribution_hash(ptr, (memcached_hash_t)(data));
+
+  case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS:
+    return memcached_set_error(*ptr, MEMCACHED_DEPRECATED, MEMCACHED_AT,
+                                      memcached_literal_param("MEMCACHED_BEHAVIOR_CACHE_LOOKUPS has been deprecated."));
+
+  case MEMCACHED_BEHAVIOR_VERIFY_KEY:
+    if (ptr->flags.binary_protocol)
+    {
+      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                                        memcached_literal_param("MEMCACHED_BEHAVIOR_VERIFY_KEY if the binary protocol has been enabled."));
+    }
+    ptr->flags.verify_key= bool(data);
+    break;
+
+  case MEMCACHED_BEHAVIOR_SORT_HOSTS:
+    {
+      ptr->flags.use_sort_hosts= bool(data);
+      return run_distribution(ptr);
+    }
+
+  case MEMCACHED_BEHAVIOR_POLL_TIMEOUT:
+    ptr->poll_timeout= (int32_t)data;
+    break;
+
+  case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT:
+    ptr->connect_timeout= (int32_t)data;
+    break;
+
+  case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT:
+    ptr->retry_timeout= int32_t(data);
+    break;
+
+  case MEMCACHED_BEHAVIOR_DEAD_TIMEOUT:
+    ptr->dead_timeout= int32_t(data);
+    break;
+
+  case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE:
+    ptr->send_size= (int32_t)data;
+    send_quit(ptr);
+    break;
+
+  case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE:
+    ptr->recv_size= (int32_t)data;
+    send_quit(ptr);
+    break;
+
+  case MEMCACHED_BEHAVIOR_TCP_KEEPIDLE:
+    ptr->tcp_keepidle= (uint32_t)data;
+    send_quit(ptr);
+    break;
+
+  case MEMCACHED_BEHAVIOR_USER_DATA:
+    return memcached_set_error(*ptr, MEMCACHED_DEPRECATED, MEMCACHED_AT,
+                               memcached_literal_param("MEMCACHED_BEHAVIOR_USER_DATA deprecated."));
+
+  case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY:
+    ptr->flags.hash_with_namespace= bool(data);
+    break;
+
+  case MEMCACHED_BEHAVIOR_NOREPLY:
+    if (memcached_is_udp(ptr) and bool(data) == false)
+    {
+      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                                 memcached_literal_param("MEMCACHED_BEHAVIOR_NOREPLY cannot be disabled while MEMCACHED_BEHAVIOR_USE_UDP is enabled."));
+    }
+    // We reverse the logic here to make it easier to understand throughout the
+    // code.
+    ptr->flags.reply= bool(data) ? false : true;
+    break;
+
+  case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
+    ptr->flags.auto_eject_hosts= bool(data);
+    break;
+
+  case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ:
+      srandom((uint32_t) time(NULL));
+      ptr->flags.randomize_replica_read= bool(data);
+      break;
+
+  case MEMCACHED_BEHAVIOR_CORK:
+      return memcached_set_error(*ptr, MEMCACHED_DEPRECATED, MEMCACHED_AT,
+                                 memcached_literal_param("MEMCACHED_BEHAVIOR_CORK is now incorporated into the driver by default."));
+
+  case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE:
+      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                                 memcached_literal_param("MEMCACHED_BEHAVIOR_LOAD_FROM_FILE can not be set with memcached_behavior_set()"));
+
+  case MEMCACHED_BEHAVIOR_MAX:
+  default:
+      /* Shouldn't get here */
+      assert_msg(0, "Invalid behavior passed to memcached_behavior_set()");
+      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                                 memcached_literal_param("Invalid behavior passed to memcached_behavior_set()"));
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+bool _is_auto_eject_host(const memcached_st *ptr)
+{
+  return ptr->flags.auto_eject_hosts;
+}
+
+uint64_t memcached_behavior_get(memcached_st *shell,
+                                const memcached_behavior_t flag)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  if (ptr == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  switch (flag)
+  {
+  case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
+    return ptr->number_of_replicas;
+
+  case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK:
+    return ptr->io_msg_watermark;
+
+  case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK:
+    return ptr->io_bytes_watermark;
+
+  case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH:
+    return ptr->io_key_prefetch;
+
+  case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL:
+    return ptr->flags.binary_protocol;
+
+  case MEMCACHED_BEHAVIOR_SUPPORT_CAS:
+    return ptr->flags.support_cas;
+
+  case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS:
+    return true;
+
+  case MEMCACHED_BEHAVIOR_NO_BLOCK:
+    return ptr->flags.no_block;
+
+  case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS:
+    return ptr->flags.buffer_requests;
+
+  case MEMCACHED_BEHAVIOR_USE_UDP:
+    return memcached_is_udp(ptr);
+
+  case MEMCACHED_BEHAVIOR_TCP_NODELAY:
+    return ptr->flags.tcp_nodelay;
+
+  case MEMCACHED_BEHAVIOR_VERIFY_KEY:
+    return ptr->flags.verify_key;
+
+  case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED:
+    if (memcached_is_consistent_distribution(ptr))
+    {
+      return memcached_is_weighted_ketama(ptr);
+    }
+    return false;
+
+  case MEMCACHED_BEHAVIOR_DISTRIBUTION:
+    return ptr->distribution;
+
+  case MEMCACHED_BEHAVIOR_KETAMA:
+    return memcached_is_consistent_distribution(ptr);
+
+  case MEMCACHED_BEHAVIOR_HASH:
+    return hashkit_get_function(&ptr->hashkit);
+
+  case MEMCACHED_BEHAVIOR_KETAMA_HASH:
+    return hashkit_get_function(&ptr->hashkit);
+
+  case MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS:
+    return ptr->flags.auto_eject_hosts;
+
+  case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
+    return ptr->server_failure_limit;
+
+  case MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT:
+    return ptr->server_timeout_limit;
+
+  case MEMCACHED_BEHAVIOR_SORT_HOSTS:
+    return ptr->flags.use_sort_hosts;
+
+  case MEMCACHED_BEHAVIOR_POLL_TIMEOUT:
+    return (uint64_t)ptr->poll_timeout;
+
+  case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT:
+    return (uint64_t)ptr->connect_timeout;
+
+  case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT:
+    return (uint64_t)ptr->retry_timeout;
+
+  case MEMCACHED_BEHAVIOR_DEAD_TIMEOUT:
+    return uint64_t(ptr->dead_timeout);
+
+  case MEMCACHED_BEHAVIOR_SND_TIMEOUT:
+    return (uint64_t)ptr->snd_timeout;
+
+  case MEMCACHED_BEHAVIOR_RCV_TIMEOUT:
+    return (uint64_t)ptr->rcv_timeout;
+
+  case MEMCACHED_BEHAVIOR_TCP_KEEPIDLE:
+    return (uint64_t)ptr->tcp_keepidle;
+
+  case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE:
+    {
+      int sock_size= 0;
+      socklen_t sock_length= sizeof(int);
+
+      if (ptr->send_size != -1) // If value is -1 then we are using the default
+      {
+        return (uint64_t) ptr->send_size;
+      }
+
+      memcached_instance_st* instance= memcached_instance_fetch(ptr, 0);
+
+      if (instance) // If we have an instance we test, otherwise we just set and pray
+      {
+        /* REFACTOR */
+        /* We just try the first host, and if it is down we return zero */
+        if (memcached_failed(memcached_connect(instance)))
+        {
+          return 0;
+        }
+
+        if (memcached_failed(memcached_io_wait_for_write(instance)))
+        {
+          return 0;
+        }
+
+        if (getsockopt(instance->fd, SOL_SOCKET, SO_SNDBUF, (char*)&sock_size, &sock_length) < 0)
+        {
+          memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
+          return 0; /* Zero means error */
+        }
+      }
+
+      return (uint64_t) sock_size;
+    }
+
+  case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE:
+    {
+      int sock_size= 0;
+      socklen_t sock_length= sizeof(int);
+
+      if (ptr->recv_size != -1) // If value is -1 then we are using the default
+        return (uint64_t) ptr->recv_size;
+
+      memcached_instance_st* instance= memcached_instance_fetch(ptr, 0);
+
+      /**
+        @note REFACTOR
+      */
+      if (instance)
+      {
+        /* We just try the first host, and if it is down we return zero */
+        if (memcached_failed(memcached_connect(instance)))
+        {
+          return 0;
+        }
+
+        if (memcached_failed(memcached_io_wait_for_write(instance)))
+        {
+          return 0;
+        }
+
+        if (getsockopt(instance->fd, SOL_SOCKET, SO_RCVBUF, (char*)&sock_size, &sock_length) < 0)
+        {
+          memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
+          return 0; /* Zero means error */
+        }
+      }
+
+      return (uint64_t) sock_size;
+    }
+
+  case MEMCACHED_BEHAVIOR_USER_DATA:
+    memcached_set_error(*ptr, MEMCACHED_DEPRECATED, MEMCACHED_AT,
+                        memcached_literal_param("MEMCACHED_BEHAVIOR_USER_DATA deprecated."));
+    return 0;
+
+  case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY:
+    return ptr->flags.hash_with_namespace;
+
+  case MEMCACHED_BEHAVIOR_NOREPLY:
+    return ptr->flags.reply ? false : true;
+
+  case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
+    return ptr->flags.auto_eject_hosts;
+
+  case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ:
+    return ptr->flags.randomize_replica_read;
+
+  case MEMCACHED_BEHAVIOR_CORK:
+#ifdef HAVE_MSG_MORE
+    return true;
+#else
+    return false;
+#endif
+
+  case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE:
+    return ptr->flags.tcp_keepalive;
+
+  case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE:
+    return bool(memcached_parse_filename(ptr));
+
+  case MEMCACHED_BEHAVIOR_MAX:
+  default:
+    assert_msg(0, "Invalid behavior passed to memcached_behavior_get()");
+    return 0;
+  }
+
+  /* NOTREACHED */
+}
+
+
+memcached_return_t memcached_behavior_set_distribution(memcached_st *shell, memcached_server_distribution_t type)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  if (ptr)
+  {
+    switch (type)
+    {
+    case MEMCACHED_DISTRIBUTION_MODULA:
+      break;
+
+    case MEMCACHED_DISTRIBUTION_CONSISTENT:
+    case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
+      memcached_set_weighted_ketama(ptr, false);
+      break;
+
+    case MEMCACHED_DISTRIBUTION_RANDOM:
+      break;
+
+    case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
+      break;
+
+    case MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED:
+      memcached_set_weighted_ketama(ptr, true);
+      break;
+
+    case MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET:
+      break;
+
+    default:
+    case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX:
+      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                                 memcached_literal_param("Invalid memcached_server_distribution_t"));
+    }
+    ptr->distribution= type;
+
+    return run_distribution(ptr);
+  }
+
+  return MEMCACHED_INVALID_ARGUMENTS;
+}
+
+
+memcached_server_distribution_t memcached_behavior_get_distribution(memcached_st *shell)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  if (ptr)
+  {
+    return ptr->distribution;
+  }
+
+  return MEMCACHED_DISTRIBUTION_CONSISTENT_MAX;
+}
+
+memcached_return_t memcached_behavior_set_key_hash(memcached_st *shell, memcached_hash_t type)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  if (ptr)
+  {
+    if (hashkit_success(hashkit_set_function(&ptr->hashkit, (hashkit_hash_algorithm_t)type)))
+    {
+      return MEMCACHED_SUCCESS;
+    }
+
+    return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                               memcached_literal_param("Invalid memcached_hash_t()"));
+  }
+
+  return MEMCACHED_INVALID_ARGUMENTS;
+}
+
+memcached_hash_t memcached_behavior_get_key_hash(memcached_st *shell)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  if (ptr)
+  {
+    return (memcached_hash_t)hashkit_get_function(&ptr->hashkit);
+  }
+
+  return MEMCACHED_HASH_MAX;
+}
+
+memcached_return_t memcached_behavior_set_distribution_hash(memcached_st *shell, memcached_hash_t type)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  if (ptr)
+  {
+    if (hashkit_success(hashkit_set_distribution_function(&ptr->hashkit, (hashkit_hash_algorithm_t)type)))
+    {
+      return MEMCACHED_SUCCESS;
+    }
+
+    return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                               memcached_literal_param("Invalid memcached_hash_t()"));
+  }
+
+  return MEMCACHED_INVALID_ARGUMENTS;
+}
+
+memcached_hash_t memcached_behavior_get_distribution_hash(memcached_st *shell)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  if (ptr)
+  {
+    return (memcached_hash_t)hashkit_get_function(&ptr->hashkit);
+  }
+
+  return MEMCACHED_HASH_MAX;
+}
+
+const char *libmemcached_string_behavior(const memcached_behavior_t flag)
+{
+  switch (flag)
+  {
+  case MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT: return "MEMCACHED_BEHAVIOR_SERVER_TIMEOUT_LIMIT";
+  case MEMCACHED_BEHAVIOR_NO_BLOCK: return "MEMCACHED_BEHAVIOR_NO_BLOCK";
+  case MEMCACHED_BEHAVIOR_TCP_NODELAY: return "MEMCACHED_BEHAVIOR_TCP_NODELAY";
+  case MEMCACHED_BEHAVIOR_HASH: return "MEMCACHED_BEHAVIOR_HASH";
+  case MEMCACHED_BEHAVIOR_KETAMA: return "MEMCACHED_BEHAVIOR_KETAMA";
+  case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE: return "MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE";
+  case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE: return "MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE";
+  case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS: return "MEMCACHED_BEHAVIOR_CACHE_LOOKUPS";
+  case MEMCACHED_BEHAVIOR_SUPPORT_CAS: return "MEMCACHED_BEHAVIOR_SUPPORT_CAS";
+  case MEMCACHED_BEHAVIOR_POLL_TIMEOUT: return "MEMCACHED_BEHAVIOR_POLL_TIMEOUT";
+  case MEMCACHED_BEHAVIOR_DISTRIBUTION: return "MEMCACHED_BEHAVIOR_DISTRIBUTION";
+  case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS: return "MEMCACHED_BEHAVIOR_BUFFER_REQUESTS";
+  case MEMCACHED_BEHAVIOR_USER_DATA: return "MEMCACHED_BEHAVIOR_USER_DATA";
+  case MEMCACHED_BEHAVIOR_SORT_HOSTS: return "MEMCACHED_BEHAVIOR_SORT_HOSTS";
+  case MEMCACHED_BEHAVIOR_VERIFY_KEY: return "MEMCACHED_BEHAVIOR_VERIFY_KEY";
+  case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT: return "MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT";
+  case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT: return "MEMCACHED_BEHAVIOR_RETRY_TIMEOUT";
+  case MEMCACHED_BEHAVIOR_DEAD_TIMEOUT: return "MEMCACHED_BEHAVIOR_DEAD_TIMEOUT";
+  case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED: return "MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED";
+  case MEMCACHED_BEHAVIOR_KETAMA_HASH: return "MEMCACHED_BEHAVIOR_KETAMA_HASH";
+  case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL: return "MEMCACHED_BEHAVIOR_BINARY_PROTOCOL";
+  case MEMCACHED_BEHAVIOR_SND_TIMEOUT: return "MEMCACHED_BEHAVIOR_SND_TIMEOUT";
+  case MEMCACHED_BEHAVIOR_RCV_TIMEOUT: return "MEMCACHED_BEHAVIOR_RCV_TIMEOUT";
+  case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT: return "MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT";
+  case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK: return "MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK";
+  case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK: return "MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK";
+  case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH: return "MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH";
+  case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY: return "MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY";
+  case MEMCACHED_BEHAVIOR_NOREPLY: return "MEMCACHED_BEHAVIOR_NOREPLY";
+  case MEMCACHED_BEHAVIOR_USE_UDP: return "MEMCACHED_BEHAVIOR_USE_UDP";
+  case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS: return "MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS";
+  case MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS: return "MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS";
+  case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS: return "MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS";
+  case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ: return "MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ";
+  case MEMCACHED_BEHAVIOR_CORK: return "MEMCACHED_BEHAVIOR_CORK";
+  case MEMCACHED_BEHAVIOR_TCP_KEEPALIVE: return "MEMCACHED_BEHAVIOR_TCP_KEEPALIVE";
+  case MEMCACHED_BEHAVIOR_TCP_KEEPIDLE: return "MEMCACHED_BEHAVIOR_TCP_KEEPIDLE";
+  case MEMCACHED_BEHAVIOR_LOAD_FROM_FILE: return "MEMCACHED_BEHAVIOR_LOAD_FROM_FILE";
+  default:
+  case MEMCACHED_BEHAVIOR_MAX: return "INVALID memcached_behavior_t";
+  }
+}
+
+const char *libmemcached_string_distribution(const memcached_server_distribution_t flag)
+{
+  switch (flag)
+  {
+  case MEMCACHED_DISTRIBUTION_MODULA: return "MEMCACHED_DISTRIBUTION_MODULA";
+  case MEMCACHED_DISTRIBUTION_CONSISTENT: return "MEMCACHED_DISTRIBUTION_CONSISTENT";
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA: return "MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA";
+  case MEMCACHED_DISTRIBUTION_RANDOM: return "MEMCACHED_DISTRIBUTION_RANDOM";
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY: return "MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY";
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED: return "MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED";
+  case MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET: return "MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET";
+  default:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX: return "INVALID memcached_server_distribution_t";
+  }
+}
+
+memcached_return_t memcached_bucket_set(memcached_st *shell,
+                                        const uint32_t *host_map,
+                                        const uint32_t *forward_map,
+                                        const uint32_t buckets,
+                                        const uint32_t replicas)
+{
+  Memcached* self= memcached2Memcached(shell);
+  memcached_return_t rc;
+
+  if (self == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  if (host_map == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  memcached_server_distribution_t old= memcached_behavior_get_distribution(self);
+
+  if (memcached_failed(rc =memcached_behavior_set_distribution(self, MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET)))
+  {
+    return rc;
+  }
+
+  if (memcached_failed(rc= memcached_virtual_bucket_create(self, host_map, forward_map, buckets, replicas)))
+  {
+    memcached_behavior_set_distribution(self, old);
+  }
+
+  return rc;
+}
diff --git a/src/libmemcached/behavior.hpp b/src/libmemcached/behavior.hpp
new file mode 100644 (file)
index 0000000..0b06c0c
--- /dev/null
@@ -0,0 +1,40 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+bool memcached_is_consistent_distribution(const memcached_st*);
+bool _is_auto_eject_host(const memcached_st *ptr);
diff --git a/src/libmemcached/byteorder.cc b/src/libmemcached/byteorder.cc
new file mode 100644 (file)
index 0000000..44500ad
--- /dev/null
@@ -0,0 +1,82 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "mem_config.h"
+#include "libmemcached/byteorder.h"
+
+/* Byte swap a 64-bit number. */
+#ifndef swap64
+static inline uint64_t swap64(uint64_t in)
+{
+#ifndef WORDS_BIGENDIAN
+  /* Little endian, flip the bytes around until someone makes a faster/better
+   * way to do this. */
+  uint64_t rv= 0;
+  for (uint8_t x= 0; x < 8; ++x)
+  {
+    rv= (rv << 8) | (in & 0xff);
+    in >>= 8;
+  }
+  return rv;
+#else
+  /* big-endian machines don't need byte swapping */
+  return in;
+#endif // WORDS_BIGENDIAN
+}
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+uint64_t memcached_ntohll(uint64_t value)
+{
+#ifdef HAVE_HTONLL
+  return ntohll(value);
+#else
+  return swap64(value);
+#endif
+}
+
+uint64_t memcached_htonll(uint64_t value)
+{
+#ifdef HAVE_HTONLL
+  return htonll(value);
+#else
+  return swap64(value);
+#endif
+}
diff --git a/src/libmemcached/byteorder.h b/src/libmemcached/byteorder.h
new file mode 100644 (file)
index 0000000..a7d108d
--- /dev/null
@@ -0,0 +1,50 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+uint64_t memcached_ntohll(uint64_t);
+
+uint64_t memcached_htonll(uint64_t);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/libmemcached/callback.cc b/src/libmemcached/callback.cc
new file mode 100644 (file)
index 0000000..a43eef9
--- /dev/null
@@ -0,0 +1,160 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Change any of the possible callbacks.
+ *
+ */
+
+#include <libmemcached/common.h>
+#include <sys/types.h>
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif
+
+/*
+  These functions provide data and function callback support
+*/
+
+memcached_return_t memcached_callback_set(memcached_st *shell,
+                                          const memcached_callback_t flag,
+                                          const void *data)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  if (ptr)
+  {
+    switch (flag)
+    {
+    case MEMCACHED_CALLBACK_PREFIX_KEY:
+      {
+        return memcached_set_namespace(*ptr, (char*)data, data ? strlen((char*)data) : 0);
+      }
+
+    case MEMCACHED_CALLBACK_USER_DATA:
+      {
+        ptr->user_data= const_cast<void *>(data);
+        break;
+      }
+
+    case MEMCACHED_CALLBACK_CLEANUP_FUNCTION:
+      {
+        memcached_cleanup_fn func= *(memcached_cleanup_fn *)&data;
+        ptr->on_cleanup= func;
+        break;
+      }
+
+    case MEMCACHED_CALLBACK_CLONE_FUNCTION:
+      {
+        memcached_clone_fn func= *(memcached_clone_fn *)&data;
+        ptr->on_clone= func;
+        break;
+      }
+
+    case MEMCACHED_CALLBACK_GET_FAILURE:
+      {
+        memcached_trigger_key_fn func= *(memcached_trigger_key_fn *)&data;
+        ptr->get_key_failure= func;
+        break;
+      }
+
+    case MEMCACHED_CALLBACK_DELETE_TRIGGER:
+      {
+        if (data) // NULL would mean we are disabling.
+        {
+          if (memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS)) 
+          {
+            return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Delete triggers cannot be used if buffering is enabled"));
+          }
+
+          if (memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_NOREPLY)) 
+          {
+            return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Delete triggers cannot be used if MEMCACHED_BEHAVIOR_NOREPLY is set"));
+          }
+        }
+
+        memcached_trigger_delete_key_fn func= *(memcached_trigger_delete_key_fn *)&data;
+        ptr->delete_trigger= func;
+        break;
+      }
+
+    case MEMCACHED_CALLBACK_MAX:
+      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid callback supplied"));
+    }
+
+    return MEMCACHED_SUCCESS;
+  }
+
+  return MEMCACHED_INVALID_ARGUMENTS;
+}
+
+void *memcached_callback_get(memcached_st *shell,
+                             const memcached_callback_t flag,
+                             memcached_return_t *error)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  memcached_return_t local_error;
+  if (error == NULL)
+  {
+    error = &local_error;
+  }
+
+  if (ptr == NULL)
+  {
+    *error= MEMCACHED_INVALID_ARGUMENTS;
+    return NULL;
+  }
+
+  switch (flag)
+  {
+  case MEMCACHED_CALLBACK_PREFIX_KEY:
+    {
+      *error= MEMCACHED_SUCCESS;
+      if (ptr->_namespace)
+      {
+        return (void *)memcached_array_string(ptr->_namespace);
+      }
+      return NULL;
+    }
+
+  case MEMCACHED_CALLBACK_USER_DATA:
+    {
+      *error= ptr->user_data ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+      return (void *)ptr->user_data;
+    }
+
+  case MEMCACHED_CALLBACK_CLEANUP_FUNCTION:
+    {
+      *error= ptr->on_cleanup ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+      return *(void **)&ptr->on_cleanup;
+    }
+
+  case MEMCACHED_CALLBACK_CLONE_FUNCTION:
+    {
+      *error= ptr->on_clone ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+      return *(void **)&ptr->on_clone;
+    }
+
+  case MEMCACHED_CALLBACK_GET_FAILURE:
+    {
+      *error= ptr->get_key_failure ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+      return *(void **)&ptr->get_key_failure;
+    }
+
+  case MEMCACHED_CALLBACK_DELETE_TRIGGER:
+    {
+      *error= ptr->delete_trigger ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+      return *(void **)&ptr->delete_trigger;
+    }
+
+  case MEMCACHED_CALLBACK_MAX:
+    break;
+  }
+
+  assert_msg(0, "Invalid callback passed to memcached_callback_get()");
+  *error= MEMCACHED_FAILURE;
+  return NULL;
+}
diff --git a/src/libmemcached/callback.h b/src/libmemcached/callback.h
new file mode 100644 (file)
index 0000000..3949ea3
--- /dev/null
@@ -0,0 +1,42 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached Client and Server 
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+test_return_t test_MEMCACHED_CALLBACK_DELETE_TRIGGER(memcached_st *);
+
+test_return_t test_MEMCACHED_CALLBACK_DELETE_TRIGGER_and_MEMCACHED_BEHAVIOR_NOREPLY(memcached_st *);
diff --git a/src/libmemcached/common.h b/src/libmemcached/common.h
new file mode 100644 (file)
index 0000000..8cedc52
--- /dev/null
@@ -0,0 +1,222 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+  Common include file for libmemached
+*/
+
+#pragma once
+
+#include <mem_config.h>
+
+#ifdef __cplusplus
+# include <cstddef>
+# include <cstdio>
+# include <cstdlib>
+# include <cstring>
+# include <ctime>
+# include <cctype>
+# include <cerrno>
+# include <climits>
+#else
+# ifdef HAVE_STDDEF_H
+#  include <stddef.h>
+# endif
+# ifdef HAVE_STDLIB_H
+#  include <stdio.h>
+# endif
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+# include <string.h>
+# ifdef HAVE_TIME_H
+#  include <time.h>
+# endif
+# ifdef HAVE_ERRNO_H
+#  include <errno.h>
+# endif
+# ifdef HAVE_LIMITS_H
+#  include <limits.h>
+# endif
+#endif
+
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#ifdef HAVE_DLFCN_H
+# include <dlfcn.h>
+#endif
+
+#if defined(_WIN32)
+# include "libmemcached/windows.hpp"
+#endif
+
+#include <libmemcached-1.0/memcached.h>
+#include "libmemcached/watchpoint.h"
+#include "libmemcached/is.h"
+typedef struct memcached_st Memcached;
+
+#ifdef HAVE_POLL_H
+# include <poll.h>
+#else
+# include "libmemcached/poll.h"
+#endif
+
+#ifdef __cplusplus
+memcached_instance_st* memcached_instance_fetch(memcached_st *ptr, uint32_t server_key);
+#endif
+
+/* These are private not to be installed headers */
+#include "libmemcached/error.hpp"
+#include "libmemcached/memory.h"
+#include "libmemcached/io.h"
+#ifdef __cplusplus
+# include "libmemcached/string.hpp"
+# include "libmemcachedprotocol-0.0/binary.h"
+# include "libmemcached/io.hpp"
+# include "libmemcached/udp.hpp"
+# include "libmemcached/do.hpp"
+# include "libmemcached/socket.hpp"
+# include "libmemcached/connect.hpp"
+# include "libmemcached/allocators.hpp"
+# include "libmemcached/hash.hpp"
+# include "libmemcached/quit.hpp"
+# include "libmemcached/instance.hpp"
+# include "libmemcached/server_instance.h"
+# include "libmemcached/server.hpp"
+# include "libmemcached/flag.hpp"
+# include "libmemcached/behavior.hpp"
+# include "libmemcached/sasl.hpp"
+# include "libmemcached/server_list.hpp"
+#endif
+
+#include "libmemcached/internal.h"
+#include "libmemcached/array.h"
+#include "libmemcached/libmemcached_probes.h"
+#include "libmemcached/byteorder.h"
+#include "libmemcached/initialize_query.h"
+
+#ifdef __cplusplus
+# include "libmemcached/response.h"
+# include "libmemcached/namespace.h"
+#else
+# include "libmemcached/virtual_bucket.h"
+#endif
+
+#ifdef __cplusplus
+# include "libmemcached/backtrace.hpp"
+# include "libmemcached/assert.hpp"
+# include "libmemcached/server.hpp"
+# include "libmemcached/key.hpp"
+# include "libmemcached/encoding_key.h"
+# include "libmemcached/result.h"
+# include "libmemcached/version.hpp"
+#endif
+
+#include "libmemcached/continuum.hpp"
+
+#if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
+
+#define likely(x)       if((x))
+#define unlikely(x)     if((x))
+
+#else
+
+#define likely(x)       if(__builtin_expect((x) != 0, 1))
+#define unlikely(x)     if(__builtin_expect((x) != 0, 0))
+#endif
+
+#define MEMCACHED_BLOCK_SIZE 1024
+#define MEMCACHED_DEFAULT_COMMAND_SIZE 350
+#define SMALL_STRING_LEN 1024
+#define HUGE_STRING_LEN 8196
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+memcached_return_t run_distribution(memcached_st *ptr);
+
+#ifdef __cplusplus
+static inline void memcached_server_response_increment(memcached_instance_st* instance)
+{
+  instance->events(POLLIN);
+  instance->cursor_active_++;
+}
+#endif
+
+#define memcached_server_response_decrement(A) (A)->cursor_active_--
+#define memcached_server_response_reset(A) (A)->cursor_active_=0
+
+#define memcached_instance_response_increment(A) (A)->cursor_active_++
+#define memcached_instance_response_decrement(A) (A)->cursor_active_--
+#define memcached_instance_response_reset(A) (A)->cursor_active_=0
+
+#ifdef __cplusplus
+}
+#endif
+
+#ifdef __cplusplus
+bool memcached_purge(memcached_instance_st*);
+memcached_instance_st* memcached_instance_by_position(const memcached_st *ptr, uint32_t server_key);
+#endif
diff --git a/src/libmemcached/connect.cc b/src/libmemcached/connect.cc
new file mode 100644 (file)
index 0000000..1cfe794
--- /dev/null
@@ -0,0 +1,818 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libmemcached/common.h>
+
+#include <cassert>
+
+#ifndef SOCK_CLOEXEC 
+#  define SOCK_CLOEXEC 0
+#endif
+
+#ifndef SOCK_NONBLOCK 
+# define SOCK_NONBLOCK 0
+#endif
+
+#ifndef FD_CLOEXEC
+# define FD_CLOEXEC 0
+#endif
+
+#ifndef SO_NOSIGPIPE
+# define SO_NOSIGPIPE 0
+#endif
+
+#ifndef TCP_NODELAY
+# define TCP_NODELAY 0
+#endif
+
+#ifndef TCP_KEEPIDLE
+# define TCP_KEEPIDLE 0
+#endif
+
+static memcached_return_t connect_poll(memcached_instance_st* server, const int connection_error)
+{
+  struct pollfd fds[1];
+  fds[0].fd= server->fd;
+  fds[0].events= server->events();
+  fds[0].revents= 0;
+
+  size_t loop_max= 5;
+
+  if (server->root->poll_timeout == 0)
+  {
+    return memcached_set_error(*server, MEMCACHED_TIMEOUT, MEMCACHED_AT,
+                               memcached_literal_param("The time to wait for a connection to be established was set to zero which produces a timeout to every call to poll()."));
+  }
+
+  while (--loop_max) // Should only loop on cases of ERESTART or EINTR
+  {
+    int number_of;
+    if ((number_of= poll(fds, 1, server->root->connect_timeout)) == -1)
+    {
+      int local_errno= get_socket_errno(); // We cache in case closesocket() modifies errno
+      switch (local_errno)
+      {
+#ifdef __linux__
+      case ERESTART:
+#endif
+      case EINTR:
+        continue;
+
+      case EFAULT:
+      case ENOMEM:
+        return memcached_set_error(*server, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+
+      case EINVAL:
+        return memcached_set_error(*server, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT,
+                                   memcached_literal_param("RLIMIT_NOFILE exceeded, or if OSX the timeout value was invalid"));
+
+      default: // This should not happen
+        break;
+      }
+
+      assert_msg(server->fd != INVALID_SOCKET, "poll() was passed an invalid file descriptor");
+      server->reset_socket();
+      server->state= MEMCACHED_SERVER_STATE_NEW;
+
+      return memcached_set_errno(*server, local_errno, MEMCACHED_AT);
+    }
+
+    if (number_of == 0)
+    {
+      if (connection_error == EINPROGRESS)
+      {
+        int err;
+        socklen_t len= sizeof(err);
+        if (getsockopt(server->fd, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == -1)
+        {
+          return memcached_set_errno(*server, errno, MEMCACHED_AT, memcached_literal_param("getsockopt() error'ed while looking for error connect_poll(EINPROGRESS)"));
+        }
+
+        // If Zero, my hero, we just fail to a generic MEMCACHED_TIMEOUT error
+        if (err != 0)
+        {
+          return memcached_set_errno(*server, err, MEMCACHED_AT, memcached_literal_param("getsockopt() found the error from poll() after connect() returned EINPROGRESS."));
+        }
+      }
+
+      return  memcached_set_error(*server, MEMCACHED_TIMEOUT, MEMCACHED_AT, memcached_literal_param("(number_of == 0)"));
+    }
+
+    assert (number_of == 1);
+
+    if (fds[0].revents & POLLERR or
+        fds[0].revents & POLLHUP or 
+        fds[0].revents & POLLNVAL)
+    {
+      int err;
+      socklen_t len= sizeof (err);
+      if (getsockopt(fds[0].fd, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == -1)
+      {
+        return memcached_set_errno(*server, errno, MEMCACHED_AT, memcached_literal_param("getsockopt() errored while looking up error state from poll()"));
+      }
+
+      // We check the value to see what happened with the socket.
+      if (err == 0) // Should not happen
+      {
+        return MEMCACHED_SUCCESS;
+      }
+      errno= err;
+
+      return memcached_set_errno(*server, err, MEMCACHED_AT, memcached_literal_param("getsockopt() found the error from poll() during connect."));
+    }
+    assert(fds[0].revents & POLLOUT);
+
+    if (fds[0].revents & POLLOUT and connection_error == EINPROGRESS)
+    {
+      int err;
+      socklen_t len= sizeof(err);
+      if (getsockopt(server->fd, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == -1)
+      {
+        return memcached_set_errno(*server, errno, MEMCACHED_AT);
+      }
+
+      if (err == 0)
+      {
+        return MEMCACHED_SUCCESS;
+      }
+
+      return memcached_set_errno(*server, err, MEMCACHED_AT, memcached_literal_param("getsockopt() found the error from poll() after connect() returned EINPROGRESS."));
+    }
+
+    break; // We only have the loop setup for errno types that require restart
+  }
+
+  // This should only be possible from ERESTART or EINTR;
+  return memcached_set_errno(*server, connection_error, MEMCACHED_AT, memcached_literal_param("connect_poll() was exhausted"));
+}
+
+static memcached_return_t set_hostinfo(memcached_instance_st* server)
+{
+  assert(server->type != MEMCACHED_CONNECTION_UNIX_SOCKET);
+  server->clear_addrinfo();
+
+  char str_port[MEMCACHED_NI_MAXSERV]= { 0 };
+  errno= 0;
+  int length= snprintf(str_port, MEMCACHED_NI_MAXSERV, "%u", uint32_t(server->port()));
+  if (length >= MEMCACHED_NI_MAXSERV or length <= 0 or errno != 0)
+  {
+    return memcached_set_error(*server, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                               memcached_literal_param("snprintf(NI_MAXSERV)"));
+  }
+
+  struct addrinfo hints;
+  memset(&hints, 0, sizeof(struct addrinfo));
+
+  hints.ai_family= AF_UNSPEC;
+  if (memcached_is_udp(server->root))
+  {
+    hints.ai_protocol= IPPROTO_UDP;
+    hints.ai_socktype= SOCK_DGRAM;
+  }
+  else
+  {
+    hints.ai_socktype= SOCK_STREAM;
+    hints.ai_protocol= IPPROTO_TCP;
+  }
+
+  assert(server->address_info == NULL);
+  assert(server->address_info_next == NULL);
+  int errcode;
+  assert(server->hostname());
+  switch(errcode= getaddrinfo(server->hostname(), str_port, &hints, &server->address_info))
+  {
+  case 0:
+    server->address_info_next= server->address_info;
+    server->state= MEMCACHED_SERVER_STATE_ADDRINFO;
+    break;
+
+  case EAI_AGAIN:
+    return memcached_set_error(*server, MEMCACHED_TIMEOUT, MEMCACHED_AT, memcached_string_make_from_cstr(gai_strerror(errcode)));
+
+  case EAI_SYSTEM:
+    server->clear_addrinfo();
+    return memcached_set_errno(*server, errno, MEMCACHED_AT, memcached_literal_param("getaddrinfo(EAI_SYSTEM)"));
+
+  case EAI_BADFLAGS:
+    server->clear_addrinfo();
+    return memcached_set_error(*server, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("getaddrinfo(EAI_BADFLAGS)"));
+
+  case EAI_MEMORY:
+    server->clear_addrinfo();
+    return memcached_set_error(*server, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, memcached_literal_param("getaddrinfo(EAI_MEMORY)"));
+
+  default:
+    {
+      server->clear_addrinfo();
+      return memcached_set_error(*server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT, memcached_string_make_from_cstr(gai_strerror(errcode)));
+    }
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+static inline void set_socket_nonblocking(memcached_instance_st* server)
+{
+#if defined(_WIN32)
+  u_long arg= 1;
+  if (ioctlsocket(server->fd, FIONBIO, &arg) == SOCKET_ERROR)
+  {
+    memcached_set_errno(*server, get_socket_errno(), NULL);
+  }
+#else
+  int flags;
+
+  if (SOCK_NONBLOCK == 0)
+  {
+    do
+    {
+      flags= fcntl(server->fd, F_GETFL, 0);
+    } while (flags == -1 && (errno == EINTR || errno == EAGAIN));
+
+    if (flags == -1)
+    {
+      memcached_set_errno(*server, errno, NULL);
+    }
+    else if ((flags & O_NONBLOCK) == 0)
+    {
+      int rval;
+
+      do
+      {
+        rval= fcntl(server->fd, F_SETFL, flags | O_NONBLOCK);
+      } while (rval == -1 && (errno == EINTR or errno == EAGAIN));
+
+      if (rval == -1)
+      {
+        memcached_set_errno(*server, errno, NULL);
+      }
+    }
+  }
+#endif
+}
+
+static bool set_socket_options(memcached_instance_st* server)
+{
+  assert_msg(server->fd != INVALID_SOCKET, "invalid socket was passed to set_socket_options()");
+
+#ifdef HAVE_FCNTL
+  // If SOCK_CLOEXEC exists then we don't need to call the following
+  if (SOCK_CLOEXEC == 0)
+  {
+    if (FD_CLOEXEC != 0)
+    {
+      int flags;
+      do
+      { 
+        flags= fcntl(server->fd, F_GETFD, 0);
+      } while (flags == -1 and (errno == EINTR or errno == EAGAIN));
+
+      if (flags != -1)
+      { 
+        int rval;
+        do
+        { 
+          rval= fcntl (server->fd, F_SETFD, flags | FD_CLOEXEC);
+        } while (rval == -1 && (errno == EINTR or errno == EAGAIN));
+        // we currently ignore the case where rval is -1
+      }
+    }
+  }
+#endif
+
+  if (memcached_is_udp(server->root))
+  {
+    return true;
+  }
+
+#ifdef HAVE_SNDTIMEO
+  if (server->root->snd_timeout > 0)
+  {
+    struct timeval waittime;
+
+    waittime.tv_sec= server->root->snd_timeout / 1000000;
+    waittime.tv_usec= server->root->snd_timeout % 1000000;
+
+    int error= setsockopt(server->fd, SOL_SOCKET, SO_SNDTIMEO,
+                          (char*)&waittime, (socklen_t)sizeof(struct timeval));
+    (void)error;
+    assert(error == 0);
+  }
+#endif
+
+#ifdef HAVE_RCVTIMEO
+  if (server->root->rcv_timeout > 0)
+  {
+    struct timeval waittime;
+
+    waittime.tv_sec= server->root->rcv_timeout / 1000000;
+    waittime.tv_usec= server->root->rcv_timeout % 1000000;
+
+    int error= setsockopt(server->fd, SOL_SOCKET, SO_RCVTIMEO,
+                          (char*)&waittime, (socklen_t)sizeof(struct timeval));
+    (void)(error);
+    assert(error == 0);
+  }
+#endif
+
+
+#if defined(_WIN32)
+#else
+# if defined(SO_NOSIGPIPE)
+  if (SO_NOSIGPIPE)
+  {
+    int set= 1;
+    int error= setsockopt(server->fd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
+
+    assert(error == 0);
+
+    // This is not considered a fatal error
+    if (error == -1)
+    {
+#if 0
+      perror("setsockopt(SO_NOSIGPIPE)");
+#endif
+    }
+  }
+# endif // SO_NOSIGPIPE
+#endif // _WIN32
+
+  if (server->root->flags.no_block)
+  {
+    struct linger linger;
+
+    linger.l_onoff= 1;
+    linger.l_linger= 0; /* By default on close() just drop the socket */
+    int error= setsockopt(server->fd, SOL_SOCKET, SO_LINGER,
+                          (char*)&linger, (socklen_t)sizeof(struct linger));
+    (void)(error);
+    assert(error == 0);
+  }
+
+  if (TCP_NODELAY)
+  {
+    if (server->root->flags.tcp_nodelay)
+    {
+      int flag= 1;
+
+      int error= setsockopt(server->fd, IPPROTO_TCP, TCP_NODELAY,
+                            (char*)&flag, (socklen_t)sizeof(int));
+      (void)(error);
+      assert(error == 0);
+    }
+  }
+
+  if (server->root->flags.tcp_keepalive)
+  {
+    int flag= 1;
+
+    int error= setsockopt(server->fd, SOL_SOCKET, SO_KEEPALIVE,
+                          (char*)&flag, (socklen_t)sizeof(int));
+    (void)(error);
+    assert(error == 0);
+  }
+
+  if (TCP_KEEPIDLE)
+  {
+    if (server->root->tcp_keepidle > 0)
+    {
+      int error= setsockopt(server->fd, IPPROTO_TCP, TCP_KEEPIDLE,
+                            (char*)&server->root->tcp_keepidle, (socklen_t)sizeof(int));
+      (void)(error);
+      assert(error == 0);
+    }
+  }
+
+  if (server->root->send_size > 0)
+  {
+    int error= setsockopt(server->fd, SOL_SOCKET, SO_SNDBUF,
+                          (char*)&server->root->send_size, (socklen_t)sizeof(int));
+    (void)(error);
+    assert(error == 0);
+  }
+
+  if (server->root->recv_size > 0)
+  {
+    int error= setsockopt(server->fd, SOL_SOCKET, SO_RCVBUF,
+                          (char*)&server->root->recv_size, (socklen_t)sizeof(int));
+    (void)(error);
+    assert(error == 0);
+  }
+
+  /* libmemcached will always use nonblocking IO to avoid write deadlocks */
+  set_socket_nonblocking(server);
+
+  return true;
+}
+
+static memcached_return_t unix_socket_connect(memcached_instance_st* server)
+{
+#ifndef _WIN32
+  WATCHPOINT_ASSERT(server->fd == INVALID_SOCKET);
+
+  do {
+    int type= SOCK_STREAM;
+    if (SOCK_CLOEXEC != 0)
+    {
+      type|= SOCK_CLOEXEC;
+    }
+
+    if (SOCK_NONBLOCK != 0)
+    {
+      type|= SOCK_NONBLOCK;
+    }
+
+    if ((server->fd= socket(AF_UNIX, type, 0)) == -1)
+    {
+      return memcached_set_errno(*server, errno, NULL);
+    }
+
+    struct sockaddr_un servAddr;
+
+    memset(&servAddr, 0, sizeof (struct sockaddr_un));
+    servAddr.sun_family= AF_UNIX;
+    if (strlen(server->hostname()) >= sizeof(servAddr.sun_path)) {
+        return memcached_set_error(*server, MEMCACHED_UNIX_SOCKET_PATH_TOO_BIG, MEMCACHED_AT);
+    }
+    strncpy(servAddr.sun_path, server->hostname(), sizeof(servAddr.sun_path)-1); /* Copy filename */
+
+    if (connect(server->fd, (struct sockaddr *)&servAddr, sizeof(servAddr)) == -1)
+    {
+      switch (errno)
+      {
+      case EINPROGRESS:
+      case EALREADY:
+      case EAGAIN:
+        server->events(POLLOUT);
+        break;
+
+      case EINTR:
+        server->reset_socket();
+        continue;
+
+      case EISCONN: /* We were spinning waiting on connect */
+        {
+          assert(0); // Programmer error
+          server->reset_socket();
+          continue;
+        }
+
+      default:
+        WATCHPOINT_ERRNO(errno);
+        server->reset_socket();
+        return memcached_set_errno(*server, errno, MEMCACHED_AT);
+      }
+    }
+  } while (0);
+  server->state= MEMCACHED_SERVER_STATE_CONNECTED;
+
+  WATCHPOINT_ASSERT(server->fd != INVALID_SOCKET);
+
+  return MEMCACHED_SUCCESS;
+#else
+  (void)server;
+  return MEMCACHED_NOT_SUPPORTED;
+#endif
+}
+
+static memcached_return_t network_connect(memcached_instance_st* server)
+{
+  bool timeout_error_occured= false;
+
+  WATCHPOINT_ASSERT(server->fd == INVALID_SOCKET);
+  WATCHPOINT_ASSERT(server->cursor_active_ == 0);
+
+  /*
+    We want to check both of these because if address_info_next has been fully tried, we want to do a new lookup to make sure we have picked up on any new DNS information.
+  */
+  if (server->address_info == NULL or server->address_info_next == NULL)
+  {
+    WATCHPOINT_ASSERT(server->state == MEMCACHED_SERVER_STATE_NEW);
+    server->address_info_next= NULL;
+    memcached_return_t rc= set_hostinfo(server);
+
+    if (memcached_failed(rc))
+    {
+      return rc;
+    }
+  }
+
+  assert(server->address_info_next);
+  assert(server->address_info);
+
+  /* Create the socket */
+  while (server->address_info_next and server->fd == INVALID_SOCKET)
+  {
+    int type= server->address_info_next->ai_socktype;
+    if (SOCK_CLOEXEC != 0)
+    {
+      type|= SOCK_CLOEXEC;
+    }
+
+    if (SOCK_NONBLOCK != 0)
+    {
+      type|= SOCK_NONBLOCK;
+    }
+
+    server->fd= socket(server->address_info_next->ai_family,
+                       type,
+                       server->address_info_next->ai_protocol);
+
+    if (int(server->fd) == SOCKET_ERROR)
+    {
+      return memcached_set_errno(*server, get_socket_errno(), NULL);
+    }
+
+    if (set_socket_options(server) == false)
+    {
+      server->reset_socket();
+      return MEMCACHED_CONNECTION_FAILURE;
+    }
+
+    /* connect to server */
+    if ((connect(server->fd, server->address_info_next->ai_addr, server->address_info_next->ai_addrlen) != SOCKET_ERROR))
+    {
+      server->state= MEMCACHED_SERVER_STATE_CONNECTED;
+      return MEMCACHED_SUCCESS;
+    }
+
+    /* An error occurred */
+    int local_error= get_socket_errno();
+    switch (local_error)
+    {
+    case ETIMEDOUT:
+      timeout_error_occured= true;
+      break;
+
+#if EWOULDBLOCK != EAGAIN
+    case EWOULDBLOCK:
+#endif
+    case EINPROGRESS: // nonblocking mode - first return
+    case EALREADY: // nonblocking mode - subsequent returns
+      {
+        server->events(POLLOUT);
+        server->state= MEMCACHED_SERVER_STATE_IN_PROGRESS;
+        memcached_return_t rc= connect_poll(server, local_error);
+
+        if (memcached_success(rc))
+        {
+          server->state= MEMCACHED_SERVER_STATE_CONNECTED;
+          return MEMCACHED_SUCCESS;
+        }
+
+        // A timeout here is treated as an error, we will not retry
+        if (rc == MEMCACHED_TIMEOUT)
+        {
+          timeout_error_occured= true;
+        }
+      }
+      break;
+
+    case EISCONN: // we are connected :-)
+      WATCHPOINT_ASSERT(0); // This is a programmer's error
+      break;
+
+    case EINTR: // Special case, we retry ai_addr
+      WATCHPOINT_ASSERT(server->fd != INVALID_SOCKET);
+      server->reset_socket();
+      continue;
+
+    case ECONNREFUSED:
+      // Probably not running service
+
+    default:
+      memcached_set_errno(*server, local_error, MEMCACHED_AT);
+      break;
+    }
+
+    WATCHPOINT_ASSERT(server->fd != INVALID_SOCKET);
+    server->reset_socket();
+    server->address_info_next= server->address_info_next->ai_next;
+  }
+
+  WATCHPOINT_ASSERT(server->fd == INVALID_SOCKET);
+
+  if (timeout_error_occured)
+  {
+    server->reset_socket();
+  }
+
+  WATCHPOINT_STRING("Never got a good file descriptor");
+
+  if (memcached_has_current_error(*server))
+  {
+    return memcached_instance_error_return(server);
+  }
+
+  if (timeout_error_occured and server->state < MEMCACHED_SERVER_STATE_IN_PROGRESS)
+  {
+    return memcached_set_error(*server, MEMCACHED_TIMEOUT, MEMCACHED_AT,
+                               memcached_literal_param("if (timeout_error_occured and server->state < MEMCACHED_SERVER_STATE_IN_PROGRESS)"));
+  }
+
+  return memcached_set_error(*server, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT); /* The last error should be from connect() */
+}
+
+
+/*
+  backoff_handling()
+
+  Based on time/failure count fail the connect without trying. This prevents waiting in a state where
+  we get caught spending cycles just waiting.
+*/
+static memcached_return_t backoff_handling(memcached_instance_st* server, bool& in_timeout)
+{
+  struct timeval curr_time;
+  bool _gettime_success= (gettimeofday(&curr_time, NULL) == 0);
+
+  /* 
+    If we hit server_failure_limit then something is completely wrong about the server.
+
+    1) If autoeject is enabled we do that.
+    2) If not? We go into timeout again, there is much else to do :(
+  */
+  if (server->server_failure_counter >= server->root->server_failure_limit)
+  {
+    /*
+      We just auto_eject if we hit this point 
+    */
+    if (_is_auto_eject_host(server->root))
+    {
+      set_last_disconnected_host(server);
+
+      // Retry dead servers if requested
+      if (_gettime_success and server->root->dead_timeout > 0)
+      {
+        server->next_retry= curr_time.tv_sec +server->root->dead_timeout;
+
+        // We only retry dead servers once before assuming failure again
+        server->server_failure_counter= server->root->server_failure_limit -1;
+      }
+
+      memcached_return_t rc;
+      if (memcached_failed(rc= run_distribution((memcached_st *)server->root)))
+      {
+        return memcached_set_error(*server, rc, MEMCACHED_AT, memcached_literal_param("Backoff handling failed during run_distribution"));
+      }
+
+      return memcached_set_error(*server, MEMCACHED_SERVER_MARKED_DEAD, MEMCACHED_AT);
+    }
+
+    server->state= MEMCACHED_SERVER_STATE_IN_TIMEOUT;
+
+    // Sanity check/setting
+    if (server->next_retry == 0)
+    {
+      server->next_retry= 1;
+    }
+  }
+
+  if (server->state == MEMCACHED_SERVER_STATE_IN_TIMEOUT)
+  {
+    /*
+      If next_retry is less then our current time, then we reset and try everything again.
+    */
+    if (_gettime_success and server->next_retry < curr_time.tv_sec)
+    {
+      server->state= MEMCACHED_SERVER_STATE_NEW;
+      server->server_timeout_counter= 0;
+    }
+    else
+    {
+      return memcached_set_error(*server, MEMCACHED_SERVER_TEMPORARILY_DISABLED, MEMCACHED_AT);
+    }
+
+    in_timeout= true;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t _memcached_connect(memcached_instance_st* server, const bool set_last_disconnected)
+{
+  assert(server);
+  if (server->fd != INVALID_SOCKET)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  LIBMEMCACHED_MEMCACHED_CONNECT_START();
+
+  bool in_timeout= false;
+  memcached_return_t rc;
+  if (memcached_failed(rc= backoff_handling(server, in_timeout)))
+  {
+    set_last_disconnected_host(server);
+    return rc;
+  }
+
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT and server->root->sasl.callbacks and memcached_is_udp(server->root))
+  {
+    return memcached_set_error(*server, MEMCACHED_INVALID_HOST_PROTOCOL, MEMCACHED_AT, memcached_literal_param("SASL is not supported for UDP connections"));
+  }
+
+  if (server->hostname()[0] == '/')
+  {
+    server->type= MEMCACHED_CONNECTION_UNIX_SOCKET;
+  }
+
+  /* We need to clean up the multi startup piece */
+  switch (server->type)
+  {
+  case MEMCACHED_CONNECTION_UDP:
+  case MEMCACHED_CONNECTION_TCP:
+    rc= network_connect(server);
+
+#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT)
+    if (LIBMEMCACHED_WITH_SASL_SUPPORT)
+    {
+      if (server->fd != INVALID_SOCKET and server->root->sasl.callbacks)
+      {
+        rc= memcached_sasl_authenticate_connection(server);
+        if (memcached_failed(rc) and server->fd != INVALID_SOCKET)
+        {
+          WATCHPOINT_ASSERT(server->fd != INVALID_SOCKET);
+          server->reset_socket();
+        }
+      }
+    }
+#endif
+    break;
+
+  case MEMCACHED_CONNECTION_UNIX_SOCKET:
+    rc= unix_socket_connect(server);
+    break;
+  }
+
+  if (memcached_success(rc))
+  {
+    server->mark_server_as_clean();
+    memcached_version_instance(server);
+    return rc;
+  }
+  else if (set_last_disconnected)
+  {
+    set_last_disconnected_host(server);
+    if (memcached_has_current_error(*server))
+    {
+      memcached_mark_server_for_timeout(server);
+      assert(memcached_failed(memcached_instance_error_return(server)));
+    }
+    else
+    {
+      memcached_set_error(*server, rc, MEMCACHED_AT);
+      memcached_mark_server_for_timeout(server);
+    }
+
+    LIBMEMCACHED_MEMCACHED_CONNECT_END();
+
+    if (in_timeout)
+    {
+      char buffer[1024];
+      int snprintf_length= snprintf(buffer, sizeof(buffer), "%s:%d", server->hostname(), int(server->port()));
+      return memcached_set_error(*server, MEMCACHED_SERVER_TEMPORARILY_DISABLED, MEMCACHED_AT, buffer, snprintf_length);
+    }
+  }
+
+  return rc;
+}
+
+memcached_return_t memcached_connect(memcached_instance_st* server)
+{
+  return _memcached_connect(server, true);
+}
diff --git a/src/libmemcached/connect.hpp b/src/libmemcached/connect.hpp
new file mode 100644 (file)
index 0000000..d1dafe5
--- /dev/null
@@ -0,0 +1,40 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+memcached_return_t memcached_connect(memcached_instance_st*);
diff --git a/src/libmemcached/continuum.hpp b/src/libmemcached/continuum.hpp
new file mode 100644 (file)
index 0000000..e39fcdc
--- /dev/null
@@ -0,0 +1,46 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+/* string value */
+struct memcached_continuum_item_st
+{
+  uint32_t index;
+  uint32_t value;
+};
diff --git a/src/libmemcached/csl/common.h b/src/libmemcached/csl/common.h
new file mode 100644 (file)
index 0000000..60b27d6
--- /dev/null
@@ -0,0 +1,52 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Configure Scripting Language
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#ifndef YY_EXTRA_TYPE
+# define YY_EXTRA_TYPE Context*
+#endif
+
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+# define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+#include <libmemcached/common.h>
+#include <libmemcached/csl/server.h>
+
diff --git a/src/libmemcached/csl/context.cc b/src/libmemcached/csl/context.cc
new file mode 100644 (file)
index 0000000..fa2500b
--- /dev/null
@@ -0,0 +1,136 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Configure Scripting Language
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/csl/common.h>
+#include <libmemcached/csl/context.h>
+
+void Context::abort(const char *error_arg, config_tokentype last_token, const char *last_token_str)
+{
+  rc= MEMCACHED_PARSE_ERROR;
+  (void)last_token;
+
+  if (error_arg)
+  {
+    memcached_set_parser_error(*memc, MEMCACHED_AT, "%s", error_arg);
+    return;
+  }
+
+  if (last_token_str)
+  {
+    memcached_set_parser_error(*memc, MEMCACHED_AT, "%s", last_token_str);
+    return;
+  }
+
+  memcached_set_parser_error(*memc, MEMCACHED_AT, "unknown parsing error");
+}
+
+void Context::error(const char *error_arg, config_tokentype last_token, const char *last_token_str)
+{
+  rc= MEMCACHED_PARSE_ERROR;
+  if (not error_arg)
+  {
+    memcached_set_parser_error(*memc, MEMCACHED_AT, "Unknown error occured during parsing (%s)", last_token_str ? last_token_str : " ");
+    return;
+  }
+
+  if (strcmp(error_arg, "memory exhausted") == 0)
+  {
+    (void)memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, memcached_string_make_from_cstr(error_arg));
+    return;
+  }
+
+  // We now test if it is something other then a syntax error, if it  we
+  // return a generic message 
+  if (strcmp(error_arg, "syntax error") != 0)
+  {
+    memcached_set_parser_error(*memc, MEMCACHED_AT, "Error occured during parsing (%s)", error_arg);
+    return;
+  }
+
+  if (last_token == UNKNOWN_OPTION and begin)
+  {
+    memcached_set_parser_error(*memc, MEMCACHED_AT, "Unknown option: %s", begin);
+  }
+  else if (last_token == UNKNOWN)
+  {
+    memcached_set_parser_error(*memc, MEMCACHED_AT, "Error occured durring parsing, an unknown token was found.");
+  }
+  else
+  {
+    memcached_set_parser_error(*memc, MEMCACHED_AT, "Error occured while parsing (%s)", last_token_str ? last_token_str : " ");
+  }
+}
+
+void Context::hostname(const char *str, size_t size, server_t& server_)
+{
+  size_t copy_length= size_t(NI_MAXHOST) > size ? size : size_t(NI_MAXHOST);
+  memcpy(_hostname, str, copy_length);
+  _hostname[copy_length]= 0;
+
+  server_.port= MEMCACHED_DEFAULT_PORT;
+  server_.weight= 1;
+  server_.c_str= _hostname;
+  server_.size= size;
+}
+
+bool Context::string_buffer(const char *str, size_t size, memcached_string_t& string_)
+{
+  if (memcached_string_set(_string_buffer, str, size))
+  {
+    string_.c_str= memcached_string_value(_string_buffer);
+    string_.size= memcached_string_length(_string_buffer);
+
+    return true;
+  }
+
+  return false;
+}
+
+bool Context::set_hash(memcached_hash_t hash)
+{
+  if (_has_hash)
+  {
+    return false;
+  }
+
+  if ((memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash)) != MEMCACHED_SUCCESS)
+  {
+    return false;
+  }
+
+  return _has_hash= true;
+}
diff --git a/src/libmemcached/csl/context.h b/src/libmemcached/csl/context.h
new file mode 100644 (file)
index 0000000..64d1f2f
--- /dev/null
@@ -0,0 +1,138 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Configure Scripting Language
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include "libmemcached/csl/common.h"
+#include "libmemcached/csl/parser.h"
+
+class Context
+{
+public:
+  Context(const char *option_string, size_t option_string_length, memcached_st *memc_,
+          memcached_return_t &rc_arg) :
+    previous_token(END),
+    scanner(NULL),
+    buf(option_string),
+    begin(NULL),
+    pos(0),
+    length(option_string_length),
+    memc(memc_),
+    rc(rc_arg),
+    _is_server(false),
+    _end(false),
+    _has_hash(false)
+  {
+    _hostname[0]= 0;
+    init_scanner();
+    rc= MEMCACHED_SUCCESS;
+
+    memc->state.is_parsing= true;
+    memcached_string_create(memc,
+                            &_string_buffer,
+                            1024);
+  }
+
+  bool end()
+  {
+    return _end;
+  }
+
+  void start();
+
+  void set_end()
+  {
+    rc= MEMCACHED_SUCCESS;
+    _end= true;
+  }
+
+  bool set_hash(memcached_hash_t hash);
+
+  void set_server()
+  {
+    _is_server= true;
+  }
+
+  void unset_server()
+  {
+    _is_server= false;
+  }
+
+  bool is_server() const
+  {
+    return _is_server;
+  }
+
+  void hostname(const char*, size_t, server_t&);
+
+  bool string_buffer(const char*, size_t, memcached_string_t&);
+
+  const char *hostname() const
+  {
+    return _hostname;
+  }
+
+  void abort(const char *, config_tokentype, const char *);
+  void error(const char *, config_tokentype, const char* );
+
+  ~Context()
+  {
+    memcached_string_free(&_string_buffer);
+    destroy_scanner();
+    memc->state.is_parsing= false;
+  }
+
+  config_tokentype previous_token;
+  void *scanner;
+  const char *buf;
+  const char *begin;
+  size_t pos;
+  size_t length;
+  memcached_st *memc;
+  memcached_return_t &rc;
+
+protected:
+  void init_scanner();   
+  void destroy_scanner();
+
+private:
+  bool _is_server;
+  bool _end;
+  char _hostname[NI_MAXHOST];
+  bool _has_hash;
+  memcached_string_st _string_buffer;
+}; 
diff --git a/src/libmemcached/csl/parser.yy b/src/libmemcached/csl/parser.yy
new file mode 100644 (file)
index 0000000..87fe4f3
--- /dev/null
@@ -0,0 +1,542 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+%{
+
+#include <libmemcached/csl/common.h>
+
+class Context;
+
+%}
+
+%define parse.error verbose
+%define api.pure
+%define api.prefix {config_}
+%define api.value.type {union CONFIG_STYPE}
+%debug
+%defines
+%expect 0
+%lex-param { yyscan_t *scanner }
+%parse-param { class Context *context }
+%parse-param { yyscan_t *scanner }
+%require "2.5"
+%start begin
+%verbose
+
+%{
+
+#include <libmemcached/options.hpp>
+
+#include <libmemcached/csl/context.h>
+#include <libmemcached/csl/symbol.h>
+#include <libmemcached/csl/scanner.h>
+
+#ifndef __INTEL_COMPILER
+# pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+#ifndef __INTEL_COMPILER
+# ifndef __clang__
+#  pragma GCC diagnostic ignored "-Wlogical-op"
+#  pragma GCC diagnostic ignored "-Wunsafe-loop-optimizations"
+# endif
+#endif
+
+int config_lex(YYSTYPE* lvalp, void* scanner);
+
+#define select_yychar(__context) yychar == UNKNOWN ? ( (__context)->previous_token == END ? UNKNOWN : (__context)->previous_token ) : yychar   
+
+#define stryytname(__yytokentype) ((__yytokentype) <  YYNTOKENS ) ? yytname[(__yytokentype)] : ""
+
+#define parser_abort(__context, __error_message) do { (__context)->abort((__error_message), config_tokentype(select_yychar(__context)), stryytname(YYTRANSLATE(select_yychar(__context)))); YYABORT; } while (0)
+
+// This is bison calling error.
+inline void __config_error(Context *context, yyscan_t *scanner, const char *error, int last_token, const char *last_token_str)
+{
+  if (not context->end())
+  {
+    context->error(error, config_tokentype(last_token), last_token_str);
+  }
+  else
+  {
+    context->error(error, config_tokentype(last_token), last_token_str);
+  }
+}
+
+#define config_error(__context, __scanner, __error_msg) do { __config_error((__context), (__scanner), (__error_msg), select_yychar(__context), stryytname(YYTRANSLATE(select_yychar(__context)))); } while (0)
+
+
+%}
+
+%token COMMENT
+%token END
+%token CSL_ERROR
+%token RESET
+%token PARSER_DEBUG
+%token INCLUDE
+%token CONFIGURE_FILE
+%token EMPTY_LINE
+%token SERVER
+%token CSL_SOCKET
+%token SERVERS
+%token SERVERS_OPTION
+%token UNKNOWN_OPTION
+%token UNKNOWN
+
+/* All behavior options */
+%token BINARY_PROTOCOL
+%token BUFFER_REQUESTS
+%token CONNECT_TIMEOUT
+%token DISTRIBUTION
+%token HASH
+%token HASH_WITH_NAMESPACE
+%token IO_BYTES_WATERMARK
+%token IO_KEY_PREFETCH
+%token IO_MSG_WATERMARK
+%token KETAMA_HASH
+%token KETAMA_WEIGHTED
+%token NOREPLY
+%token NUMBER_OF_REPLICAS
+%token POLL_TIMEOUT
+%token RANDOMIZE_REPLICA_READ
+%token RCV_TIMEOUT
+%token REMOVE_FAILED_SERVERS
+%token RETRY_TIMEOUT
+%token SND_TIMEOUT
+%token SOCKET_RECV_SIZE
+%token SOCKET_SEND_SIZE
+%token SORT_HOSTS
+%token SUPPORT_CAS
+%token USER_DATA
+%token USE_UDP
+%token VERIFY_KEY
+%token _TCP_KEEPALIVE
+%token _TCP_KEEPIDLE
+%token _TCP_NODELAY
+%token FETCH_VERSION
+
+/* Callbacks */
+%token NAMESPACE
+
+/* Pool */
+%token POOL_MIN
+%token POOL_MAX
+
+/* Hash types */
+%token MD5
+%token CRC
+%token FNV1_64
+%token FNV1A_64
+%token FNV1_32
+%token FNV1A_32
+%token HSIEH
+%token MURMUR
+%token JENKINS
+
+/* Distributions */
+%token CONSISTENT
+%token MODULA
+%token RANDOM
+
+/* Boolean values */
+%token <boolean> CSL_TRUE
+%token <boolean> CSL_FALSE
+
+%nonassoc ','
+%nonassoc '='
+
+%token <number> CSL_FLOAT
+%token <number> NUMBER
+%token <number> PORT
+%token <number> WEIGHT_START
+%token <server> IPADDRESS
+%token <server> HOSTNAME
+%token <string> STRING
+%token <string> QUOTED_STRING
+%token <string> FILE_PATH
+
+%type <behavior> behavior_boolean
+%type <behavior> behavior_number
+%type <distribution> distribution
+%type <hash> hash
+%type <number> optional_port
+%type <number> optional_weight
+%type <string> string
+
+%%
+
+begin:
+          statement
+        | begin ' ' statement
+        ;
+
+statement:
+         expression
+          { }
+        | COMMENT
+          { }
+        | EMPTY_LINE
+          { }
+        | END
+          {
+            context->set_end();
+            YYACCEPT;
+          }
+        | CSL_ERROR
+          {
+            context->rc= MEMCACHED_PARSE_USER_ERROR;
+            parser_abort(context, "ERROR called directly");
+          }
+        | RESET
+          {
+            memcached_reset(context->memc);
+          }
+        | PARSER_DEBUG
+          {
+            yydebug= 1;
+          }
+        | INCLUDE ' ' string
+          {
+            if ((context->rc= memcached_parse_configure_file(*context->memc, $3.c_str, $3.size)) != MEMCACHED_SUCCESS)
+            {
+              parser_abort(context, "Failed to parse configuration file");
+            }
+          }
+        ;
+
+
+expression:
+          SERVER HOSTNAME optional_port optional_weight
+          {
+            if (memcached_failed(context->rc= memcached_server_add_with_weight(context->memc, $2.c_str, $3, uint32_t($4))))
+            {
+              char buffer[1024];
+              snprintf(buffer, sizeof(buffer), "Failed to add server: %s:%u", $2.c_str, uint32_t($3));
+              parser_abort(context, buffer);
+            }
+            context->unset_server();
+          }
+        | SERVER IPADDRESS optional_port optional_weight
+          {
+            if (memcached_failed(context->rc= memcached_server_add_with_weight(context->memc, $2.c_str, $3, uint32_t($4))))
+            {
+              char buffer[1024];
+              snprintf(buffer, sizeof(buffer), "Failed to add server: %s:%u", $2.c_str, uint32_t($3));
+              parser_abort(context, buffer);
+            }
+            context->unset_server();
+          }
+        | CSL_SOCKET string optional_weight
+          {
+            if (memcached_failed(context->rc= memcached_server_add_unix_socket_with_weight(context->memc, $2.c_str, uint32_t($3))))
+            {
+              char buffer[1024];
+              snprintf(buffer, sizeof(buffer), "Failed to add socket: %s", $2.c_str);
+              parser_abort(context, buffer);
+            }
+          }
+        | CONFIGURE_FILE string
+          {
+            memcached_set_configuration_file(context->memc, $2.c_str, $2.size);
+          }
+        | POOL_MIN NUMBER
+          {
+            context->memc->configure.initial_pool_size= uint32_t($2);
+          }
+        | POOL_MAX NUMBER
+          {
+            context->memc->configure.max_pool_size= uint32_t($2);
+          }
+        | behaviors
+        ;
+
+behaviors:
+          NAMESPACE string
+          {
+            if (memcached_callback_get(context->memc, MEMCACHED_CALLBACK_PREFIX_KEY, NULL))
+            {
+              parser_abort(context, "--NAMESPACE can only be called once");
+            }
+
+            if ((context->rc= memcached_set_namespace(*context->memc, $2.c_str, $2.size)) != MEMCACHED_SUCCESS)
+            {
+              parser_abort(context, memcached_last_error_message(context->memc));
+            }
+          }
+        | FETCH_VERSION
+          {
+            memcached_flag(*context->memc, MEMCACHED_FLAG_IS_FETCHING_VERSION, true);
+          }
+        | DISTRIBUTION distribution
+          {
+            // Check to see if DISTRIBUTION has already been set
+            if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
+            {
+              parser_abort(context, "--DISTRIBUTION can only be called once");
+            }
+
+            if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
+            {
+              parser_abort(context, memcached_last_error_message(context->memc));;
+            }
+          }
+        | DISTRIBUTION distribution ',' hash
+          {
+            // Check to see if DISTRIBUTION has already been set
+            if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, $2)) != MEMCACHED_SUCCESS)
+            {
+              parser_abort(context, "--DISTRIBUTION can only be called once");
+            }
+
+            if ((context->rc= memcached_behavior_set_distribution_hash(context->memc, $4)) != MEMCACHED_SUCCESS)
+            {
+              parser_abort(context, "Unable to set the hash for the DISTRIBUTION requested");
+            }
+          }
+        | HASH hash
+          {
+            if (context->set_hash($2) == false)
+            {
+              parser_abort(context, "--HASH can only be set once");
+            }
+          }
+        | behavior_number NUMBER
+          {
+            if ((context->rc= memcached_behavior_set(context->memc, $1, $2)) != MEMCACHED_SUCCESS)
+            {
+              parser_abort(context, "Unable to set behavior");
+            }
+          }
+        | behavior_boolean
+          {
+            if ((context->rc= memcached_behavior_set(context->memc, $1, true)) != MEMCACHED_SUCCESS)
+            {
+              char buffer[1024];
+              snprintf(buffer, sizeof(buffer), "Could not set: %s", libmemcached_string_behavior($1));
+              parser_abort(context, buffer);
+            }
+          }
+        |  USER_DATA
+          {
+          }
+        ;
+
+behavior_number:
+          REMOVE_FAILED_SERVERS
+          {
+            $$= MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS;
+          }
+        | CONNECT_TIMEOUT
+          {
+            $$= MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT;
+          }
+        | IO_MSG_WATERMARK
+          {
+            $$= MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK;
+          }
+        | IO_BYTES_WATERMARK
+          {
+            $$= MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK;
+          }
+        | IO_KEY_PREFETCH
+          {
+            $$= MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH;
+          }
+        | NUMBER_OF_REPLICAS
+          {
+            $$= MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS;
+          }
+        | POLL_TIMEOUT
+          {
+            $$= MEMCACHED_BEHAVIOR_POLL_TIMEOUT;
+          }
+        |  RCV_TIMEOUT
+          {
+            $$= MEMCACHED_BEHAVIOR_RCV_TIMEOUT;
+          }
+        |  RETRY_TIMEOUT
+          {
+            $$= MEMCACHED_BEHAVIOR_RETRY_TIMEOUT;
+          }
+        |  SND_TIMEOUT
+          {
+            $$= MEMCACHED_BEHAVIOR_SND_TIMEOUT;
+          }
+        |  SOCKET_RECV_SIZE
+          {
+            $$= MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE;
+          }
+        |  SOCKET_SEND_SIZE
+          {
+            $$= MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE;
+          }
+        ;
+
+behavior_boolean: 
+          BINARY_PROTOCOL
+          {
+            $$= MEMCACHED_BEHAVIOR_BINARY_PROTOCOL;
+          }
+        | BUFFER_REQUESTS
+          {
+            $$= MEMCACHED_BEHAVIOR_BUFFER_REQUESTS;
+          }
+        | HASH_WITH_NAMESPACE
+          {
+            $$= MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY;
+          }
+        | NOREPLY
+          {
+            $$= MEMCACHED_BEHAVIOR_NOREPLY;
+          }
+        |  RANDOMIZE_REPLICA_READ
+          {
+            $$= MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ;
+          }
+        |  SORT_HOSTS
+          {
+            $$= MEMCACHED_BEHAVIOR_SORT_HOSTS;
+          }
+        |  SUPPORT_CAS
+          {
+            $$= MEMCACHED_BEHAVIOR_SUPPORT_CAS;
+          }
+        |  _TCP_NODELAY
+          {
+            $$= MEMCACHED_BEHAVIOR_TCP_NODELAY;
+          }
+        |  _TCP_KEEPALIVE
+          {
+            $$= MEMCACHED_BEHAVIOR_TCP_KEEPALIVE;
+          }
+        |  _TCP_KEEPIDLE
+          {
+            $$= MEMCACHED_BEHAVIOR_TCP_KEEPIDLE;
+          }
+        |  USE_UDP
+          {
+            $$= MEMCACHED_BEHAVIOR_USE_UDP;
+          }
+        |  VERIFY_KEY
+          {
+            $$= MEMCACHED_BEHAVIOR_VERIFY_KEY;
+          }
+
+
+optional_port:
+          { $$= MEMCACHED_DEFAULT_PORT;}
+        | PORT
+          { };
+        ;
+
+optional_weight:
+          { $$= 1; }
+        | WEIGHT_START
+          { }
+        ;
+
+hash:
+          MD5
+          {
+            $$= MEMCACHED_HASH_MD5;
+          }
+        | CRC
+          {
+            $$= MEMCACHED_HASH_CRC;
+          }
+        | FNV1_64
+          {
+            $$= MEMCACHED_HASH_FNV1_64;
+          }
+        | FNV1A_64
+          {
+            $$= MEMCACHED_HASH_FNV1A_64;
+          }
+        | FNV1_32
+          {
+            $$= MEMCACHED_HASH_FNV1_32;
+          }
+        | FNV1A_32
+          {
+            $$= MEMCACHED_HASH_FNV1A_32;
+          }
+        | HSIEH
+          {
+            $$= MEMCACHED_HASH_HSIEH;
+          }
+        | MURMUR
+          {
+            $$= MEMCACHED_HASH_MURMUR;
+          }
+        | JENKINS
+          {
+            $$= MEMCACHED_HASH_JENKINS;
+          }
+        ;
+
+string:
+          STRING
+          {
+            $$= $1;
+          }
+        | QUOTED_STRING
+          {
+            $$= $1;
+          }
+        ;
+
+distribution:
+          CONSISTENT
+          {
+            $$= MEMCACHED_DISTRIBUTION_CONSISTENT;
+          }
+        | MODULA
+          {
+            $$= MEMCACHED_DISTRIBUTION_MODULA;
+          }
+        | RANDOM
+          {
+            $$= MEMCACHED_DISTRIBUTION_RANDOM;
+          }
+        ;
+
+%% 
+
+void Context::start() 
+{
+  config_parse(this, (void **)scanner);
+}
+
diff --git a/src/libmemcached/csl/scanner.l b/src/libmemcached/csl/scanner.l
new file mode 100644 (file)
index 0000000..d82af27
--- /dev/null
@@ -0,0 +1,239 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+%top{
+
+#include <libmemcached/csl/common.h>
+#include <libmemcached/csl/context.h>
+#include <libmemcached/csl/parser.h>
+#include <libmemcached/csl/symbol.h>
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#pragma GCC diagnostic ignored "-Wsign-compare"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wmissing-declarations"
+#pragma GCC diagnostic ignored "-Wunused-result"
+#pragma GCC diagnostic ignored "-Wmissing-noreturn"
+#endif
+
+#ifdef __clang__
+#pragma GCC diagnostic ignored "-Wshorten-64-to-32"
+#endif
+
+#ifndef __INTEL_COMPILER
+#ifndef __clang__
+#pragma GCC diagnostic ignored "-Wlogical-op"
+#endif
+#endif
+
+}
+
+
+%{
+#define PARAM yyget_extra(yyscanner)
+
+#define get_lex_chars(buffer, result, max_size, context) \
+{ \
+  if (context->pos >= context->length) \
+  { \
+    result= YY_NULL; \
+  } \
+  else \
+  { \
+    result= (int)(context->length - context->pos); \
+    (size_t)result > (size_t)max_size ? result= max_size : 0; \
+    memcpy(buffer, context->buf + context->pos, result); \
+    context->pos += result; \
+  } \
+}
+
+#define YY_FATAL_ERROR(msg) \
+{ \
+}
+
+#define YYSTYPE CONFIG_STYPE
+
+#define YY_INPUT(buffer, result, max_size) get_lex_chars(buffer, result, max_size, PARAM)
+
+%}
+
+%option nostdinit
+%option 8bit
+%option warn
+%option bison-bridge
+%option never-interactive
+%option case-insensitive
+%option nodefault
+%option noinput
+%option nounput
+%option noyywrap
+%option perf-report
+%option prefix="config_"
+%option reentrant
+
+%%
+
+
+=|,|[ ]       { return yytext[0];}
+
+[[:digit:]]+ { yylval->number= atoi(yytext); return (NUMBER); }
+
+:[[:digit:]]{1,5} { yylval->number= atoi(yytext +1); return PORT; }
+
+"/?"[[:digit:]]{1,5} { yylval->number= atoi(yytext +2); return WEIGHT_START; }
+
+[\t\r\n] ; /* skip whitespace */
+
+
+^#.*$ {
+      return COMMENT;
+    }
+
+"--SERVER="                          { yyextra->begin= yytext; yyextra->set_server(); return yyextra->previous_token= SERVER; }
+
+"--SOCKET="                          { yyextra->begin= yytext; return yyextra->previous_token= CSL_SOCKET; }
+
+"--BINARY-PROTOCOL"                    { yyextra->begin= yytext; return yyextra->previous_token= BINARY_PROTOCOL; }
+"--BUFFER-REQUESTS"                    { yyextra->begin= yytext; return yyextra->previous_token= BUFFER_REQUESTS; }
+"--CONFIGURE-FILE="                    { yyextra->begin= yytext; return yyextra->previous_token= CONFIGURE_FILE; }
+"--CONNECT-TIMEOUT="                   { yyextra->begin= yytext; return yyextra->previous_token= CONNECT_TIMEOUT; }
+"--DISTRIBUTION="                      { yyextra->begin= yytext; return yyextra->previous_token= DISTRIBUTION; }
+"--HASH-WITH-NAMESPACE"                { yyextra->begin= yytext; return yyextra->previous_token= HASH_WITH_NAMESPACE; }
+"--HASH="                              { yyextra->begin= yytext; return yyextra->previous_token= HASH; }
+"--IO-BYTES-WATERMARK="                { yyextra->begin= yytext; return yyextra->previous_token= IO_BYTES_WATERMARK; }
+"--IO-KEY-PREFETCH="                   { yyextra->begin= yytext; return yyextra->previous_token= IO_KEY_PREFETCH; }
+"--IO-MSG-WATERMARK="          { yyextra->begin= yytext; return yyextra->previous_token= IO_MSG_WATERMARK; }
+"--NOREPLY"                         { yyextra->begin= yytext; return yyextra->previous_token= NOREPLY; }
+"--NUMBER-OF-REPLICAS="                { yyextra->begin= yytext; return yyextra->previous_token= NUMBER_OF_REPLICAS; }
+"--POLL-TIMEOUT="                      { yyextra->begin= yytext; return yyextra->previous_token= POLL_TIMEOUT; }
+"--RANDOMIZE-REPLICA-READ"             { yyextra->begin= yytext; return yyextra->previous_token= RANDOMIZE_REPLICA_READ; }
+"--RCV-TIMEOUT="                       { yyextra->begin= yytext; return yyextra->previous_token= RCV_TIMEOUT; }
+"--REMOVE-FAILED-SERVERS="                     { yyextra->begin= yytext; return yyextra->previous_token= REMOVE_FAILED_SERVERS; }
+"--RETRY-TIMEOUT="                     { yyextra->begin= yytext; return yyextra->previous_token= RETRY_TIMEOUT; }
+"--SND-TIMEOUT="                       { yyextra->begin= yytext; return yyextra->previous_token= SND_TIMEOUT; }
+"--SOCKET-RECV-SIZE="          { yyextra->begin= yytext; return yyextra->previous_token= SOCKET_RECV_SIZE; }
+"--SOCKET-SEND-SIZE="          { yyextra->begin= yytext; return yyextra->previous_token= SOCKET_SEND_SIZE; }
+"--SORT-HOSTS"                 { yyextra->begin= yytext; return yyextra->previous_token= SORT_HOSTS; }
+"--SUPPORT-CAS"                        { yyextra->begin= yytext; return yyextra->previous_token= SUPPORT_CAS; }
+"--TCP-KEEPALIVE"                      { yyextra->begin= yytext; return yyextra->previous_token= _TCP_KEEPALIVE; }
+"--TCP-KEEPIDLE"                       { yyextra->begin= yytext; return yyextra->previous_token= _TCP_KEEPIDLE; }
+"--TCP-NODELAY"                        { yyextra->begin= yytext; return yyextra->previous_token= _TCP_NODELAY; }
+"--USE-UDP"                            { yyextra->begin= yytext; return yyextra->previous_token= USE_UDP; }
+"--USER-DATA"                  { yyextra->begin= yytext; return yyextra->previous_token= USER_DATA; }
+"--VERIFY-KEY"                      { yyextra->begin= yytext; return yyextra->previous_token= VERIFY_KEY; }
+
+"--POOL-MIN="                          { yyextra->begin= yytext; return yyextra->previous_token= POOL_MIN; }
+"--POOL-MAX="                          { yyextra->begin= yytext; return yyextra->previous_token= POOL_MAX; }
+
+"--NAMESPACE="                         { yyextra->begin= yytext; return yyextra->previous_token= NAMESPACE; }
+
+"--FETCH-VERSION"                              { yyextra->begin= yytext; return yyextra->previous_token= FETCH_VERSION; }
+
+INCLUDE           { yyextra->begin= yytext; return yyextra->previous_token= INCLUDE; }
+RESET           { yyextra->begin= yytext; return yyextra->previous_token= RESET; }
+DEBUG           { yyextra->begin= yytext; return yyextra->previous_token= PARSER_DEBUG; }
+SERVERS           { yyextra->begin= yytext; return yyextra->previous_token= SERVERS; }
+END           { yyextra->begin= yytext; return yyextra->previous_token= END; }
+CSL_ERROR           { yyextra->begin= yytext; return yyextra->previous_token= CSL_ERROR; }
+
+TRUE           { return yyextra->previous_token= CSL_TRUE; }
+FALSE           { return yyextra->previous_token= CSL_FALSE; }
+
+
+"--"[[:alnum:]]*   {
+      yyextra->begin= yytext;
+      return UNKNOWN_OPTION;
+    }
+
+CONSISTENT      { return CONSISTENT; }
+MODULA          { return MODULA; }
+RANDOM          { return RANDOM; }
+
+MD5                    { return MD5; }
+CRC                    { return CRC; }
+FNV1_64                        { return FNV1_64; }
+FNV1A_64                       { return FNV1A_64; }
+FNV1_32                        { return FNV1_32; }
+FNV1A_32                       { return FNV1A_32; }
+HSIEH                  { return HSIEH; }
+MURMUR                 { return MURMUR; }
+JENKINS                        { return JENKINS; }
+
+(([[:digit:]]{1,3}"."){3}([[:digit:]]{1,3})) {
+      yyextra->hostname(yytext, yyleng, yylval->server);
+      return IPADDRESS;
+    }
+
+[[:alnum:]]["."[:alnum:]_-]+[[:alnum:]] {
+      if (yyextra->is_server())
+      {
+        yyextra->hostname(yytext, yyleng, yylval->server);
+
+        return HOSTNAME;
+      }
+
+      yyextra->string_buffer(yytext, yyleng, yylval->string);
+
+      return STRING;
+    }
+
+L?\"(\\.|[^\\"])*\" {
+      yyget_text(yyscanner)[yyleng -1]= 0;
+      yyextra->string_buffer(yytext +1, yyleng -2, yylval->string);
+      return QUOTED_STRING;
+    }
+
+.   {
+      yyextra->begin= yytext;
+      return UNKNOWN;
+    }
+
+%%
+
+void Context::init_scanner()
+{
+  yylex_init(&scanner);
+  yyset_extra(this, scanner);
+}
+
+void Context::destroy_scanner()
+{
+  (void)yy_fatal_error; // Removes warning about unused yy_fatal_error()
+  yylex_destroy(scanner);
+}
+
diff --git a/src/libmemcached/csl/server.h b/src/libmemcached/csl/server.h
new file mode 100644 (file)
index 0000000..21915d6
--- /dev/null
@@ -0,0 +1,52 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Configure Scripting Language
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <cstdlib>
+
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+struct server_t
+{
+  const char *c_str;
+  size_t size;
+  in_port_t port;
+  uint32_t weight;
+};
diff --git a/src/libmemcached/csl/symbol.h b/src/libmemcached/csl/symbol.h
new file mode 100644 (file)
index 0000000..10ff603
--- /dev/null
@@ -0,0 +1,55 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Configure Scripting Language
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libmemcached/csl/common.h>
+
+union CONFIG_STYPE
+{
+  long long number;  
+  memcached_string_t string;
+  memcached_string_t option;
+  double double_number;
+  memcached_server_distribution_t distribution;
+  memcached_hash_t hash;
+  memcached_behavior_t behavior;
+  bool boolean;
+  server_t server;
+};
+
+typedef union CONFIG_STYPE CONFIG_STYPE;
diff --git a/src/libmemcached/delete.cc b/src/libmemcached/delete.cc
new file mode 100644 (file)
index 0000000..ef1d847
--- /dev/null
@@ -0,0 +1,210 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+memcached_return_t memcached_delete(memcached_st *shell, const char *key, size_t key_length,
+                                    time_t expiration)
+{
+  return memcached_delete_by_key(shell, key, key_length, key, key_length, expiration);
+}
+
+static inline memcached_return_t ascii_delete(memcached_instance_st* instance,
+                                              uint32_t ,
+                                              const char *key,
+                                              const size_t key_length,
+                                              const bool reply,
+                                              const bool is_buffering)
+{
+  libmemcached_io_vector_st vector[]=
+  {
+    { NULL, 0 },
+    { memcached_literal_param("delete ") },
+    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+    { key, key_length },
+    { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
+    { memcached_literal_param("\r\n") }
+  };
+
+  /* Send command header, only flush if we are NOT buffering */
+  return memcached_vdo(instance, vector, 6, is_buffering ? false : true);
+}
+
+static inline memcached_return_t binary_delete(memcached_instance_st* instance,
+                                               uint32_t server_key,
+                                               const char *key,
+                                               const size_t key_length,
+                                               const bool reply,
+                                               const bool is_buffering)
+{
+  protocol_binary_request_delete request= {};
+
+  bool should_flush= is_buffering ? false : true;
+
+  initialize_binary_request(instance, request.message.header);
+
+  if (reply)
+  {
+    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETE;
+  }
+  else
+  {
+    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
+  }
+  request.message.header.request.keylen= htons(uint16_t(key_length + memcached_array_size(instance->root->_namespace)));
+  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+  request.message.header.request.bodylen= htonl(uint32_t(key_length + memcached_array_size(instance->root->_namespace)));
+
+  libmemcached_io_vector_st vector[]=
+  {
+    { NULL, 0 },
+    { request.bytes, sizeof(request.bytes) },
+    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+    { key, key_length }
+  };
+
+  memcached_return_t rc= memcached_vdo(instance, vector,  4, should_flush);
+
+  if (memcached_has_replicas(instance))
+  {
+    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
+
+    for (uint32_t x= 0; x < memcached_has_replicas(instance); ++x)
+    {
+      ++server_key;
+
+      if (server_key == memcached_server_count(instance->root))
+      {
+        server_key= 0;
+      }
+
+      memcached_instance_st* replica= memcached_instance_fetch(instance->root, server_key);
+
+      if (memcached_success(memcached_vdo(replica, vector, 4, should_flush)))
+      {
+        memcached_server_response_decrement(replica);
+      }
+    }
+  }
+
+  return rc;
+}
+
+memcached_return_t memcached_delete_by_key(memcached_st *shell,
+                                           const char *group_key, size_t group_key_length,
+                                           const char *key, size_t key_length,
+                                           time_t expiration)
+{
+  Memcached* memc= memcached2Memcached(shell);
+  LIBMEMCACHED_MEMCACHED_DELETE_START();
+
+  memcached_return_t rc;
+  if (memcached_fatal(rc= initialize_query(memc, true)))
+  {
+    return rc;
+  }
+
+  if (memcached_fatal(rc= memcached_key_test(*memc, (const char **)&key, &key_length, 1)))
+  {
+    return memcached_last_error(memc);
+  }
+
+  if (expiration)
+  {
+    return memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, 
+                               memcached_literal_param("Memcached server version does not allow expiration of deleted items"));
+  }
+
+  uint32_t server_key= memcached_generate_hash_with_redistribution(memc, group_key, group_key_length);
+  memcached_instance_st* instance= memcached_instance_fetch(memc, server_key);
+  
+  bool is_buffering= memcached_is_buffering(instance->root);
+  bool is_replying= memcached_is_replying(instance->root);
+
+  // If a delete trigger exists, we need a response, so no buffering/noreply
+  if (memc->delete_trigger)
+  {
+    if (is_buffering)
+    {
+      return memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, 
+                                 memcached_literal_param("Delete triggers cannot be used if buffering is enabled"));
+    }
+
+    if (is_replying == false)
+    {
+      return memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, 
+                                 memcached_literal_param("Delete triggers cannot be used if MEMCACHED_BEHAVIOR_NOREPLY is set"));
+    }
+  }
+
+  if (memcached_is_binary(memc))
+  {
+    rc= binary_delete(instance, server_key, key, key_length, is_replying, is_buffering);
+  }
+  else
+  {
+    rc= ascii_delete(instance, server_key, key, key_length, is_replying, is_buffering);
+  }
+
+  if (rc == MEMCACHED_SUCCESS)
+  {
+    if (is_buffering == true)
+    {
+      rc= MEMCACHED_BUFFERED;
+    }
+    else if (is_replying == false)
+    {
+      rc= MEMCACHED_SUCCESS;
+    }
+    else
+    {
+      char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+      rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+      if (rc == MEMCACHED_DELETED)
+      {
+        rc= MEMCACHED_SUCCESS;
+        if (memc->delete_trigger)
+        {
+          memc->delete_trigger(memc, key, key_length);
+        }
+      }
+    }
+  }
+
+  LIBMEMCACHED_MEMCACHED_DELETE_END();
+  return rc;
+}
diff --git a/src/libmemcached/do.cc b/src/libmemcached/do.cc
new file mode 100644 (file)
index 0000000..59f9d5a
--- /dev/null
@@ -0,0 +1,110 @@
+/* LibMemcached
+ * Copyright (C) 2006-2010 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary:
+ *
+ */
+
+#include <libmemcached/common.h>
+
+static memcached_return_t _vdo_udp(memcached_instance_st* instance,
+                                   libmemcached_io_vector_st vector[],
+                                   const size_t count)
+{
+#ifndef __MINGW32__
+  if (vector[0].buffer or vector[0].length)
+  {
+    return memcached_set_error(*instance->root, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, 
+                               memcached_literal_param("UDP messages was attempted, but vector was not setup for it"));
+  }
+
+  struct msghdr msg;
+  memset(&msg, 0, sizeof(msg));
+
+  increment_udp_message_id(instance);
+  vector[0].buffer= instance->write_buffer;
+  vector[0].length= UDP_DATAGRAM_HEADER_LENGTH;
+
+  msg.msg_iov= (struct iovec*)vector;
+#ifdef __APPLE__
+  msg.msg_iovlen= int(count);
+#else
+  msg.msg_iovlen= count;
+#endif
+
+  uint32_t retry= 5;
+  while (--retry)
+  {
+    ssize_t sendmsg_length= ::sendmsg(instance->fd, &msg, 0);
+    if (sendmsg_length > 0)
+    {
+      break;
+    }
+    else if (sendmsg_length < 0)
+    {
+      if (errno == EMSGSIZE)
+      {
+        return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+      }
+
+      return memcached_set_errno(*instance, errno, MEMCACHED_AT);
+    }
+  }
+
+  return MEMCACHED_SUCCESS;
+#else
+  (void)instance;
+  (void)vector;
+  (void)count;
+  return MEMCACHED_FAILURE;
+#endif
+}
+
+memcached_return_t memcached_vdo(memcached_instance_st* instance,
+                                 libmemcached_io_vector_st vector[],
+                                 const size_t count,
+                                 const bool with_flush)
+{
+  memcached_return_t rc;
+
+  assert_msg(vector, "Invalid vector passed");
+
+  if (memcached_failed(rc= memcached_connect(instance)))
+  {
+    WATCHPOINT_ERROR(rc);
+    assert_msg(instance->error_messages, "memcached_connect() returned an error but the Instance showed none.");
+    return rc;
+  }
+
+  /*
+  ** Since non buffering ops in UDP mode dont check to make sure they will fit
+  ** before they start writing, if there is any data in buffer, clear it out,
+  ** otherwise we might get a partial write.
+  **/
+  bool sent_success;
+  if (memcached_is_udp(instance->root))
+  {
+    sent_success= memcached_success(rc= _vdo_udp(instance, vector, count));
+  } else {
+    sent_success= memcached_io_writev(instance, vector, count, with_flush);
+  }
+  if (sent_success == false)
+  {
+    rc= memcached_last_error(instance->root);
+    if (rc == MEMCACHED_SUCCESS)
+    {
+      memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+    }
+    memcached_io_reset(instance);
+  }
+  else if (memcached_is_replying(instance->root) && !memcached_is_udp(instance->root))
+  {
+    memcached_server_response_increment(instance);
+  }
+
+  return rc;
+}
diff --git a/src/libmemcached/do.hpp b/src/libmemcached/do.hpp
new file mode 100644 (file)
index 0000000..d2dc667
--- /dev/null
@@ -0,0 +1,43 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+memcached_return_t memcached_vdo(memcached_instance_st*,
+                                 libmemcached_io_vector_st vector[],
+                                 const size_t count,
+                                 const bool with_flush);
diff --git a/src/libmemcached/dump.cc b/src/libmemcached/dump.cc
new file mode 100644 (file)
index 0000000..c0c4ed6
--- /dev/null
@@ -0,0 +1,171 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+  We use this to dump all keys.
+
+  At this point we only support a callback method. This could be optimized by first
+  calling items and finding active slabs. For the moment though we just loop through
+  all slabs on servers and "grab" the keys.
+*/
+
+#include <libmemcached/common.h>
+
+static memcached_return_t ascii_dump(Memcached *memc, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
+{
+  memcached_version(memc);
+  /* MAX_NUMBER_OF_SLAB_CLASSES is defined to 200 in Memcached 1.4.10 */
+  for (uint32_t x= 0; x < 200; x++)
+  {
+    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+    int buffer_length= snprintf(buffer, sizeof(buffer), "%u", x);
+    if (size_t(buffer_length) >= sizeof(buffer) or buffer_length < 0)
+    {
+      return memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                                 memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
+    }
+
+    // @NOTE the hard coded zero means "no limit"
+    libmemcached_io_vector_st vector[]=
+    {
+      { memcached_literal_param("stats cachedump ") },
+      { buffer, size_t(buffer_length) },
+      { memcached_literal_param(" 0\r\n") }
+    };
+
+    // Send message to all servers
+    for (uint32_t server_key= 0; server_key < memcached_server_count(memc); server_key++)
+    {
+      memcached_instance_st* instance= memcached_instance_fetch(memc, server_key);
+
+      // skip slabs >63 for server versions >= 1.4.23
+      if (x < 64 || memcached_version_instance_cmp(instance, 1, 4, 23) < 0) {
+        memcached_return_t vdo_rc;
+        if (memcached_failed((vdo_rc= memcached_vdo(instance, vector, 3, true))))
+        {
+          return vdo_rc;
+        }
+      }
+    }
+
+    // Collect the returned items
+    memcached_instance_st* instance;
+    memcached_return_t read_ret= MEMCACHED_SUCCESS;
+    while ((instance= memcached_io_get_readable_server(memc, read_ret)))
+    {
+      memcached_return_t response_rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+      if (response_rc == MEMCACHED_ITEM)
+      {
+        char *string_ptr, *end_ptr;
+
+        string_ptr= buffer;
+        string_ptr+= 5; /* Move past ITEM */
+
+        for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++) {} ;
+
+        char *key= string_ptr;
+        key[(size_t)(end_ptr-string_ptr)]= 0;
+
+        for (uint32_t callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++)
+        {
+          memcached_return_t callback_rc= (*callback[callback_counter])(memc, key, (size_t)(end_ptr-string_ptr), context);
+          if (callback_rc != MEMCACHED_SUCCESS)
+          {
+            // @todo build up a message for the error from the value
+            memcached_set_error(*instance, callback_rc, MEMCACHED_AT);
+            break;
+          }
+        }
+      }
+      else if (response_rc == MEMCACHED_END)
+      { 
+        // All items have been returned
+      }
+      else if (response_rc == MEMCACHED_SERVER_ERROR)
+      {
+        /* If we try to request stats cachedump for a slab class that is too big
+         * the server will return an incorrect error message:
+         * "MEMCACHED_SERVER_ERROR failed to allocate memory"
+         * This isn't really a fatal error, so let's just skip it. I want to
+         * fix the return value from the memcached server to a CLIENT_ERROR,
+         * so let's add support for that as well right now.
+       */
+        assert(response_rc == MEMCACHED_SUCCESS); // Just fail
+        return response_rc;
+      }
+      else if (response_rc == MEMCACHED_CLIENT_ERROR)
+      {
+        /* The maximum number of slabs has changed in the past (currently 1<<6-1),
+         * so ignore any client errors complaining about an illegal slab id.
+         */
+        if (0 == strncmp(buffer, "CLIENT_ERROR Illegal slab id", sizeof("CLIENT_ERROR Illegal slab id") - 1)) {
+          memcached_error_free(*instance);
+          memcached_error_free(*memc);
+        } else {
+          return response_rc;
+        }
+      }
+      else
+      {
+        // IO error of some sort must have occurred
+        return response_rc;
+      }
+    }
+  }
+
+  return memcached_has_current_error(*memc) ? MEMCACHED_SOME_ERRORS : MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_dump(memcached_st *shell, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(ptr, true)))
+  {
+    return rc;
+  }
+
+  /* 
+    No support for Binary protocol yet
+    @todo Fix this so that we just flush, switch to ascii, and then go back to binary.
+  */
+  if (memcached_is_binary(ptr))
+  {
+    return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, memcached_literal_param("Binary protocol is not supported for memcached_dump()"));
+  }
+
+  return ascii_dump(ptr, callback, context, number_of_callbacks);
+}
diff --git a/src/libmemcached/encoding_key.cc b/src/libmemcached/encoding_key.cc
new file mode 100644 (file)
index 0000000..1e17d50
--- /dev/null
@@ -0,0 +1,56 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+#include <libmemcached/assert.hpp>
+
+static void _set_encoding_key(Memcached& memc, const char *key, size_t key_length)
+{
+  hashkit_key(&memc.hashkit, key, key_length);
+}
+
+memcached_return_t memcached_set_encoding_key(memcached_st* shell, const char *key, size_t key_length)
+{
+  Memcached* memc= memcached2Memcached(shell);
+  if (memc)
+  {
+    _set_encoding_key(*memc, key, key_length);
+    return MEMCACHED_SUCCESS;
+  }
+
+  return MEMCACHED_INVALID_ARGUMENTS;
+}
diff --git a/src/libmemcached/encoding_key.h b/src/libmemcached/encoding_key.h
new file mode 100644 (file)
index 0000000..a2c47b0
--- /dev/null
@@ -0,0 +1,48 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  memcached_string_t memcached_encoding_key(Memcached&);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/libmemcached/error.cc b/src/libmemcached/error.cc
new file mode 100644 (file)
index 0000000..3de8ece
--- /dev/null
@@ -0,0 +1,675 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+#include "libmemcached/assert.hpp"
+
+#include <cerrno>
+#include <cstdarg>
+#include <cstdio>
+
+#define MAX_ERROR_LENGTH 2048
+struct memcached_error_t
+{
+  Memcached *root;
+  uint64_t query_id;
+  struct memcached_error_t *next;
+  memcached_return_t rc;
+  int local_errno;
+  size_t size;
+  char message[MAX_ERROR_LENGTH];
+};
+
+static void _set(memcached_instance_st& server, Memcached& memc)
+{
+  if (server.error_messages and server.error_messages->query_id != server.root->query_id)
+  {
+    memcached_error_free(server);
+  }
+
+  if (memc.error_messages)
+  {
+    if (memc.error_messages->rc == MEMCACHED_TIMEOUT)
+    {
+      server.io_wait_count.timeouts++;
+    }
+
+    memcached_error_t *error= libmemcached_xmalloc(&memc, memcached_error_t);
+    if (error)
+    {
+      memcpy(error, memc.error_messages, sizeof(memcached_error_t));
+      error->next= server.error_messages;
+      server.error_messages= error;
+    }
+  }
+}
+
+#if 0
+static int error_log_fd= -1;
+#endif
+
+static void _set(Memcached& memc, memcached_string_t *str, memcached_return_t &rc, const char *at, int local_errno= 0)
+{
+  if (memc.error_messages && memc.error_messages->query_id != memc.query_id)
+  {
+    memcached_error_free(memc);
+  }
+
+  if (memcached_fatal(rc) or rc == MEMCACHED_CLIENT_ERROR)
+  {
+    // For memory allocation we use our error since it is a bit more specific
+    if (local_errno == ENOMEM and rc == MEMCACHED_ERRNO)
+    {
+      rc= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    }
+
+    if (rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
+    {
+      local_errno= ENOMEM;
+    }
+
+    if (rc == MEMCACHED_ERRNO and not local_errno)
+    {
+      local_errno= errno;
+      rc= MEMCACHED_ERRNO;
+    }
+
+    if (rc == MEMCACHED_ERRNO and local_errno == ENOTCONN)
+    {
+      rc= MEMCACHED_CONNECTION_FAILURE;
+    }
+
+    if (rc == MEMCACHED_ERRNO and local_errno == ECONNRESET)
+    {
+      rc= MEMCACHED_CONNECTION_FAILURE;
+    }
+
+    if (local_errno == EINVAL)
+    {
+      rc= MEMCACHED_INVALID_ARGUMENTS;
+    }
+
+    if (local_errno == ECONNREFUSED)
+    {
+      rc= MEMCACHED_CONNECTION_FAILURE;
+    }
+
+    if (rc == MEMCACHED_TIMEOUT)
+    {
+    }
+
+    memcached_error_t *error= libmemcached_xmalloc(&memc, memcached_error_t);
+    if (error == NULL) // Bad business if this happens
+    {
+      assert_msg(error, "libmemcached_xmalloc() failed to allocate a memcached_error_t");
+      return;
+    }
+
+    error->root= &memc;
+    error->query_id= memc.query_id;
+    error->rc= rc;
+    error->local_errno= local_errno;
+
+    // MEMCACHED_CLIENT_ERROR is a special case because it is an error coming from the server
+    if (rc == MEMCACHED_CLIENT_ERROR)
+    {
+      assert(str);
+      assert(str->size);
+      if (str and str->size)
+      {
+        assert(error->local_errno == 0);
+        error->local_errno= 0;
+
+        error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%p) %.*s", 
+                                   error->root,
+                                   int(str->size), str->c_str);
+      }
+    }
+    else if (local_errno)
+    {
+      const char *errmsg_ptr;
+      char errmsg[MAX_ERROR_LENGTH];
+      errmsg[0]= 0;
+      errmsg_ptr= errmsg;
+
+#if defined(STRERROR_R_CHAR_P) && STRERROR_R_CHAR_P
+      errmsg_ptr= strerror_r(local_errno, errmsg, sizeof(errmsg));
+#elif defined(HAVE_STRERROR_R) && HAVE_STRERROR_R
+      strerror_r(local_errno, errmsg, sizeof(errmsg));
+      errmsg_ptr= errmsg;
+#elif defined(HAVE_STRERROR) && HAVE_STRERROR
+      snprintf(errmsg, sizeof(errmsg), "%s", strerror(local_errno));
+      errmsg_ptr= errmsg;
+#endif
+
+      if (str and str->size and local_errno)
+      {
+        error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%p) %s(%s), %.*s -> %s", 
+                                   error->root,
+                                   memcached_strerror(&memc, rc), 
+                                   errmsg_ptr,
+                                   memcached_string_printf(*str), at);
+      }
+      else
+      {
+        error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%p) %s(%s) -> %s", 
+                                   error->root,
+                                   memcached_strerror(&memc, rc), 
+                                   errmsg_ptr,
+                                   at);
+      }
+    }
+    else if (rc == MEMCACHED_PARSE_ERROR and str and str->size)
+    {
+      error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%p) %.*s -> %s", 
+                                 error->root,
+                                 int(str->size), str->c_str, at);
+    }
+    else if (str and str->size)
+    {
+      error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%p) %s, %.*s -> %s", 
+                                 error->root,
+                                 memcached_strerror(&memc, rc), 
+                                 int(str->size), str->c_str, at);
+    }
+    else
+    {
+      error->size= (int)snprintf(error->message, MAX_ERROR_LENGTH, "(%p) %s -> %s", 
+                                 error->root,
+                                 memcached_strerror(&memc, rc), at);
+    }
+
+    error->next= memc.error_messages;
+    memc.error_messages= error;
+#if 0
+    if (error_log_fd == -1)
+    {
+  //    unlink("/tmp/libmemcachd.log");
+      if ((error_log_fd= open("/tmp/libmemcachd.log", O_CREAT | O_WRONLY | O_APPEND, 0644)) < 0)
+      {
+        perror("open");
+        error_log_fd= -1;
+      }
+    }
+    ::write(error_log_fd, error->message, error->size);
+    ::write(error_log_fd, "\n", 1);
+#endif
+  }
+}
+
+memcached_return_t memcached_set_error(Memcached& memc, memcached_return_t rc, const char *at, const char *str, size_t length)
+{
+  assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
+  memcached_string_t tmp= { str, length };
+  return memcached_set_error(memc, rc, at, tmp);
+}
+
+memcached_return_t memcached_set_error(memcached_instance_st& self, memcached_return_t rc, const char *at, const char *str, size_t length)
+{
+  assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
+  assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a Instance");
+
+  memcached_string_t tmp= { str, length };
+  return memcached_set_error(self, rc, at, tmp);
+}
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#endif
+
+memcached_return_t memcached_set_error(Memcached& memc, memcached_return_t rc, const char *at, memcached_string_t& str)
+{
+  assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
+  if (memcached_fatal(rc))
+  {
+    _set(memc, &str, rc, at);
+  }
+
+  return rc;
+}
+
+memcached_return_t memcached_set_parser_error(Memcached& memc,
+                                              const char *at,
+                                              const char *format, ...)
+{
+  va_list args;
+
+  char buffer[BUFSIZ];
+  va_start(args, format);
+  int length= vsnprintf(buffer, sizeof(buffer), format, args);
+  va_end(args);
+
+  return memcached_set_error(memc, MEMCACHED_PARSE_ERROR, at, buffer, length);
+}
+
+static inline size_t append_host_to_string(memcached_instance_st& self, char* buffer, const size_t buffer_length)
+{
+  size_t size= 0;
+  switch (self.type)
+  {
+  case MEMCACHED_CONNECTION_TCP:
+  case MEMCACHED_CONNECTION_UDP:
+    size+= snprintf(buffer, buffer_length, " host: %s:%d",
+                    self.hostname(), int(self.port()));
+    break;
+
+  case MEMCACHED_CONNECTION_UNIX_SOCKET:
+    size+= snprintf(buffer, buffer_length, " socket: %s",
+                    self.hostname());
+    break;
+  }
+
+  return size;
+}
+
+memcached_return_t memcached_set_error(memcached_instance_st& self, memcached_return_t rc, const char *at, memcached_string_t& str)
+{
+  assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
+  assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_instance_st");
+  if (memcached_fatal(rc) == false and rc != MEMCACHED_CLIENT_ERROR)
+  {
+    return rc;
+  }
+
+  char hostname_port_message[MAX_ERROR_LENGTH];
+  char* hostname_port_message_ptr= hostname_port_message;
+  int size= 0;
+  if (str.size)
+  {
+    size= snprintf(hostname_port_message_ptr, sizeof(hostname_port_message), "%.*s, ",
+                   memcached_string_printf(str));
+    hostname_port_message_ptr+= size;
+  }
+
+  size+= append_host_to_string(self, hostname_port_message_ptr, sizeof(hostname_port_message) -size);
+
+  memcached_string_t error_host= { hostname_port_message, size_t(size) };
+
+  assert_msg(self.root, "Programmer error, root was not set on instance");
+  if (self.root)
+  {
+    _set(*self.root, &error_host, rc, at);
+    _set(self, (*self.root));
+    assert(self.error_messages);
+    assert(self.root->error_messages);
+    assert(self.error_messages->rc == self.root->error_messages->rc);
+  }
+
+  return rc;
+}
+
+memcached_return_t memcached_set_error(memcached_instance_st& self, memcached_return_t rc, const char *at)
+{
+  assert_msg(rc != MEMCACHED_SOME_ERRORS, "Programmer error, MEMCACHED_SOME_ERRORS was about to be set on a memcached_instance_st");
+  if (memcached_fatal(rc) == false)
+  {
+    return rc;
+  }
+
+  char hostname_port[MEMCACHED_NI_MAXHOST +MEMCACHED_NI_MAXSERV + sizeof("host : ")];
+  size_t size= append_host_to_string(self, hostname_port, sizeof(hostname_port));
+
+  memcached_string_t error_host= { hostname_port, size};
+
+  if (self.root)
+  {
+    _set(*self.root, &error_host, rc, at);
+    _set(self, *self.root);
+  }
+
+  return rc;
+}
+
+memcached_return_t memcached_set_error(Memcached& self, memcached_return_t rc, const char *at)
+{
+  assert_msg(rc != MEMCACHED_ERRNO, "Programmer error, MEMCACHED_ERRNO was set to be returned to client");
+  if (memcached_fatal(rc) == false)
+  {
+    return rc;
+  }
+
+  _set(self, NULL, rc, at);
+
+  return rc;
+}
+
+memcached_return_t memcached_set_errno(Memcached& self, int local_errno, const char *at, const char *str, size_t length)
+{
+  memcached_string_t tmp= { str, length };
+  return memcached_set_errno(self, local_errno, at, tmp);
+}
+
+memcached_return_t memcached_set_errno(memcached_instance_st& self, int local_errno, const char *at, const char *str, size_t length)
+{
+  memcached_string_t tmp= { str, length };
+  return memcached_set_errno(self, local_errno, at, tmp);
+}
+
+memcached_return_t memcached_set_errno(Memcached& self, int local_errno, const char *at)
+{
+  if (local_errno == 0)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  memcached_return_t rc= MEMCACHED_ERRNO;
+  _set(self, NULL, rc, at, local_errno);
+
+  return rc;
+}
+
+memcached_return_t memcached_set_errno(Memcached& memc, int local_errno, const char *at, memcached_string_t& str)
+{
+  if (local_errno == 0)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  memcached_return_t rc= MEMCACHED_ERRNO;
+  _set(memc, &str, rc, at, local_errno);
+
+  return rc;
+}
+
+memcached_return_t memcached_set_errno(memcached_instance_st& self, int local_errno, const char *at, memcached_string_t& str)
+{
+  if (local_errno == 0)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  char hostname_port_message[MAX_ERROR_LENGTH];
+  char* hostname_port_message_ptr= hostname_port_message;
+  size_t size= 0;
+  if (str.size)
+  {
+    size= snprintf(hostname_port_message_ptr, sizeof(hostname_port_message), "%.*s, ", memcached_string_printf(str));
+  }
+  size+= append_host_to_string(self, hostname_port_message_ptr, sizeof(hostname_port_message) -size);
+
+  memcached_string_t error_host= { hostname_port_message, size };
+
+  memcached_return_t rc= MEMCACHED_ERRNO;
+  if (self.root == NULL)
+  {
+    return rc;
+  }
+
+  _set(*self.root, &error_host, rc, at, local_errno);
+  _set(self, (*self.root));
+
+#if 0
+  if (self.root->error_messages->rc != self.error_messages->rc)
+  {
+    fprintf(stderr, "%s:%d %s != %s\n", __FILE__, __LINE__,
+            memcached_strerror(NULL, self.root->error_messages->rc),
+            memcached_strerror(NULL, self.error_messages->rc));
+  }
+#endif
+
+  return rc;
+}
+
+memcached_return_t memcached_set_errno(memcached_instance_st& self, int local_errno, const char *at)
+{
+  if (local_errno == 0)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  char hostname_port_message[MAX_ERROR_LENGTH];
+  size_t size= append_host_to_string(self, hostname_port_message, sizeof(hostname_port_message));
+
+  memcached_string_t error_host= { hostname_port_message, size };
+
+  memcached_return_t rc= MEMCACHED_ERRNO;
+  if (self.root == NULL)
+  {
+    return rc;
+  }
+
+  _set(*self.root, &error_host, rc, at, local_errno);
+  _set(self, (*self.root));
+
+  return rc;
+}
+
+static void _error_print(const memcached_error_t *error)
+{
+  if (error == NULL)
+  {
+    return;
+  }
+
+  if (error->size == 0)
+  {
+    fprintf(stderr, "\t%s\n", memcached_strerror(NULL, error->rc) );
+  }
+  else
+  {
+    fprintf(stderr, "\t%s %s\n", memcached_strerror(NULL, error->rc), error->message);
+  }
+
+  _error_print(error->next);
+}
+
+void memcached_error_print(const Memcached *shell)
+{
+  const Memcached* self= memcached2Memcached(shell);
+  if (self == NULL)
+  {
+    return;
+  }
+
+  _error_print(self->error_messages);
+
+  for (uint32_t x= 0; x < memcached_server_count(self); x++)
+  {
+    memcached_instance_st* instance= memcached_instance_by_position(self, x);
+
+    _error_print(instance->error_messages);
+  }
+}
+
+static void _error_free(memcached_error_t *error)
+{
+  if (error)
+  {
+    _error_free(error->next);
+
+    libmemcached_free(error->root, error);
+  }
+}
+
+void memcached_error_free(Memcached& self)
+{
+  _error_free(self.error_messages);
+  self.error_messages= NULL;
+}
+
+void memcached_error_free(memcached_instance_st& self)
+{
+  _error_free(self.error_messages);
+  self.error_messages= NULL;
+}
+
+void memcached_error_free(memcached_server_st& self)
+{
+  _error_free(self.error_messages);
+  self.error_messages= NULL;
+}
+
+const char *memcached_error(const memcached_st *memc)
+{
+  return memcached_last_error_message(memc);
+}
+
+const char *memcached_last_error_message(const memcached_st *shell)
+{
+  const Memcached* memc= memcached2Memcached(shell);
+  if (memc)
+  {
+    if (memc->error_messages)
+    {
+      if (memc->error_messages->size and memc->error_messages->message[0])
+      {
+        return memc->error_messages->message;
+      }
+
+      return memcached_strerror(memc, memc->error_messages->rc);
+    }
+
+    return memcached_strerror(memc, MEMCACHED_SUCCESS);
+  }
+
+  return memcached_strerror(memc, MEMCACHED_INVALID_ARGUMENTS);
+}
+
+bool memcached_has_current_error(Memcached &memc)
+{
+  if (memc.error_messages 
+      and memc.error_messages->query_id == memc.query_id
+      and memcached_failed(memc.error_messages->rc))
+  {
+    return true;
+  }
+
+  return false;
+}
+
+bool memcached_has_current_error(memcached_instance_st& server)
+{
+  return memcached_has_current_error(*(server.root));
+}
+
+memcached_return_t memcached_last_error(const memcached_st *shell)
+{
+  const Memcached* memc= memcached2Memcached(shell);
+  if (memc)
+  {
+    if (memc->error_messages)
+    {
+      return memc->error_messages->rc;
+    }
+
+    return MEMCACHED_SUCCESS;
+  }
+
+  return MEMCACHED_INVALID_ARGUMENTS;
+}
+
+int memcached_last_error_errno(const memcached_st *shell)
+{
+  const Memcached* memc= memcached2Memcached(shell);
+  if (memc == NULL)
+  {
+    return 0;
+  }
+
+  if (memc->error_messages == NULL)
+  {
+    return 0;
+  }
+
+  return memc->error_messages->local_errno;
+}
+
+const char *memcached_server_error(const memcached_instance_st * server)
+{
+  if (server == NULL)
+  {
+    return NULL;
+  }
+
+  if (server->error_messages == NULL)
+  {
+    return memcached_strerror(server->root, MEMCACHED_SUCCESS);
+  }
+
+  if (server->error_messages->size == 0)
+  {
+    return memcached_strerror(server->root, server->error_messages->rc);
+  }
+
+  return server->error_messages->message;
+}
+
+
+memcached_error_t *memcached_error_copy(const memcached_instance_st& server)
+{
+  if (server.error_messages == NULL)
+  {
+    return NULL;
+  }
+
+  memcached_error_t *error= libmemcached_xmalloc(server.root, memcached_error_t);
+  memcpy(error, server.error_messages, sizeof(memcached_error_t));
+  error->next= NULL;
+
+  return error;
+}
+
+memcached_return_t memcached_server_error_return(const memcached_instance_st * ptr)
+{
+  if (ptr == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  if (ptr->error_messages)
+  {
+    return ptr->error_messages->rc;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_instance_error_return(memcached_instance_st* instance)
+{
+  if (instance == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  if (instance->error_messages)
+  {
+    return instance->error_messages->rc;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
diff --git a/src/libmemcached/error.hpp b/src/libmemcached/error.hpp
new file mode 100644 (file)
index 0000000..847dbc2
--- /dev/null
@@ -0,0 +1,90 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libmemcached/common.h"
+
+#pragma once
+
+#ifdef __cplusplus
+
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+#define MEMCACHED_AT __FILE__ ":" TOSTRING(__LINE__)
+
+memcached_return_t memcached_set_parser_error(Memcached& memc,
+                                              const char *at,
+                                              const char *format, ...);
+
+memcached_return_t memcached_set_error(Memcached&, memcached_return_t rc, const char *at);
+
+memcached_return_t memcached_set_error(memcached_instance_st&, memcached_return_t rc, const char *at);
+
+memcached_return_t memcached_set_error(Memcached&, memcached_return_t rc, const char *at, const char *str, size_t length);
+
+memcached_return_t memcached_set_error(memcached_instance_st&, memcached_return_t rc, const char *at, const char *str, size_t length);
+
+memcached_return_t memcached_set_error(Memcached& memc, memcached_return_t rc, const char *at, memcached_string_t& str);
+
+memcached_return_t memcached_set_error(memcached_instance_st&, memcached_return_t rc, const char *at, memcached_string_t& str);
+
+memcached_return_t memcached_set_errno(Memcached& memc, int local_errno, const char *at, memcached_string_t& str);
+
+memcached_return_t memcached_set_errno(memcached_instance_st&, int local_errno, const char *at, memcached_string_t& str);
+
+memcached_return_t memcached_set_errno(Memcached& memc, int local_errno, const char *at, const char *str, size_t length);
+
+memcached_return_t memcached_set_errno(memcached_instance_st&, int local_errno, const char *at, const char *str, size_t length);
+
+memcached_return_t memcached_set_errno(Memcached& memc, int local_errno, const char *at);
+
+memcached_return_t memcached_set_errno(memcached_instance_st&, int local_errno, const char *at);
+
+bool memcached_has_current_error(Memcached&);
+
+bool memcached_has_current_error(memcached_instance_st&);
+
+void memcached_error_free(Memcached&);
+
+void memcached_error_free(memcached_server_st&);
+
+void memcached_error_free(memcached_instance_st& self);
+
+memcached_error_t *memcached_error_copy(const memcached_instance_st&);
+
+memcached_return_t memcached_instance_error_return(memcached_instance_st*);
+
+#endif
diff --git a/src/libmemcached/exist.cc b/src/libmemcached/exist.cc
new file mode 100644 (file)
index 0000000..5cb99e6
--- /dev/null
@@ -0,0 +1,159 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+static memcached_return_t ascii_exist(Memcached *memc, memcached_instance_st* instance, const char *key, size_t key_length)
+{
+  libmemcached_io_vector_st vector[]=
+  {
+    { NULL, 0 },
+    { memcached_literal_param("add ") },
+    { memcached_array_string(memc->_namespace), memcached_array_size(memc->_namespace) },
+    { key, key_length },
+    { memcached_literal_param(" 0") },
+    { memcached_literal_param(" 2678400") },
+    { memcached_literal_param(" 0") },
+    { memcached_literal_param("\r\n") },
+    { memcached_literal_param("\r\n") }
+  };
+
+  /* Send command header */
+  memcached_return_t rc;
+  if (memcached_fatal(rc= memcached_vdo(instance, vector, 9, true)))
+  {
+    return rc;
+  }
+
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+  rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+
+  if (rc == MEMCACHED_NOTSTORED)
+  {
+    rc= MEMCACHED_SUCCESS;
+  }
+
+  if (rc == MEMCACHED_STORED)
+  {
+    rc= MEMCACHED_NOTFOUND;
+  }
+
+  return rc;
+}
+
+static memcached_return_t binary_exist(Memcached *memc, memcached_instance_st* instance, const char *key, size_t key_length)
+{
+  protocol_binary_request_set request= {};
+  size_t send_length= sizeof(request.bytes);
+
+  initialize_binary_request(instance, request.message.header);
+
+  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_ADD;
+  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(memc->_namespace)));
+  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+  request.message.header.request.extlen= 8;
+  request.message.body.flags= 0;
+  request.message.body.expiration= htonl(2678400);
+
+  request.message.header.request.bodylen= htonl((uint32_t) (key_length 
+                                                            +memcached_array_size(memc->_namespace)
+                                                            +request.message.header.request.extlen));
+
+  libmemcached_io_vector_st vector[]=
+  {
+    { NULL, 0 },
+    { request.bytes, send_length },
+    { memcached_array_string(memc->_namespace), memcached_array_size(memc->_namespace) },
+    { key, key_length }
+  };
+
+  /* write the header */
+  memcached_return_t rc;
+  if (memcached_fatal(rc= memcached_vdo(instance, vector, 4, true)))
+  {
+    return rc;
+  }
+
+  rc= memcached_response(instance, NULL, 0, NULL);
+
+  if (rc == MEMCACHED_SUCCESS)
+  {
+    rc= MEMCACHED_NOTFOUND;
+  }
+
+  if (rc == MEMCACHED_DATA_EXISTS)
+  {
+    rc= MEMCACHED_SUCCESS;
+  }
+
+  return rc;
+}
+
+memcached_return_t memcached_exist(memcached_st *memc, const char *key, size_t key_length)
+{
+  return memcached_exist_by_key(memc, key, key_length, key, key_length);
+}
+
+memcached_return_t memcached_exist_by_key(memcached_st *shell,
+                                          const char *group_key, size_t group_key_length,
+                                          const char *key, size_t key_length)
+{
+  Memcached* memc= memcached2Memcached(shell);
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(memc, true)))
+  {
+    return rc;
+  }
+
+  if (memcached_is_udp(memc))
+  {
+    return memcached_set_error(*memc, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+  }
+
+  uint32_t server_key= memcached_generate_hash_with_redistribution(memc, group_key, group_key_length);
+  memcached_instance_st* instance= memcached_instance_fetch(memc, server_key);
+
+  if (memcached_is_binary(memc))
+  {
+    rc= binary_exist(memc, instance, key, key_length);
+  }
+  else
+  {
+    rc= ascii_exist(memc, instance, key, key_length);
+  }
+
+  return rc;
+}
diff --git a/src/libmemcached/fetch.cc b/src/libmemcached/fetch.cc
new file mode 100644 (file)
index 0000000..d795109
--- /dev/null
@@ -0,0 +1,320 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+char *memcached_fetch(memcached_st *shell, char *key, size_t *key_length, 
+                      size_t *value_length, 
+                      uint32_t *flags,
+                      memcached_return_t *error)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  memcached_return_t unused;
+  if (error == NULL)
+  {
+    error= &unused;
+  }
+
+  if (memcached_is_udp(ptr))
+  {
+    if (value_length)
+    {
+      *value_length= 0;
+    }
+
+    if (key_length)
+    {
+      *key_length= 0;
+    }
+
+    if (flags)
+    {
+      *flags= 0;
+    }
+
+    if (key)
+    {
+      *key= 0;
+    }
+
+    *error= MEMCACHED_NOT_SUPPORTED;
+    return NULL;
+  }
+
+  memcached_result_st *result_buffer= &ptr->result;
+  result_buffer= memcached_fetch_result(ptr, result_buffer, error);
+  if (result_buffer == NULL or memcached_failed(*error))
+  {
+    WATCHPOINT_ASSERT(result_buffer == NULL);
+    if (value_length)
+    {
+      *value_length= 0;
+    }
+
+    if (key_length)
+    {
+      *key_length= 0;
+    }
+
+    if (flags)
+    {
+      *flags= 0;
+    }
+
+    if (key)
+    {
+      *key= 0;
+    }
+
+    return NULL;
+  }
+
+  if (value_length)
+  {
+    *value_length= memcached_string_length(&result_buffer->value);
+  }
+
+  if (key)
+  {
+    if (result_buffer->key_length > MEMCACHED_MAX_KEY)
+    {
+      *error= MEMCACHED_KEY_TOO_BIG;
+      if (value_length)
+      {
+        *value_length= 0;
+      }
+
+      if (key_length)
+      {
+        *key_length= 0;
+      }
+
+      if (flags)
+      {
+        *flags= 0;
+      }
+
+      if (key)
+      {
+        *key= 0;
+      }
+
+      return NULL;
+    }
+
+    strncpy(key, result_buffer->item_key, result_buffer->key_length); // For the binary protocol we will cut off the key :(
+    if (key_length)
+    {
+      *key_length= result_buffer->key_length;
+    }
+  }
+
+  if (flags)
+  {
+    *flags= result_buffer->item_flags;
+  }
+
+  return memcached_string_take_value(&result_buffer->value);
+}
+
+memcached_result_st *memcached_fetch_result(memcached_st *ptr,
+                                            memcached_result_st *result,
+                                            memcached_return_t *error)
+{
+  memcached_return_t unused;
+  if (error == NULL)
+  {
+    error= &unused;
+  }
+
+  if (ptr == NULL)
+  {
+    *error= MEMCACHED_INVALID_ARGUMENTS;
+    return NULL;
+  }
+
+  if (memcached_is_udp(ptr))
+  {
+    *error= MEMCACHED_NOT_SUPPORTED;
+    return NULL;
+  }
+
+  if (result == NULL)
+  {
+    // If we have already initialized (ie it is in use) our internal, we
+    // create one.
+    if (memcached_is_initialized(&ptr->result))
+    {
+      if ((result= memcached_result_create(ptr, NULL)) == NULL)
+      {
+        *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+        return NULL;
+      }
+    }
+    else
+    {
+      result= memcached_result_create(ptr, &ptr->result);
+    }
+  }
+
+  *error= MEMCACHED_MAXIMUM_RETURN; // We use this to see if we ever go into the loop
+  memcached_instance_st *server;
+  memcached_return_t read_ret= MEMCACHED_SUCCESS;
+  bool connection_failures= false;
+  while ((server= memcached_io_get_readable_server(ptr, read_ret)))
+  {
+    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+    *error= memcached_response(server, buffer, sizeof(buffer), result);
+
+    if (*error == MEMCACHED_IN_PROGRESS)
+    {
+      continue;
+    }
+    else if (*error == MEMCACHED_CONNECTION_FAILURE)
+    {
+      connection_failures= true;
+      continue;
+    }
+    else if (*error == MEMCACHED_SUCCESS)
+    {
+      result->count++;
+      return result;
+    }
+    else if (*error == MEMCACHED_END)
+    {
+      memcached_server_response_reset(server);
+    }
+    else if (*error != MEMCACHED_NOTFOUND)
+    {
+      break;
+    }
+  }
+
+  if (*error == MEMCACHED_NOTFOUND and result->count)
+  {
+    *error= MEMCACHED_END;
+  }
+  else if (*error == MEMCACHED_MAXIMUM_RETURN and result->count)
+  {
+    *error= MEMCACHED_END;
+  }
+  else if (*error == MEMCACHED_MAXIMUM_RETURN) // while() loop was never entered
+  {
+    *error= MEMCACHED_NOTFOUND;
+  }
+  else if (connection_failures)
+  {
+    /*  
+        If we have a connection failure to some servers, the caller may
+        wish to treat that differently to getting a definitive NOT_FOUND
+        from all servers, so return MEMCACHED_CONNECTION_FAILURE to allow
+        that. 
+        */
+    *error= MEMCACHED_CONNECTION_FAILURE;
+  }
+  else if (*error == MEMCACHED_SUCCESS)
+  {
+    *error= MEMCACHED_END;
+  }
+  else if (result->count == 0)
+  {
+    *error= MEMCACHED_NOTFOUND;
+  }
+
+  /* We have completed reading data */
+  if (memcached_is_allocated(result))
+  {
+    memcached_result_free(result);
+  }
+  else
+  {
+    result->count= 0;
+    memcached_string_reset(&result->value);
+  }
+
+  return NULL;
+}
+
+memcached_return_t memcached_fetch_execute(memcached_st *shell, 
+                                           memcached_execute_fn *callback,
+                                           void *context,
+                                           uint32_t number_of_callbacks)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  memcached_result_st *result= &ptr->result;
+  memcached_return_t rc;
+  bool some_errors= false;
+
+  while ((result= memcached_fetch_result(ptr, result, &rc)))
+  {
+    if (memcached_failed(rc) and rc == MEMCACHED_NOTFOUND)
+    {
+      continue;
+    }
+    else if (memcached_failed(rc))
+    {
+      memcached_set_error(*ptr, rc, MEMCACHED_AT);
+      some_errors= true;
+      continue;
+    }
+
+    for (uint32_t x= 0; x < number_of_callbacks; x++)
+    {
+      memcached_return_t ret= (*callback[x])(ptr, result, context);
+      if (memcached_failed(ret))
+      {
+        some_errors= true;
+        memcached_set_error(*ptr, ret, MEMCACHED_AT);
+        break;
+      }
+    }
+  }
+
+  if (some_errors)
+  {
+    return MEMCACHED_SOME_ERRORS;
+  }
+
+  // If we were able to run all keys without issue we return
+  // MEMCACHED_SUCCESS
+  if (memcached_success(rc))
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  return rc;
+}
diff --git a/src/libmemcached/flag.cc b/src/libmemcached/flag.cc
new file mode 100644 (file)
index 0000000..09b401e
--- /dev/null
@@ -0,0 +1,156 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+bool memcached_flag(const memcached_st& memc, const memcached_flag_t flag)
+{
+  switch (flag)
+  {
+  case MEMCACHED_FLAG_AUTO_EJECT_HOSTS:
+    return memcached_is_auto_eject_hosts(&memc);
+
+  case MEMCACHED_FLAG_BINARY_PROTOCOL:
+    return memcached_is_binary(&memc);
+
+  case MEMCACHED_FLAG_BUFFER_REQUESTS:
+    return memcached_is_buffering(&memc);
+
+  case MEMCACHED_FLAG_HASH_WITH_NAMESPACE:
+    return memcached_is_hash_with_namespace(&memc);
+
+  case MEMCACHED_FLAG_NO_BLOCK:
+    return memcached_is_no_block(&memc);
+
+  case MEMCACHED_FLAG_REPLY:
+    return memcached_is_replying(&memc);
+
+  case MEMCACHED_FLAG_RANDOMIZE_REPLICA_READ:
+    return memcached_is_randomize_replica_read(&memc);
+
+  case MEMCACHED_FLAG_SUPPORT_CAS:
+    return memcached_is_cas(&memc);
+
+  case MEMCACHED_FLAG_TCP_NODELAY:
+    return memcached_is_tcp_nodelay(&memc);
+
+  case MEMCACHED_FLAG_USE_SORT_HOSTS:
+    return memcached_is_use_sort_hosts(&memc);
+
+  case MEMCACHED_FLAG_USE_UDP:
+    return memcached_is_udp(&memc);
+
+  case MEMCACHED_FLAG_VERIFY_KEY:
+    return memcached_is_verify_key(&memc);
+
+  case MEMCACHED_FLAG_TCP_KEEPALIVE:
+    return memcached_is_use_sort_hosts(&memc);
+
+  case MEMCACHED_FLAG_IS_AES:
+    return memcached_is_aes(&memc);
+
+  case MEMCACHED_FLAG_IS_FETCHING_VERSION:
+    return memcached_is_fetching_version(&memc);
+  }
+
+  abort();
+}
+
+void memcached_flag(memcached_st& memc, const memcached_flag_t flag, const bool arg)
+{
+  switch (flag)
+  {
+  case MEMCACHED_FLAG_AUTO_EJECT_HOSTS:
+    memcached_set_auto_eject_hosts(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_BINARY_PROTOCOL:
+    memcached_set_binary(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_BUFFER_REQUESTS:
+    memcached_set_buffering(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_HASH_WITH_NAMESPACE:
+    memcached_set_hash_with_namespace(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_NO_BLOCK:
+    memcached_set_no_block(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_REPLY:
+    memcached_set_replying(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_RANDOMIZE_REPLICA_READ:
+    memcached_set_randomize_replica_read(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_SUPPORT_CAS:
+    memcached_set_cas(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_TCP_NODELAY:
+    memcached_set_tcp_nodelay(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_USE_SORT_HOSTS:
+    memcached_set_use_sort_hosts(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_USE_UDP:
+    memcached_set_udp(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_VERIFY_KEY:
+    memcached_set_verify_key(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_TCP_KEEPALIVE:
+    memcached_set_use_sort_hosts(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_IS_AES:
+    memcached_set_aes(memc, arg);
+    break;
+
+  case MEMCACHED_FLAG_IS_FETCHING_VERSION:
+    memcached_set_fetching_version(memc, arg);
+    break;
+  }
+}
diff --git a/src/libmemcached/flag.hpp b/src/libmemcached/flag.hpp
new file mode 100644 (file)
index 0000000..6efe2ef
--- /dev/null
@@ -0,0 +1,59 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+enum memcached_flag_t
+{
+  MEMCACHED_FLAG_AUTO_EJECT_HOSTS,
+  MEMCACHED_FLAG_BINARY_PROTOCOL,
+  MEMCACHED_FLAG_BUFFER_REQUESTS,
+  MEMCACHED_FLAG_HASH_WITH_NAMESPACE,
+  MEMCACHED_FLAG_NO_BLOCK,
+  MEMCACHED_FLAG_REPLY,
+  MEMCACHED_FLAG_RANDOMIZE_REPLICA_READ,
+  MEMCACHED_FLAG_SUPPORT_CAS,
+  MEMCACHED_FLAG_TCP_NODELAY,
+  MEMCACHED_FLAG_USE_SORT_HOSTS,
+  MEMCACHED_FLAG_USE_UDP,
+  MEMCACHED_FLAG_VERIFY_KEY,
+  MEMCACHED_FLAG_TCP_KEEPALIVE,
+  MEMCACHED_FLAG_IS_AES,
+  MEMCACHED_FLAG_IS_FETCHING_VERSION
+};
+
+bool memcached_flag(const memcached_st&, const memcached_flag_t);
+void memcached_flag(memcached_st&, const memcached_flag_t, const bool);
diff --git a/src/libmemcached/flush.cc b/src/libmemcached/flush.cc
new file mode 100644 (file)
index 0000000..9702771
--- /dev/null
@@ -0,0 +1,172 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+static memcached_return_t memcached_flush_binary(Memcached *ptr, 
+                                                 time_t expiration,
+                                                 const bool reply)
+{
+  protocol_binary_request_flush request= {};
+
+  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
+  request.message.header.request.extlen= 4;
+  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+  request.message.header.request.bodylen= htonl(request.message.header.request.extlen);
+  request.message.body.expiration= htonl((uint32_t) expiration);
+
+  memcached_return_t rc= MEMCACHED_SUCCESS;
+
+  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
+  {
+    memcached_instance_st* instance= memcached_instance_fetch(ptr, x);
+    initialize_binary_request(instance, request.message.header);
+
+    if (reply)
+    {
+      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
+    }
+    else
+    {
+      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSHQ;
+    }
+
+    libmemcached_io_vector_st vector[]=
+    {
+      { NULL, 0 },
+      { request.bytes, sizeof(request.bytes) }
+    };
+
+    memcached_return_t rrc;
+    if (memcached_failed(rrc= memcached_vdo(instance, vector, 2, true)))
+    {
+      if (instance->error_messages == NULL or instance->root->error_messages == NULL)
+      {
+        memcached_set_error(*instance, rrc, MEMCACHED_AT);
+      }
+      rc= MEMCACHED_SOME_ERRORS;
+    } 
+  }
+
+  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
+  {
+    memcached_instance_st* instance= memcached_instance_fetch(ptr, x);
+
+    if (instance->response_count() > 0)
+    {
+      (void)memcached_response(instance, NULL, 0, NULL);
+    }
+  }
+
+  return rc;
+}
+
+static memcached_return_t memcached_flush_textual(Memcached *ptr, 
+                                                  time_t expiration,
+                                                  const bool reply)
+{
+  char buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+  int send_length= 0;
+  if (expiration)
+  {
+    send_length= snprintf(buffer, sizeof(buffer), "%llu", (unsigned long long)expiration);
+  }
+
+  if (size_t(send_length) >= sizeof(buffer) or send_length < 0)
+  {
+    return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                               memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
+  }
+
+  memcached_return_t rc= MEMCACHED_SUCCESS;
+  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
+  {
+    memcached_instance_st* instance= memcached_instance_fetch(ptr, x);
+
+    libmemcached_io_vector_st vector[]=
+    {
+      { NULL, 0 },
+      { memcached_literal_param("flush_all ") },
+      { buffer, size_t(send_length) },
+      { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
+      { memcached_literal_param("\r\n") }
+    };
+
+    memcached_return_t rrc= memcached_vdo(instance, vector, 5, true);
+    if (memcached_success(rrc) and reply == true)
+    {
+      char response_buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+      rrc= memcached_response(instance, response_buffer, sizeof(response_buffer), NULL);
+    }
+
+    if (memcached_failed(rrc))
+    {
+      // If an error has already been reported, then don't add to it
+      if (instance->error_messages == NULL or instance->root->error_messages == NULL)
+      {
+        memcached_set_error(*instance, rrc, MEMCACHED_AT);
+      }
+      rc= MEMCACHED_SOME_ERRORS;
+    }
+  }
+
+  return rc;
+}
+
+memcached_return_t memcached_flush(memcached_st *shell, time_t expiration)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(ptr, true)))
+  {
+    return rc;
+  }
+
+  bool reply= memcached_is_replying(ptr);
+
+  LIBMEMCACHED_MEMCACHED_FLUSH_START();
+  if (memcached_is_binary(ptr))
+  {
+    rc= memcached_flush_binary(ptr, expiration, reply);
+  }
+  else
+  {
+    rc= memcached_flush_textual(ptr, expiration, reply);
+  }
+  LIBMEMCACHED_MEMCACHED_FLUSH_END();
+
+  return rc;
+}
diff --git a/src/libmemcached/flush_buffers.cc b/src/libmemcached/flush_buffers.cc
new file mode 100644 (file)
index 0000000..24f7c0d
--- /dev/null
@@ -0,0 +1,71 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+memcached_return_t memcached_flush_buffers(memcached_st *shell)
+{
+  Memcached* memc= memcached2Memcached(shell);
+  if (memc)
+  {
+    memcached_return_t ret= MEMCACHED_SUCCESS;
+
+    for (uint32_t x= 0; x < memcached_server_count(memc); ++x)
+    {
+      memcached_instance_st* instance= memcached_instance_fetch(memc, x);
+
+      if (instance->write_buffer_offset != 0) 
+      {
+        if (instance->fd == INVALID_SOCKET and
+            (ret= memcached_connect(instance)) != MEMCACHED_SUCCESS)
+        {
+          WATCHPOINT_ERROR(ret);
+          return ret;
+        }
+
+        if (memcached_io_write(instance) == false)
+        {
+          ret= MEMCACHED_SOME_ERRORS;
+        }
+      }
+    }
+
+    return ret;
+  }
+
+  return MEMCACHED_INVALID_ARGUMENTS;
+}
diff --git a/src/libmemcached/get.cc b/src/libmemcached/get.cc
new file mode 100644 (file)
index 0000000..86d8cf2
--- /dev/null
@@ -0,0 +1,738 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+/*
+  What happens if no servers exist?
+*/
+char *memcached_get(memcached_st *ptr, const char *key,
+                    size_t key_length,
+                    size_t *value_length,
+                    uint32_t *flags,
+                    memcached_return_t *error)
+{
+  return memcached_get_by_key(ptr, NULL, 0, key, key_length, value_length,
+                              flags, error);
+}
+
+static memcached_return_t __mget_by_key_real(memcached_st *ptr,
+                                             const char *group_key,
+                                             size_t group_key_length,
+                                             const char * const *keys,
+                                             const size_t *key_length,
+                                             size_t number_of_keys,
+                                             const bool mget_mode);
+char *memcached_get_by_key(memcached_st *shell,
+                           const char *group_key,
+                           size_t group_key_length,
+                           const char *key, size_t key_length,
+                           size_t *value_length,
+                           uint32_t *flags,
+                           memcached_return_t *error)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  memcached_return_t unused;
+  if (error == NULL)
+  {
+    error= &unused;
+  }
+
+  uint64_t query_id= 0;
+  if (ptr)
+  {
+    query_id= ptr->query_id;
+  }
+
+  /* Request the key */
+  *error= __mget_by_key_real(ptr, group_key, group_key_length,
+                             (const char * const *)&key, &key_length, 
+                             1, false);
+  if (ptr)
+  {
+    assert_msg(ptr->query_id == query_id +1, "Programmer error, the query_id was not incremented.");
+  }
+
+  if (memcached_failed(*error))
+  {
+    if (ptr)
+    {
+      if (memcached_has_current_error(*ptr)) // Find the most accurate error
+      {
+        *error= memcached_last_error(ptr);
+      }
+    }
+
+    if (value_length) 
+    {
+      *value_length= 0;
+    }
+
+    return NULL;
+  }
+
+  char *value= memcached_fetch(ptr, NULL, NULL,
+                               value_length, flags, error);
+  assert_msg(ptr->query_id == query_id +1, "Programmer error, the query_id was not incremented.");
+
+  /* This is for historical reasons */
+  if (*error == MEMCACHED_END)
+  {
+    *error= MEMCACHED_NOTFOUND;
+  }
+  if (value == NULL)
+  {
+    if (ptr->get_key_failure and *error == MEMCACHED_NOTFOUND)
+    {
+      memcached_result_st key_failure_result;
+      memcached_result_st* result_ptr= memcached_result_create(ptr, &key_failure_result);
+      memcached_return_t rc= ptr->get_key_failure(ptr, key, key_length, result_ptr);
+
+      /* On all failure drop to returning NULL */
+      if (rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED)
+      {
+        if (rc == MEMCACHED_BUFFERED)
+        {
+          uint64_t latch; /* We use latch to track the state of the original socket */
+          latch= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS);
+          if (latch == 0)
+          {
+            memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1);
+          }
+
+          rc= memcached_set(ptr, key, key_length,
+                            (memcached_result_value(result_ptr)),
+                            (memcached_result_length(result_ptr)),
+                            0,
+                            (memcached_result_flags(result_ptr)));
+
+          if (rc == MEMCACHED_BUFFERED and latch == 0)
+          {
+            memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 0);
+          }
+        }
+        else
+        {
+          rc= memcached_set(ptr, key, key_length,
+                            (memcached_result_value(result_ptr)),
+                            (memcached_result_length(result_ptr)),
+                            0,
+                            (memcached_result_flags(result_ptr)));
+        }
+
+        if (rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED)
+        {
+          *error= rc;
+          *value_length= memcached_result_length(result_ptr);
+          *flags= memcached_result_flags(result_ptr);
+          char *result_value=  memcached_string_take_value(&result_ptr->value);
+          memcached_result_free(result_ptr);
+
+          return result_value;
+        }
+      }
+
+      memcached_result_free(result_ptr);
+    }
+    assert_msg(ptr->query_id == query_id +1, "Programmer error, the query_id was not incremented.");
+
+    return NULL;
+  }
+
+  return value;
+}
+
+memcached_return_t memcached_mget(memcached_st *ptr,
+                                  const char * const *keys,
+                                  const size_t *key_length,
+                                  size_t number_of_keys)
+{
+  return memcached_mget_by_key(ptr, NULL, 0, keys, key_length, number_of_keys);
+}
+
+static memcached_return_t binary_mget_by_key(memcached_st *ptr,
+                                             const uint32_t master_server_key,
+                                             const bool is_group_key_set,
+                                             const char * const *keys,
+                                             const size_t *key_length,
+                                             const size_t number_of_keys,
+                                             const bool mget_mode);
+
+static memcached_return_t __mget_by_key_real(memcached_st *ptr,
+                                             const char *group_key,
+                                             const size_t group_key_length,
+                                             const char * const *keys,
+                                             const size_t *key_length,
+                                             size_t number_of_keys,
+                                             const bool mget_mode)
+{
+  bool failures_occured_in_sending= false;
+  const char *get_command= "get";
+  uint8_t get_command_length= 3;
+  unsigned int master_server_key= (unsigned int)-1; /* 0 is a valid server id! */
+
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(ptr, true)))
+  {
+    return rc;
+  }
+
+  if (memcached_is_udp(ptr))
+  {
+    return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+  }
+
+  LIBMEMCACHED_MEMCACHED_MGET_START();
+
+  if (number_of_keys == 0)
+  {
+    return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Numbers of keys provided was zero"));
+  }
+
+  if (memcached_failed((rc= memcached_key_test(*ptr, keys, key_length, number_of_keys))))
+  {
+    assert(memcached_last_error(ptr) == rc);
+
+    return rc;
+  }
+
+  bool is_group_key_set= false;
+  if (group_key and group_key_length)
+  {
+    master_server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+    is_group_key_set= true;
+  }
+
+  /*
+    Here is where we pay for the non-block API. We need to remove any data sitting
+    in the queue before we start our get.
+
+    It might be optimum to bounce the connection if count > some number.
+  */
+  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
+  {
+    memcached_instance_st* instance= memcached_instance_fetch(ptr, x);
+
+    if (instance->response_count())
+    {
+      char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+
+      if (ptr->flags.no_block)
+      {
+        memcached_io_write(instance);
+      }
+
+      while(instance->response_count())
+      {
+        (void)memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, &ptr->result);
+      }
+    }
+  }
+
+  if (memcached_is_binary(ptr))
+  {
+    return binary_mget_by_key(ptr, master_server_key, is_group_key_set, keys,
+                              key_length, number_of_keys, mget_mode);
+  }
+
+  if (ptr->flags.support_cas)
+  {
+    get_command= "gets";
+    get_command_length= 4;
+  }
+
+  /*
+    If a server fails we warn about errors and start all over with sending keys
+    to the server.
+  */
+  WATCHPOINT_ASSERT(rc == MEMCACHED_SUCCESS);
+  size_t hosts_connected= 0;
+  for (uint32_t x= 0; x < number_of_keys; x++)
+  {
+    uint32_t server_key;
+
+    if (is_group_key_set)
+    {
+      server_key= master_server_key;
+    }
+    else
+    {
+      server_key= memcached_generate_hash_with_redistribution(ptr, keys[x], key_length[x]);
+    }
+
+    memcached_instance_st* instance= memcached_instance_fetch(ptr, server_key);
+
+    libmemcached_io_vector_st vector[]=
+    {
+      { get_command, get_command_length },
+      { memcached_literal_param(" ") },
+      { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+      { keys[x], key_length[x] }
+    };
+
+
+    if (instance->response_count() == 0)
+    {
+      rc= memcached_connect(instance);
+
+      if (memcached_failed(rc))
+      {
+        memcached_set_error(*instance, rc, MEMCACHED_AT);
+        continue;
+      }
+      hosts_connected++;
+
+      if ((memcached_io_writev(instance, vector, 1, false)) == false)
+      {
+        failures_occured_in_sending= true;
+        continue;
+      }
+      WATCHPOINT_ASSERT(instance->cursor_active_ == 0);
+      memcached_instance_response_increment(instance);
+      WATCHPOINT_ASSERT(instance->cursor_active_ == 1);
+    }
+
+    {
+      if ((memcached_io_writev(instance, (vector + 1), 3, false)) == false)
+      {
+        memcached_instance_response_reset(instance);
+        failures_occured_in_sending= true;
+        continue;
+      }
+    }
+  }
+
+  if (hosts_connected == 0)
+  {
+    LIBMEMCACHED_MEMCACHED_MGET_END();
+
+    if (memcached_failed(rc))
+    {
+      return rc;
+    }
+
+    return memcached_set_error(*ptr, MEMCACHED_NO_SERVERS, MEMCACHED_AT);
+  }
+
+
+  /*
+    Should we muddle on if some servers are dead?
+  */
+  bool success_happened= false;
+  for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
+  {
+    memcached_instance_st* instance= memcached_instance_fetch(ptr, x);
+
+    if (instance->response_count())
+    {
+      /* We need to do something about non-connnected hosts in the future */
+      if ((memcached_io_write(instance, "\r\n", 2, true)) == -1)
+      {
+        failures_occured_in_sending= true;
+      }
+      else
+      {
+        success_happened= true;
+      }
+    }
+  }
+
+  LIBMEMCACHED_MEMCACHED_MGET_END();
+
+  if (failures_occured_in_sending and success_happened)
+  {
+    return MEMCACHED_SOME_ERRORS;
+  }
+
+  if (success_happened)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  return MEMCACHED_FAILURE; // Complete failure occurred
+}
+
+memcached_return_t memcached_mget_by_key(memcached_st *shell,
+                                         const char *group_key,
+                                         size_t group_key_length,
+                                         const char * const *keys,
+                                         const size_t *key_length,
+                                         size_t number_of_keys)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  return __mget_by_key_real(ptr, group_key, group_key_length, keys, key_length, number_of_keys, true);
+}
+
+memcached_return_t memcached_mget_execute(memcached_st *ptr,
+                                          const char * const *keys,
+                                          const size_t *key_length,
+                                          size_t number_of_keys,
+                                          memcached_execute_fn *callback,
+                                          void *context,
+                                          unsigned int number_of_callbacks)
+{
+  return memcached_mget_execute_by_key(ptr, NULL, 0, keys, key_length,
+                                       number_of_keys, callback,
+                                       context, number_of_callbacks);
+}
+
+memcached_return_t memcached_mget_execute_by_key(memcached_st *shell,
+                                                 const char *group_key,
+                                                 size_t group_key_length,
+                                                 const char * const *keys,
+                                                 const size_t *key_length,
+                                                 size_t number_of_keys,
+                                                 memcached_execute_fn *callback,
+                                                 void *context,
+                                                 unsigned int number_of_callbacks)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(ptr, false)))
+  {
+    return rc;
+  }
+
+  if (memcached_is_udp(ptr))
+  {
+    return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+  }
+
+  if (memcached_is_binary(ptr) == false)
+  {
+    return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT,
+                               memcached_literal_param("ASCII protocol is not supported for memcached_mget_execute_by_key()"));
+  }
+
+  memcached_callback_st *original_callbacks= ptr->callbacks;
+  memcached_callback_st cb= {
+    callback,
+    context,
+    number_of_callbacks
+  };
+
+  ptr->callbacks= &cb;
+  rc= memcached_mget_by_key(ptr, group_key, group_key_length, keys,
+                            key_length, number_of_keys);
+  ptr->callbacks= original_callbacks;
+
+  return rc;
+}
+
+static memcached_return_t simple_binary_mget(memcached_st *ptr,
+                                             const uint32_t master_server_key,
+                                             bool is_group_key_set,
+                                             const char * const *keys,
+                                             const size_t *key_length,
+                                             const size_t number_of_keys, const bool mget_mode)
+{
+  memcached_return_t rc= MEMCACHED_NOTFOUND;
+
+  bool flush= (number_of_keys == 1);
+
+  if (memcached_failed(rc= memcached_key_test(*ptr, keys, key_length, number_of_keys)))
+  {
+    return rc;
+  }
+
+  /*
+    If a server fails we warn about errors and start all over with sending keys
+    to the server.
+  */
+  for (uint32_t x= 0; x < number_of_keys; ++x)
+  {
+    uint32_t server_key;
+
+    if (is_group_key_set)
+    {
+      server_key= master_server_key;
+    }
+    else
+    {
+      server_key= memcached_generate_hash_with_redistribution(ptr, keys[x], key_length[x]);
+    }
+
+    memcached_instance_st* instance= memcached_instance_fetch(ptr, server_key);
+
+    if (instance->response_count() == 0)
+    {
+      rc= memcached_connect(instance);
+      if (memcached_failed(rc))
+      {
+        continue;
+      }
+    }
+
+    protocol_binary_request_getk request= { }; //= {.bytes= {0}};
+    initialize_binary_request(instance, request.message.header);
+    if (mget_mode)
+    {
+      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETKQ;
+    }
+    else
+    {
+      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
+    }
+
+#if 0
+    {
+      memcached_return_t vk= memcached_validate_key_length(key_length[x], ptr->flags.binary_protocol);
+      if (memcached_failed(rc= memcached_key_test(*memc, (const char **)&key, &key_length, 1)))
+      {
+        memcached_set_error(ptr, vk, MEMCACHED_AT, memcached_literal_param("Key was too long."));
+
+        if (x > 0)
+        {
+          memcached_io_reset(instance);
+        }
+
+        return vk;
+      }
+    }
+#endif
+
+    request.message.header.request.keylen= htons((uint16_t)(key_length[x] + memcached_array_size(ptr->_namespace)));
+    request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+    request.message.header.request.bodylen= htonl((uint32_t)( key_length[x] + memcached_array_size(ptr->_namespace)));
+
+    libmemcached_io_vector_st vector[]=
+    {
+      { request.bytes, sizeof(request.bytes) },
+      { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+      { keys[x], key_length[x] }
+    };
+
+    if (memcached_io_writev(instance, vector, 3, flush) == false)
+    {
+      memcached_server_response_reset(instance);
+      rc= MEMCACHED_SOME_ERRORS;
+      continue;
+    }
+
+    /* We just want one pending response per server */
+    memcached_server_response_reset(instance);
+    memcached_server_response_increment(instance);
+    if ((x > 0 and x == ptr->io_key_prefetch) and memcached_flush_buffers(ptr) != MEMCACHED_SUCCESS)
+    {
+      rc= MEMCACHED_SOME_ERRORS;
+    }
+  }
+
+  if (mget_mode)
+  {
+    /*
+      Send a noop command to flush the buffers
+    */
+    protocol_binary_request_noop request= {}; //= {.bytes= {0}};
+    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_NOOP;
+    request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+
+    for (uint32_t x= 0; x < memcached_server_count(ptr); ++x)
+    {
+      memcached_instance_st* instance= memcached_instance_fetch(ptr, x);
+
+      if (instance->response_count())
+      {
+        initialize_binary_request(instance, request.message.header);
+        if ((memcached_io_write(instance) == false) or
+            (memcached_io_write(instance, request.bytes, sizeof(request.bytes), true) == -1))
+        {
+          memcached_instance_response_reset(instance);
+          memcached_io_reset(instance);
+          rc= MEMCACHED_SOME_ERRORS;
+        }
+      }
+    }
+  }
+
+  return rc;
+}
+
+static memcached_return_t replication_binary_mget(memcached_st *ptr,
+                                                  uint32_t* hash,
+                                                  bool* dead_servers,
+                                                  const char *const *keys,
+                                                  const size_t *key_length,
+                                                  const size_t number_of_keys)
+{
+  memcached_return_t rc= MEMCACHED_NOTFOUND;
+  uint32_t start= 0;
+  uint64_t randomize_read= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ);
+
+  if (randomize_read)
+  {
+    start= (uint32_t)random() % (uint32_t)(ptr->number_of_replicas + 1);
+  }
+
+  /* Loop for each replica */
+  for (uint32_t replica= 0; replica <= ptr->number_of_replicas; ++replica)
+  {
+    bool success= true;
+
+    for (uint32_t x= 0; x < number_of_keys; ++x)
+    {
+      if (hash[x] == memcached_server_count(ptr))
+      {
+        continue; /* Already successfully sent */
+      }
+
+      uint32_t server= hash[x] +replica;
+
+      /* In case of randomized reads */
+      if (randomize_read and ((server + start) <= (hash[x] + ptr->number_of_replicas)))
+      {
+        server+= start;
+      }
+
+      while (server >= memcached_server_count(ptr))
+      {
+        server -= memcached_server_count(ptr);
+      }
+
+      if (dead_servers[server])
+      {
+        continue;
+      }
+
+      memcached_instance_st* instance= memcached_instance_fetch(ptr, server);
+
+      if (instance->response_count() == 0)
+      {
+        rc= memcached_connect(instance);
+
+        if (memcached_failed(rc))
+        {
+          memcached_io_reset(instance);
+          dead_servers[server]= true;
+          success= false;
+          continue;
+        }
+      }
+
+      protocol_binary_request_getk request= {};
+      initialize_binary_request(instance, request.message.header);
+      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
+      request.message.header.request.keylen= htons((uint16_t)(key_length[x] + memcached_array_size(ptr->_namespace)));
+      request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+      request.message.header.request.bodylen= htonl((uint32_t)(key_length[x] + memcached_array_size(ptr->_namespace)));
+
+      /*
+       * We need to disable buffering to actually know that the request was
+       * successfully sent to the server (so that we should expect a result
+       * back). It would be nice to do this in buffered mode, but then it
+       * would be complex to handle all error situations if we got to send
+       * some of the messages, and then we failed on writing out some others
+       * and we used the callback interface from memcached_mget_execute so
+       * that we might have processed some of the responses etc. For now,
+       * just make sure we work _correctly_
+     */
+      libmemcached_io_vector_st vector[]=
+      {
+        { request.bytes, sizeof(request.bytes) },
+        { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+        { keys[x], key_length[x] }
+      };
+
+      if (memcached_io_writev(instance, vector, 3, true) == false)
+      {
+        memcached_io_reset(instance);
+        dead_servers[server]= true;
+        success= false;
+        continue;
+      }
+
+      memcached_server_response_increment(instance);
+      hash[x]= memcached_server_count(ptr);
+    }
+
+    if (success)
+    {
+      break;
+    }
+  }
+
+  return rc;
+}
+
+static memcached_return_t binary_mget_by_key(memcached_st *ptr,
+                                             const uint32_t master_server_key,
+                                             bool is_group_key_set,
+                                             const char * const *keys,
+                                             const size_t *key_length,
+                                             const size_t number_of_keys,
+                                             const bool mget_mode)
+{
+  if (ptr->number_of_replicas == 0)
+  {
+    return simple_binary_mget(ptr, master_server_key, is_group_key_set,
+                              keys, key_length, number_of_keys, mget_mode);
+  }
+
+  uint32_t* hash= libmemcached_xvalloc(ptr, number_of_keys, uint32_t);
+  bool* dead_servers= libmemcached_xcalloc(ptr, memcached_server_count(ptr), bool);
+
+  if (hash == NULL or dead_servers == NULL)
+  {
+    libmemcached_free(ptr, hash);
+    libmemcached_free(ptr, dead_servers);
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+  }
+
+  if (is_group_key_set)
+  {
+    for (size_t x= 0; x < number_of_keys; x++)
+    {
+      hash[x]= master_server_key;
+    }
+  }
+  else
+  {
+    for (size_t x= 0; x < number_of_keys; x++)
+    {
+      hash[x]= memcached_generate_hash_with_redistribution(ptr, keys[x], key_length[x]);
+    }
+  }
+
+  memcached_return_t rc= replication_binary_mget(ptr, hash, dead_servers, keys,
+                                                 key_length, number_of_keys);
+
+  WATCHPOINT_IFERROR(rc);
+  libmemcached_free(ptr, hash);
+  libmemcached_free(ptr, dead_servers);
+
+  return MEMCACHED_SUCCESS;
+}
diff --git a/src/libmemcached/hash.cc b/src/libmemcached/hash.cc
new file mode 100644 (file)
index 0000000..4e02312
--- /dev/null
@@ -0,0 +1,195 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libmemcached/common.h>
+
+#include <sys/time.h>
+
+#include <libmemcached/virtual_bucket.h>
+
+uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash_t hash_algorithm)
+{
+  return libhashkit_digest(key, key_length, (hashkit_hash_algorithm_t)hash_algorithm);
+}
+
+static inline uint32_t generate_hash(const Memcached *ptr, const char *key, size_t key_length)
+{
+  return hashkit_digest(&ptr->hashkit, key, key_length);
+}
+
+static uint32_t dispatch_host(const Memcached *ptr, uint32_t hash)
+{
+  switch (ptr->distribution)
+  {
+  case MEMCACHED_DISTRIBUTION_CONSISTENT:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
+    {
+      uint32_t num= ptr->ketama.continuum_points_counter;
+      WATCHPOINT_ASSERT(ptr->ketama.continuum);
+
+      memcached_continuum_item_st *begin, *end, *left, *right, *middle;
+      begin= left= ptr->ketama.continuum;
+      end= right= ptr->ketama.continuum + num;
+
+      while (left < right)
+      {
+        middle= left + (right - left) / 2;
+        if (middle->value < hash)
+          left= middle + 1;
+        else
+          right= middle;
+      }
+      if (right == end)
+        right= begin;
+      return right->index;
+    }
+  case MEMCACHED_DISTRIBUTION_MODULA:
+    return hash % memcached_server_count(ptr);
+  case MEMCACHED_DISTRIBUTION_RANDOM:
+    return (uint32_t) random() % memcached_server_count(ptr);
+  case MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET:
+    {
+      return memcached_virtual_bucket_get(ptr, hash);
+    }
+  default:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX:
+    WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
+    return hash % memcached_server_count(ptr);
+  }
+  /* NOTREACHED */
+}
+
+/*
+  One version is public and will not modify the distribution hash, the other will.
+*/
+static inline uint32_t _generate_hash_wrapper(const Memcached *ptr, const char *key, size_t key_length)
+{
+  WATCHPOINT_ASSERT(memcached_server_count(ptr));
+
+  if (memcached_server_count(ptr) == 1)
+    return 0;
+
+  if (ptr->flags.hash_with_namespace)
+  {
+    size_t temp_length= memcached_array_size(ptr->_namespace) + key_length;
+    char temp[MEMCACHED_MAX_KEY];
+
+    if (temp_length > MEMCACHED_MAX_KEY -1)
+      return 0;
+
+    strncpy(temp, memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace));
+    strncpy(temp + memcached_array_size(ptr->_namespace), key, key_length);
+
+    return generate_hash(ptr, temp, temp_length);
+  }
+  else
+  {
+    return generate_hash(ptr, key, key_length);
+  }
+}
+
+static inline void _regen_for_auto_eject(Memcached *ptr)
+{
+  if (_is_auto_eject_host(ptr) && ptr->ketama.next_distribution_rebuild)
+  {
+    struct timeval now;
+
+    if (gettimeofday(&now, NULL) == 0 and
+        now.tv_sec > ptr->ketama.next_distribution_rebuild)
+    {
+      run_distribution(ptr);
+    }
+  }
+}
+
+void memcached_autoeject(memcached_st *ptr)
+{
+  _regen_for_auto_eject(ptr);
+}
+
+uint32_t memcached_generate_hash_with_redistribution(memcached_st *ptr, const char *key, size_t key_length)
+{
+  uint32_t hash= _generate_hash_wrapper(ptr, key, key_length);
+
+  _regen_for_auto_eject(ptr);
+
+  return dispatch_host(ptr, hash);
+}
+
+uint32_t memcached_generate_hash(const memcached_st *shell, const char *key, size_t key_length)
+{
+  const Memcached* ptr= memcached2Memcached(shell);
+  if (ptr)
+  {
+    return dispatch_host(ptr, _generate_hash_wrapper(ptr, key, key_length));
+  }
+
+  return UINT32_MAX;
+}
+
+const hashkit_st *memcached_get_hashkit(const memcached_st *shell)
+{
+  const Memcached* ptr= memcached2Memcached(shell);
+  if (ptr)
+  {
+    return &ptr->hashkit;
+  }
+
+  return NULL;
+}
+
+memcached_return_t memcached_set_hashkit(memcached_st *shell, hashkit_st *hashk)
+{
+  Memcached* self= memcached2Memcached(shell);
+  if (self)
+  {
+    hashkit_free(&self->hashkit);
+    hashkit_clone(&self->hashkit, hashk);
+
+    return MEMCACHED_SUCCESS;
+  }
+
+  return MEMCACHED_INVALID_ARGUMENTS;
+}
+
+const char * libmemcached_string_hash(memcached_hash_t type)
+{
+  return libhashkit_string_hash((hashkit_hash_algorithm_t)type);
+}
diff --git a/src/libmemcached/hash.hpp b/src/libmemcached/hash.hpp
new file mode 100644 (file)
index 0000000..bf450ee
--- /dev/null
@@ -0,0 +1,40 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+uint32_t memcached_generate_hash_with_redistribution(memcached_st *ptr, const char *key, size_t key_length);
diff --git a/src/libmemcached/hosts.cc b/src/libmemcached/hosts.cc
new file mode 100644 (file)
index 0000000..98cb3f7
--- /dev/null
@@ -0,0 +1,618 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+#include "libmemcached/assert.hpp"
+
+#include <cmath>
+#include <sys/time.h>
+
+/* Protoypes (static) */
+static memcached_return_t update_continuum(Memcached *ptr);
+
+static int compare_servers(const void *p1, const void *p2)
+{
+  const memcached_instance_st * a= (const memcached_instance_st *)p1;
+  const memcached_instance_st * b= (const memcached_instance_st *)p2;
+
+  int return_value= strcmp(a->_hostname, b->_hostname);
+
+  if (return_value == 0)
+  {
+    return_value= int(a->port() - b->port());
+  }
+
+  return return_value;
+}
+
+static void sort_hosts(Memcached *ptr)
+{
+  if (memcached_server_count(ptr))
+  {
+    qsort(memcached_instance_list(ptr), memcached_server_count(ptr), sizeof(memcached_instance_st), compare_servers);
+  }
+}
+
+
+memcached_return_t run_distribution(Memcached *ptr)
+{
+  if (ptr->flags.use_sort_hosts)
+  {
+    sort_hosts(ptr);
+  }
+
+  switch (ptr->distribution)
+  {
+  case MEMCACHED_DISTRIBUTION_CONSISTENT:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_WEIGHTED:
+    return update_continuum(ptr);
+
+  case MEMCACHED_DISTRIBUTION_VIRTUAL_BUCKET:
+  case MEMCACHED_DISTRIBUTION_MODULA:
+    break;
+
+  case MEMCACHED_DISTRIBUTION_RANDOM:
+    srandom((uint32_t) time(NULL));
+    break;
+
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_MAX:
+  default:
+    assert_msg(0, "Invalid distribution type passed to run_distribution()");
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+static uint32_t ketama_server_hash(const char *key, size_t key_length, uint32_t alignment)
+{
+  unsigned char results[16];
+
+  libhashkit_md5_signature((unsigned char*)key, key_length, results);
+
+  return ((uint32_t) (results[3 + alignment * 4] & 0xFF) << 24)
+    | ((uint32_t) (results[2 + alignment * 4] & 0xFF) << 16)
+    | ((uint32_t) (results[1 + alignment * 4] & 0xFF) << 8)
+    | (results[0 + alignment * 4] & 0xFF);
+}
+
+static int continuum_item_cmp(const void *t1, const void *t2)
+{
+  memcached_continuum_item_st *ct1= (memcached_continuum_item_st *)t1;
+  memcached_continuum_item_st *ct2= (memcached_continuum_item_st *)t2;
+
+  /* Why 153? Hmmm... */
+  WATCHPOINT_ASSERT(ct1->value != 153);
+  if (ct1->value == ct2->value)
+  {
+    if (ct1->index == ct2->index)
+    {
+      return 0;
+    }
+    else if (ct1->index > ct2->index)
+    {
+      return 1;
+    }
+    else
+    {
+      return -1;
+    }
+  }
+  else if (ct1->value > ct2->value)
+  {
+    return 1;
+  }
+  else
+  {
+    return -1;
+  }
+}
+
+static memcached_return_t update_continuum(Memcached *ptr)
+{
+  uint32_t continuum_index= 0;
+  uint32_t pointer_counter= 0;
+  uint32_t pointer_per_server= MEMCACHED_POINTS_PER_SERVER;
+  uint32_t pointer_per_hash= 1;
+  uint32_t live_servers= 0;
+  struct timeval now;
+
+  if (gettimeofday(&now, NULL))
+  {
+    return memcached_set_errno(*ptr, errno, MEMCACHED_AT);
+  }
+
+  memcached_instance_st* list= memcached_instance_list(ptr);
+
+  /* count live servers (those without a retry delay set) */
+  bool is_auto_ejecting= _is_auto_eject_host(ptr);
+  if (is_auto_ejecting)
+  {
+    live_servers= 0;
+    ptr->ketama.next_distribution_rebuild= 0;
+    for (uint32_t host_index= 0; host_index < memcached_server_count(ptr); ++host_index)
+    {
+      if (list[host_index].next_retry <= now.tv_sec)
+      {
+        live_servers++;
+      }
+      else
+      {
+        if (ptr->ketama.next_distribution_rebuild == 0 or list[host_index].next_retry < ptr->ketama.next_distribution_rebuild)
+        {
+          ptr->ketama.next_distribution_rebuild= list[host_index].next_retry;
+        }
+      }
+    }
+  }
+  else
+  {
+    live_servers= memcached_server_count(ptr);
+  }
+
+  if (live_servers == 0)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  uint32_t points_per_server = (uint32_t) (memcached_is_weighted_ketama(ptr) ? MEMCACHED_POINTS_PER_SERVER_KETAMA : MEMCACHED_POINTS_PER_SERVER);
+  uint32_t continuum_limit = live_servers * points_per_server;
+  uint32_t continuum_extra = MEMCACHED_CONTINUUM_ADDITION * points_per_server;
+
+  if (continuum_limit > ptr->ketama.continuum_count)
+  {
+    memcached_continuum_item_st *new_ptr;
+
+    new_ptr= libmemcached_xrealloc(ptr, ptr->ketama.continuum, continuum_limit + continuum_extra, memcached_continuum_item_st);
+
+    if (new_ptr == 0)
+    {
+      return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    }
+
+    ptr->ketama.continuum= new_ptr;
+    ptr->ketama.continuum_count= continuum_limit + continuum_extra;
+  }
+  assert_msg(ptr->ketama.continuum, "Programmer Error, empty ketama continuum");
+
+  uint64_t total_weight= 0;
+  if (memcached_is_weighted_ketama(ptr))
+  {
+    for (uint32_t host_index = 0; host_index < memcached_server_count(ptr); ++host_index)
+    {
+      if (is_auto_ejecting == false or list[host_index].next_retry <= now.tv_sec)
+      {
+        total_weight += list[host_index].weight;
+      }
+    }
+  }
+
+  for (uint32_t host_index= 0; host_index < memcached_server_count(ptr); ++host_index)
+  {
+    if (is_auto_ejecting and list[host_index].next_retry > now.tv_sec)
+    {
+      continue;
+    }
+
+    if (memcached_is_weighted_ketama(ptr))
+    {
+        float pct= (float)list[host_index].weight / (float)total_weight;
+        pointer_per_server= (uint32_t) ((::floor((float) (pct * MEMCACHED_POINTS_PER_SERVER_KETAMA / 4 * (float)live_servers + 0.0000000001))) * 4);
+        pointer_per_hash= 4;
+        if (0 && DEBUG)
+        {
+          printf("ketama_weighted:%s|%d|%llu|%u\n",
+                 list[host_index]._hostname,
+                 list[host_index].port(),
+                 (unsigned long long)list[host_index].weight,
+                 pointer_per_server);
+        }
+    }
+
+
+    if (ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY)
+    {
+      for (uint32_t pointer_index= 0;
+           pointer_index < pointer_per_server / pointer_per_hash;
+           pointer_index++)
+      {
+        char sort_host[1 +MEMCACHED_NI_MAXHOST +1 +MEMCACHED_NI_MAXSERV +1 + MEMCACHED_NI_MAXSERV ]= "";
+        int sort_host_length;
+
+        // Spymemcached ketema key format is: hostname/ip:port-index
+        // If hostname is not available then: /ip:port-index
+        sort_host_length= snprintf(sort_host, sizeof(sort_host),
+                                   "/%s:%u-%u",
+                                   list[host_index]._hostname,
+                                   (uint32_t)list[host_index].port(),
+                                   pointer_index);
+
+        if (size_t(sort_host_length) >= sizeof(sort_host) or sort_host_length < 0)
+        {
+          return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                                     memcached_literal_param("snprintf(sizeof(sort_host))"));
+        }
+
+        if (0 && DEBUG)
+        {
+          fprintf(stdout, "update_continuum: key is %s\n", sort_host);
+        }
+
+        if (memcached_is_weighted_ketama(ptr))
+        {
+          for (uint32_t x= 0; x < pointer_per_hash; x++)
+          {
+            uint32_t value= ketama_server_hash(sort_host, (size_t)sort_host_length, x);
+            ptr->ketama.continuum[continuum_index].index= host_index;
+            ptr->ketama.continuum[continuum_index++].value= value;
+          }
+        }
+        else
+        {
+          uint32_t value= hashkit_digest(&ptr->hashkit, sort_host, (size_t)sort_host_length);
+          ptr->ketama.continuum[continuum_index].index= host_index;
+          ptr->ketama.continuum[continuum_index++].value= value;
+        }
+      }
+    }
+    else
+    {
+      for (uint32_t pointer_index= 1;
+           pointer_index <= pointer_per_server / pointer_per_hash;
+           pointer_index++)
+      {
+        char sort_host[MEMCACHED_NI_MAXHOST +1 +MEMCACHED_NI_MAXSERV +1 +MEMCACHED_NI_MAXSERV]= "";
+        int sort_host_length;
+
+        if (list[host_index].port() == MEMCACHED_DEFAULT_PORT)
+        {
+          sort_host_length= snprintf(sort_host, sizeof(sort_host),
+                                     "%s-%u",
+                                     list[host_index]._hostname,
+                                     pointer_index - 1);
+        }
+        else
+        {
+          sort_host_length= snprintf(sort_host, sizeof(sort_host),
+                                     "%s:%u-%u",
+                                     list[host_index]._hostname,
+                                     (uint32_t)list[host_index].port(),
+                                     pointer_index - 1);
+        }
+
+        if (size_t(sort_host_length) >= sizeof(sort_host) or sort_host_length < 0)
+        {
+          return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                                     memcached_literal_param("snprintf(sizeof(sort_host)))"));
+        }
+
+        if (memcached_is_weighted_ketama(ptr))
+        {
+          for (uint32_t x = 0; x < pointer_per_hash; x++)
+          {
+            uint32_t value= ketama_server_hash(sort_host, (size_t)sort_host_length, x);
+            ptr->ketama.continuum[continuum_index].index= host_index;
+            ptr->ketama.continuum[continuum_index++].value= value;
+          }
+        }
+        else
+        {
+          uint32_t value= hashkit_digest(&ptr->hashkit, sort_host, (size_t)sort_host_length);
+          ptr->ketama.continuum[continuum_index].index= host_index;
+          ptr->ketama.continuum[continuum_index++].value= value;
+        }
+      }
+    }
+
+    pointer_counter+= pointer_per_server;
+  }
+
+  assert_msg(ptr, "Programmer Error, no valid ptr");
+  assert_msg(ptr->ketama.continuum, "Programmer Error, empty ketama continuum");
+  assert_msg(memcached_server_count(ptr) * MEMCACHED_POINTS_PER_SERVER <= MEMCACHED_CONTINUUM_SIZE, "invalid size information being given to qsort()");
+  ptr->ketama.continuum_points_counter= pointer_counter;
+  qsort(ptr->ketama.continuum, ptr->ketama.continuum_points_counter, sizeof(memcached_continuum_item_st), continuum_item_cmp);
+
+  if (DEBUG)
+  {
+    for (uint32_t pointer_index= 0; memcached_server_count(ptr) && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++)
+    {
+      WATCHPOINT_ASSERT(ptr->ketama.continuum[pointer_index].value <= ptr->ketama.continuum[pointer_index + 1].value);
+    }
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t server_add(Memcached *memc, 
+                                     const memcached_string_t& hostname,
+                                     in_port_t port,
+                                     uint32_t weight,
+                                     memcached_connection_t type)
+{
+  assert_msg(memc, "Programmer mistake, somehow server_add() was passed a NULL memcached_st");
+
+  if (memc->number_of_hosts)
+  {
+    assert(memcached_instance_list(memc));
+  }
+
+  if (memcached_instance_list(memc))
+  {
+    assert(memc->number_of_hosts);
+  }
+
+  uint32_t host_list_size= memc->number_of_hosts +1;
+  memcached_instance_st* new_host_list= libmemcached_xrealloc(memc, memcached_instance_list(memc), host_list_size, memcached_instance_st);
+
+  if (new_host_list == NULL)
+  {
+    return memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+  }
+
+  memcached_instance_set(memc, new_host_list, host_list_size);
+  assert(memc->number_of_hosts == host_list_size);
+
+  /* TODO: Check return type */
+  memcached_instance_st* instance= memcached_instance_fetch(memc, memcached_server_count(memc) -1);
+
+  if (__instance_create_with(memc, instance, hostname, port, weight, type) == NULL)
+  {
+    return memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+  }
+
+  if (weight > 1)
+  {
+    if (memcached_is_consistent_distribution(memc))
+    {
+      memcached_set_weighted_ketama(memc, true);
+    }
+  }
+
+  return run_distribution(memc);
+}
+
+
+memcached_return_t memcached_server_push(memcached_st *shell, const memcached_server_list_st list)
+{
+  if (list == NULL)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  Memcached* ptr= memcached2Memcached(shell);
+  if (ptr)
+  {
+    uint32_t original_host_size= memcached_server_count(ptr);
+    uint32_t count= memcached_server_list_count(list);
+    uint32_t host_list_size= count +original_host_size;
+
+    memcached_instance_st* new_host_list= libmemcached_xrealloc(ptr, memcached_instance_list(ptr), host_list_size, memcached_instance_st);
+
+    if (new_host_list == NULL)
+    {
+      return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    }
+
+    memcached_instance_set(ptr, new_host_list, host_list_size);
+
+    ptr->state.is_parsing= true;
+    for (uint32_t x= 0; x < count; ++x, ++original_host_size)
+    {
+      WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
+
+      // We have extended the array, and now we will find it, and use it.
+      memcached_instance_st* instance= memcached_instance_fetch(ptr, original_host_size);
+      WATCHPOINT_ASSERT(instance);
+
+      memcached_string_t hostname= { memcached_string_make_from_cstr(list[x].hostname) };
+      if (__instance_create_with(ptr, instance, 
+                                 hostname,
+                                 list[x].port, list[x].weight, list[x].type) == NULL)
+      {
+        ptr->state.is_parsing= false;
+        return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+      }
+
+      if (list[x].weight > 1)
+      {
+        memcached_set_weighted_ketama(ptr, true);
+      }
+    }
+    ptr->state.is_parsing= false;
+
+    return run_distribution(ptr);
+  }
+
+  return MEMCACHED_INVALID_ARGUMENTS;
+}
+
+memcached_return_t memcached_instance_push(memcached_st *ptr, const struct memcached_instance_st* list, uint32_t number_of_hosts)
+{
+  if (list == NULL)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  uint32_t original_host_size= memcached_server_count(ptr);
+  uint32_t host_list_size= number_of_hosts +original_host_size;
+  memcached_instance_st* new_host_list= libmemcached_xrealloc(ptr, memcached_instance_list(ptr), host_list_size, memcached_instance_st);
+
+  if (new_host_list == NULL)
+  {
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+  }
+
+  memcached_instance_set(ptr, new_host_list, host_list_size);
+
+  // We don't bother with lookups for this operation
+  ptr->state.is_parsing= true;
+
+  // We use original_host_size since size will now point to the first new
+  // instance allocated.
+  for (uint32_t x= 0; x < number_of_hosts; ++x, ++original_host_size)
+  {
+    WATCHPOINT_ASSERT(list[x]._hostname[0] != 0);
+
+    // We have extended the array, and now we will find it, and use it.
+    memcached_instance_st* instance= memcached_instance_fetch(ptr, original_host_size);
+    WATCHPOINT_ASSERT(instance);
+
+    memcached_string_t hostname= { memcached_string_make_from_cstr(list[x]._hostname) };
+    if (__instance_create_with(ptr, instance, 
+                               hostname,
+                               list[x].port(), list[x].weight, list[x].type) == NULL)
+    {
+      ptr->state.is_parsing= false;
+      return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+    }
+
+    if (list[x].weight > 1)
+    {
+      memcached_set_weighted_ketama(ptr, true);
+    }
+  }
+  ptr->state.is_parsing= false;
+
+  return run_distribution(ptr);
+}
+
+memcached_return_t memcached_server_add_unix_socket(memcached_st *ptr,
+                                                    const char *filename)
+{
+  return memcached_server_add_unix_socket_with_weight(ptr, filename, 0);
+}
+
+memcached_return_t memcached_server_add_unix_socket_with_weight(memcached_st *shell,
+                                                                const char *filename,
+                                                                uint32_t weight)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  if (ptr)
+  {
+    memcached_string_t _filename= { memcached_string_make_from_cstr(filename) };
+    if (memcached_is_valid_filename(_filename) == false)
+    {
+      return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid filename for socket provided"));
+    }
+
+    return server_add(ptr, _filename, 0, weight, MEMCACHED_CONNECTION_UNIX_SOCKET);
+  }
+
+  return MEMCACHED_FAILURE;
+}
+
+memcached_return_t memcached_server_add_udp(memcached_st *ptr,
+                                            const char *hostname,
+                                            in_port_t port)
+{
+  return memcached_server_add_udp_with_weight(ptr, hostname, port, 0);
+}
+
+memcached_return_t memcached_server_add_udp_with_weight(memcached_st *shell,
+                                                        const char *,
+                                                        in_port_t,
+                                                        uint32_t)
+{
+  Memcached* self= memcached2Memcached(shell);
+  if (self)
+  {
+    return memcached_set_error(*self, MEMCACHED_DEPRECATED, MEMCACHED_AT);
+  }
+
+  return MEMCACHED_INVALID_ARGUMENTS;
+}
+
+memcached_return_t memcached_server_add(memcached_st *shell,
+                                        const char *hostname,
+                                        in_port_t port)
+{
+  return memcached_server_add_with_weight(shell, hostname, port, 0);
+}
+
+memcached_return_t memcached_server_add_with_weight(memcached_st *shell,
+                                                    const char *hostname,
+                                                    in_port_t port,
+                                                    uint32_t weight)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  if (ptr == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  if (port == 0)
+  {
+    port= MEMCACHED_DEFAULT_PORT;
+  }
+
+  size_t hostname_length= hostname ? strlen(hostname) : 0;
+  if (hostname_length == 0)
+  {
+    hostname= "localhost";
+    hostname_length= memcached_literal_param_size("localhost");
+  }
+
+  memcached_string_t _hostname= { hostname, hostname_length };
+
+  if (memcached_is_valid_servername(_hostname) == false)
+  {
+    return memcached_set_error(*ptr, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid hostname provided"));
+  }
+
+  return server_add(ptr, _hostname, port, weight, _hostname.c_str[0] == '/' ? MEMCACHED_CONNECTION_UNIX_SOCKET  : MEMCACHED_CONNECTION_TCP);
+}
+
+memcached_return_t memcached_server_add_parsed(memcached_st *ptr,
+                                               const char *hostname,
+                                               size_t hostname_length,
+                                               in_port_t port,
+                                               uint32_t weight)
+{
+  char buffer[MEMCACHED_NI_MAXHOST]= { 0 };
+
+  memcpy(buffer, hostname, hostname_length);
+  buffer[hostname_length]= 0;
+
+  memcached_string_t _hostname= { buffer, hostname_length };
+
+  return server_add(ptr, _hostname,
+                    port,
+                    weight,
+                    MEMCACHED_CONNECTION_TCP);
+}
diff --git a/src/libmemcached/initialize_query.cc b/src/libmemcached/initialize_query.cc
new file mode 100644 (file)
index 0000000..cef8e57
--- /dev/null
@@ -0,0 +1,80 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+memcached_return_t initialize_query(Memcached *self, bool increment_query_id)
+{
+  if (self == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  if (increment_query_id)
+  {
+    self->query_id++;
+  }
+
+  if (self->state.is_time_for_rebuild)
+  {
+    memcached_reset(self);
+  }
+
+  if (memcached_server_count(self) == 0)
+  {
+    return memcached_set_error(*self, MEMCACHED_NO_SERVERS, MEMCACHED_AT);
+  }
+
+  memcached_error_free(*self);
+  memcached_result_reset(&self->result);
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t initialize_const_query(const Memcached *self)
+{
+  if (self == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  if (memcached_server_count(self) == 0)
+  {
+    return MEMCACHED_NO_SERVERS;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
diff --git a/src/libmemcached/initialize_query.h b/src/libmemcached/initialize_query.h
new file mode 100644 (file)
index 0000000..105283c
--- /dev/null
@@ -0,0 +1,41 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+memcached_return_t initialize_query(Memcached *self, bool increment_query_id);
+
+memcached_return_t initialize_const_query(const Memcached *self);
diff --git a/src/libmemcached/instance.cc b/src/libmemcached/instance.cc
new file mode 100644 (file)
index 0000000..df08c60
--- /dev/null
@@ -0,0 +1,361 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+static inline void _server_init(memcached_instance_st* self, Memcached *root,
+                                const memcached_string_t& hostname,
+                                in_port_t port,
+                                uint32_t weight, memcached_connection_t type)
+{
+  self->options.is_shutting_down= false;
+  self->options.is_dead= false;
+  self->options.ready= false;
+  self->_events= 0;
+  self->_revents= 0;
+  self->cursor_active_= 0;
+  self->port_= port;
+  self->fd= INVALID_SOCKET;
+  self->io_bytes_sent= 0;
+  self->request_id= 0;
+  self->server_failure_counter= 0;
+  self->server_failure_counter_query_id= 0;
+  self->server_timeout_counter= 0;
+  self->server_timeout_counter_query_id= 0;
+  self->weight= weight ? weight : 1; // 1 is the default weight value
+  self->io_wait_count.read= 0;
+  self->io_wait_count.write= 0;
+  self->io_wait_count.timeouts= 0;
+  self->io_wait_count._bytes_read= 0;
+  self->major_version= UINT8_MAX;
+  self->micro_version= UINT8_MAX;
+  self->minor_version= UINT8_MAX;
+  self->type= type;
+  self->error_messages= NULL;
+  self->read_ptr= self->read_buffer;
+  self->read_buffer_length= 0;
+  self->write_buffer_offset= 0;
+  self->address_info= NULL;
+  self->address_info_next= NULL;
+
+  self->state= MEMCACHED_SERVER_STATE_NEW;
+  self->next_retry= 0;
+
+  self->root= root;
+  if (root)
+  {
+    self->version= ++root->server_info.version;
+  }
+  else
+  {
+    self->version= UINT_MAX;
+  }
+  self->limit_maxbytes= 0;
+  self->hostname(hostname);
+}
+
+static memcached_instance_st* _server_create(memcached_instance_st* self, const memcached_st *memc)
+{
+  if (self == NULL)
+  {
+   self= libmemcached_xmalloc(memc, memcached_instance_st);
+
+    if (self == NULL)
+    {
+      return NULL; /*  MEMCACHED_MEMORY_ALLOCATION_FAILURE */
+    }
+
+    self->options.is_allocated= true;
+  }
+  else
+  {
+    self->options.is_allocated= false;
+  }
+
+  self->options.is_initialized= true;
+
+  return self;
+}
+
+void memcached_instance_st::events(short arg)
+{
+  if ((_events | arg) == _events)
+  {
+    return;
+  }
+
+  _events|= arg;
+}
+
+void memcached_instance_st::revents(short arg)
+{
+  if (arg)
+  {
+    options.ready= true;
+  }
+
+  _revents= arg;
+  _events&= short(~arg);
+}
+
+memcached_instance_st* __instance_create_with(memcached_st *memc,
+                                                    memcached_instance_st* self,
+                                                    const memcached_string_t& hostname,
+                                                    const in_port_t port,
+                                                    uint32_t weight, 
+                                                    const memcached_connection_t type)
+{
+  if (memcached_is_valid_servername(hostname) == false)
+  {
+    memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid hostname provided"));
+    return NULL;
+  }
+
+  self= _server_create(self, memc);
+
+  if (self == NULL)
+  {
+    return NULL;
+  }
+
+  _server_init(self, const_cast<memcached_st *>(memc), hostname, port, weight, type);
+
+  if (memc and memcached_is_udp(memc))
+  { 
+    self->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
+    memcached_io_init_udp_header(self, 0);
+  }
+
+  return self;
+}
+
+void __instance_free(memcached_instance_st* self)
+{
+  memcached_quit_server(self, false);
+
+  self->clear_addrinfo();
+  assert(self->address_info_next == NULL);
+
+  memcached_error_free(*self);
+
+  if (memcached_is_allocated(self))
+  {
+    libmemcached_free(self->root, self);
+  }
+  else
+  {
+    self->options.is_initialized= false;
+  }
+}
+
+void memcached_instance_free(memcached_instance_st* self)
+{
+  if (self)
+  {
+    __instance_free(self);
+  }
+}
+
+memcached_return_t memcached_server_cursor(const memcached_st* shell,
+                                           const memcached_server_fn *callback,
+                                           void *context,
+                                           uint32_t number_of_callbacks)
+{
+  const Memcached* memc= memcached2Memcached(shell);
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_const_query(memc)))
+  {
+    return rc;
+  }
+
+  size_t errors= 0;
+  for (uint32_t x= 0; x < memcached_instance_list_count(memc); x++)
+  {
+    memcached_instance_st* instance= memcached_instance_by_position(memc, x);
+
+    for (uint32_t y= 0; y < number_of_callbacks; y++)
+    {
+      memcached_return_t ret= (*callback[y])(memc, instance, context);
+
+      if (memcached_failed(ret))
+      {
+        errors++;
+        continue;
+      }
+    }
+  }
+
+  return errors ? MEMCACHED_SOME_ERRORS : MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_server_execute(memcached_st *memc,
+                                            memcached_server_execute_fn callback,
+                                            void *context)
+{
+  if (callback == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  bool some_errors= false;;
+  for (uint32_t x= 0; x < memcached_instance_list_count(memc); x++)
+  {
+    memcached_instance_st* instance= memcached_instance_fetch(memc, x);
+
+    memcached_return_t rc= (*callback)(memc, instance, context);
+    if (rc == MEMCACHED_INVALID_ARGUMENTS)
+    {
+      return rc;
+    }
+    else if (memcached_fatal(rc))
+    {
+      some_errors= true;
+    }
+  }
+
+  (void)some_errors;
+  return MEMCACHED_SUCCESS;
+}
+
+const memcached_instance_st * memcached_server_by_key(memcached_st *shell,
+                                                     const char *key,
+                                                     size_t key_length,
+                                                     memcached_return_t *error)
+{
+  Memcached* memc= memcached2Memcached(shell);
+  memcached_return_t unused;
+  if (error == NULL)
+  {
+    error= &unused;
+  }
+
+
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_const_query(memc)))
+  {
+    *error= rc;
+    return NULL;
+  }
+
+  if (memcached_failed((memcached_key_test(*memc, (const char **)&key, &key_length, 1))))
+  {
+    *error= memcached_last_error(memc);
+    return NULL;
+  }
+
+  uint32_t server_key= memcached_generate_hash(memc, key, key_length);
+  return memcached_instance_by_position(memc, server_key);
+}
+
+/*
+  If we do not have a valid object to clone from, we toss an error.
+*/
+static memcached_instance_st* memcached_instance_clone(memcached_instance_st* source)
+{
+  /* We just do a normal create if source is missing */
+  if (source == NULL)
+  {
+    return NULL;
+  }
+
+  memcached_string_t hostname_= { memcached_string_make_from_cstr(source->hostname()) };
+  return __instance_create_with(source->root,
+                                NULL,
+                                hostname_,
+                                source->port(), source->weight,
+                                source->type);
+}
+
+void set_last_disconnected_host(memcached_instance_st* self)
+{
+  assert(self->root);
+  if (self->root)
+  {
+    if (memcached_server_get_last_disconnect(self->root) and
+        memcached_server_get_last_disconnect(self->root)->version == self->version)
+    {
+      return;
+    }
+
+    // const_cast
+    memcached_st *root= (memcached_st *)self->root;
+
+    memcached_instance_free((memcached_instance_st*)(root->last_disconnected_server));
+
+    // We set is_parsing so that no lookup happens
+    root->state.is_parsing= true;
+    root->last_disconnected_server= memcached_instance_clone(self);
+    root->state.is_parsing= false;
+
+    ((memcached_instance_st*)memcached_server_get_last_disconnect(root))->version= self->version;
+  }
+}
+
+const memcached_instance_st * memcached_server_get_last_disconnect(const memcached_st *shell)
+{
+  const Memcached* self= memcached2Memcached(shell);
+  if (self)
+  {
+    return (const memcached_instance_st *)self->last_disconnected_server;
+  }
+
+  return 0;
+}
+
+void memcached_instance_next_retry(const memcached_instance_st * self, const time_t absolute_time)
+{
+  WATCHPOINT_ASSERT(self);
+  if (self)
+  {
+    ((memcached_instance_st*)self)->next_retry= absolute_time;
+  }
+}
+
+bool memcached_instance_st::valid() const
+{
+  if (fd == INVALID_SOCKET)
+  {
+    return false;
+  }
+
+  return true;
+}
+
+bool memcached_instance_st::is_shutting_down() const
+{
+  return options.is_shutting_down;
+}
diff --git a/src/libmemcached/instance.hpp b/src/libmemcached/instance.hpp
new file mode 100644 (file)
index 0000000..63bf083
--- /dev/null
@@ -0,0 +1,199 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/ 
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifndef WIN32
+# ifdef HAVE_NETDB_H
+#  include <netdb.h>
+# endif
+#endif
+
+#ifdef NI_MAXHOST
+# define MEMCACHED_NI_MAXHOST NI_MAXHOST
+#else
+# define MEMCACHED_NI_MAXHOST 1025
+#endif
+
+#ifdef NI_MAXSERV
+# define MEMCACHED_NI_MAXSERV NI_MAXSERV
+#else
+# define MEMCACHED_NI_MAXSERV 32
+#endif
+
+#include "libmemcached/string.hpp"
+
+// @todo Complete class transformation
+struct memcached_instance_st {
+  in_port_t port() const
+  {
+    return port_;
+  }
+
+  void port(in_port_t arg)
+  {
+    port_= arg;
+  }
+
+  void mark_server_as_clean()
+  {
+    server_failure_counter= 0;
+    server_timeout_counter= 0;
+    next_retry= 0;
+  }
+
+  void disable()
+  {
+  }
+
+  void enable()
+  {
+  }
+
+  bool valid() const;
+
+  bool is_shutting_down() const;
+
+  void start_close_socket();
+  void close_socket();
+  void reset_socket();
+
+  uint32_t response_count() const
+  {
+    return cursor_active_;
+  }
+
+  struct {
+    bool is_allocated;
+    bool is_initialized;
+    bool is_shutting_down;
+    bool is_dead;
+    bool ready;
+  } options;
+
+  short _events;
+  short _revents;
+
+  short events(void)
+  {
+    return _events;
+  }
+
+  short revents(void)
+  {
+    return _revents;
+  }
+
+  const char* hostname()
+  {
+    return _hostname;
+  }
+
+  void hostname(const memcached_string_t& hostname_)
+  {
+    if (hostname_.size)
+    {
+      memcpy(_hostname, hostname_.c_str, hostname_.size);
+      _hostname[hostname_.size]= 0;
+    }
+    else
+    {
+      memcpy(_hostname, memcached_literal_param("localhost"));
+      _hostname[memcached_literal_param_size("localhost")]= 0;
+    }
+  }
+
+  void events(short);
+  void revents(short);
+
+  uint32_t cursor_active_;
+  in_port_t port_;
+  memcached_socket_t fd;
+  uint32_t io_bytes_sent; /* # bytes sent since last read */
+  uint32_t request_id;
+  uint32_t server_failure_counter;
+  uint64_t server_failure_counter_query_id;
+  uint32_t server_timeout_counter;
+  uint64_t server_timeout_counter_query_id;
+  uint32_t weight;
+  uint32_t version;
+  enum memcached_server_state_t state;
+  struct {
+    uint32_t read;
+    uint32_t write;
+    uint32_t timeouts;
+    size_t _bytes_read;
+  } io_wait_count;
+  uint8_t major_version; // Default definition of UINT8_MAX means that it has not been set.
+  uint8_t micro_version; // ditto, and note that this is the third, not second version bit
+  uint8_t minor_version; // ditto
+  memcached_connection_t type;
+  char *read_ptr;
+  size_t read_buffer_length;
+  size_t write_buffer_offset;
+  struct addrinfo *address_info;
+  struct addrinfo *address_info_next;
+  time_t next_retry;
+  struct memcached_st *root;
+  uint64_t limit_maxbytes;
+  struct memcached_error_t *error_messages;
+  char read_buffer[MEMCACHED_MAX_BUFFER];
+  char write_buffer[MEMCACHED_MAX_BUFFER];
+  char _hostname[MEMCACHED_NI_MAXHOST];
+
+  void clear_addrinfo()
+  {
+    if (address_info)
+    {
+      freeaddrinfo(address_info);
+      address_info= NULL;
+      address_info_next= NULL;
+    }
+  }
+};
+
+memcached_instance_st* __instance_create_with(memcached_st *memc,
+                                              memcached_instance_st* self,
+                                              const memcached_string_t& _hostname,
+                                              const in_port_t port,
+                                              uint32_t weight, 
+                                              const memcached_connection_t type);
+
+memcached_return_t memcached_instance_push(memcached_st *ptr, const memcached_instance_st*, uint32_t);
+
+void __instance_free(memcached_instance_st *);
diff --git a/src/libmemcached/internal.h b/src/libmemcached/internal.h
new file mode 100644 (file)
index 0000000..67ae67d
--- /dev/null
@@ -0,0 +1,46 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/libmemcached/io.cc b/src/libmemcached/io.cc
new file mode 100644 (file)
index 0000000..13c8cf3
--- /dev/null
@@ -0,0 +1,934 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libmemcached/common.h>
+
+#ifdef HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+
+void initialize_binary_request(memcached_instance_st* server, protocol_binary_request_header& header)
+{
+  server->request_id++;
+  header.request.magic= PROTOCOL_BINARY_REQ;
+  header.request.opaque= htons(server->request_id);
+}
+
+enum memc_read_or_write {
+  MEM_READ,
+  MEM_WRITE
+};
+
+/**
+ * Try to fill the input buffer for a server with as much
+ * data as possible.
+ *
+ * @param instance the server to pack
+ */
+static bool repack_input_buffer(memcached_instance_st* instance)
+{
+  if (instance->read_ptr != instance->read_buffer)
+  {
+    /* Move all of the data to the beginning of the buffer so
+     ** that we can fit more data into the buffer...
+   */
+    memmove(instance->read_buffer, instance->read_ptr, instance->read_buffer_length);
+    instance->read_ptr= instance->read_buffer;
+  }
+
+  /* There is room in the buffer, try to fill it! */
+  if (instance->read_buffer_length != MEMCACHED_MAX_BUFFER)
+  {
+    do {
+      /* Just try a single read to grab what's available */
+      ssize_t nr;
+      if ((nr= ::recv(instance->fd,
+                      instance->read_ptr + instance->read_buffer_length,
+                      MEMCACHED_MAX_BUFFER - instance->read_buffer_length,
+                      MSG_NOSIGNAL)) <= 0)
+      {
+        if (nr == 0)
+        {
+          memcached_set_error(*instance, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT);
+        }
+        else
+        {
+          switch (get_socket_errno())
+          {
+          case EINTR:
+            continue;
+
+#if EWOULDBLOCK != EAGAIN
+          case EWOULDBLOCK:
+#endif
+          case EAGAIN:
+#ifdef __linux
+          case ERESTART:
+#endif
+            break; // No IO is fine, we can just move on
+
+          default:
+            memcached_set_errno(*instance, get_socket_errno(), MEMCACHED_AT);
+          }
+        }
+
+        break;
+      }
+      else // We read data, append to our read buffer
+      {
+        instance->read_buffer_length+= size_t(nr);
+
+        return true;
+      }
+    } while (false);
+  }
+
+  return false;
+}
+
+/**
+ * If the we have callbacks connected to this server structure
+ * we may start process the input queue and fire the callbacks
+ * for the incomming messages. This function is _only_ called
+ * when the input buffer is full, so that we _know_ that we have
+ * at least _one_ message to process.
+ *
+ * @param instance the server to star processing iput messages for
+ * @return true if we processed anything, false otherwise
+ */
+static bool process_input_buffer(memcached_instance_st* instance)
+{
+  /*
+   ** We might be able to process some of the response messages if we
+   ** have a callback set up
+ */
+  if (instance->root->callbacks != NULL)
+  {
+    /*
+     * We might have responses... try to read them out and fire
+     * callbacks
+   */
+    memcached_callback_st cb= *instance->root->callbacks;
+
+    memcached_set_processing_input((Memcached *)instance->root, true);
+
+    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+    Memcached *root= (Memcached *)instance->root;
+    memcached_return_t error= memcached_response(instance, buffer, sizeof(buffer), &root->result);
+
+    memcached_set_processing_input(root, false);
+
+    if (error == MEMCACHED_SUCCESS)
+    {
+      for (unsigned int x= 0; x < cb.number_of_callback; x++)
+      {
+        error= (*cb.callback[x])(instance->root, &root->result, cb.context);
+        if (error != MEMCACHED_SUCCESS)
+        {
+          break;
+        }
+      }
+
+      /* @todo what should I do with the error message??? */
+    }
+    /* @todo what should I do with other error messages?? */
+    return true;
+  }
+
+  return false;
+}
+
+static memcached_return_t io_wait(memcached_instance_st* instance,
+                                  const short events)
+{
+  /*
+   ** We are going to block on write, but at least on Solaris we might block
+   ** on write if we haven't read anything from our input buffer..
+   ** Try to purge the input buffer if we don't do any flow control in the
+   ** application layer (just sending a lot of data etc)
+   ** The test is moved down in the purge function to avoid duplication of
+   ** the test.
+ */
+  if (events & POLLOUT)
+  {
+    if (memcached_purge(instance) == false)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+
+  struct pollfd fds;
+  fds.fd= instance->fd;
+  fds.events= events;
+  fds.revents= 0;
+
+  if (fds.events & POLLOUT) /* write */
+  {
+    instance->io_wait_count.write++;
+  }
+  else
+  {
+    instance->io_wait_count.read++;
+  }
+
+  if (instance->root->poll_timeout == 0) // Mimic 0 causes timeout behavior (not all platforms do this)
+  {
+    return memcached_set_error(*instance, MEMCACHED_TIMEOUT, MEMCACHED_AT, memcached_literal_param("poll_timeout() was set to zero"));
+  }
+
+  size_t loop_max= 5;
+  while (--loop_max) // While loop is for ERESTART or EINTR
+  {
+    int active_fd= poll(&fds, 1, instance->root->poll_timeout);
+
+    if (active_fd >= 1)
+    {
+      assert_msg(active_fd == 1 , "poll() returned an unexpected number of active file descriptors");
+      if (fds.revents & POLLIN or fds.revents & POLLOUT)
+      {
+        return MEMCACHED_SUCCESS;
+      }
+
+      if (fds.revents & POLLHUP)
+      {
+        return memcached_set_error(*instance, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT, 
+                                   memcached_literal_param("poll() detected hang up"));
+      }
+
+      if (fds.revents & POLLERR)
+      {
+        int local_errno= EINVAL;
+        int err;
+        socklen_t len= sizeof (err);
+        if (getsockopt(instance->fd, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == 0)
+        {
+          if (err == 0) // treat this as EINTR
+          {
+            continue;
+          }
+          local_errno= err;
+        }
+        memcached_quit_server(instance, true);
+        return memcached_set_errno(*instance, local_errno, MEMCACHED_AT,
+                                   memcached_literal_param("poll() returned POLLHUP"));
+      }
+      
+      return memcached_set_error(*instance, MEMCACHED_FAILURE, MEMCACHED_AT, memcached_literal_param("poll() returned a value that was not dealt with"));
+    }
+
+    if (active_fd == 0)
+    {
+      return memcached_set_error(*instance, MEMCACHED_TIMEOUT, MEMCACHED_AT, memcached_literal_param("No active_fd were found"));
+    }
+
+    // Only an error should result in this code being called.
+    int local_errno= get_socket_errno(); // We cache in case memcached_quit_server() modifies errno
+    assert_msg(active_fd == -1 , "poll() returned an unexpected value");
+    switch (local_errno)
+    {
+#ifdef __linux
+    case ERESTART:
+#endif
+    case EINTR:
+      continue;
+
+    case EFAULT:
+    case ENOMEM:
+      memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+      break;
+
+    case EINVAL:
+      memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, memcached_literal_param("RLIMIT_NOFILE exceeded, or if OSX the timeout value was invalid"));
+      break;
+
+    default:
+      memcached_set_errno(*instance, local_errno, MEMCACHED_AT, memcached_literal_param("poll"));
+    }
+
+    break;
+  }
+
+  memcached_quit_server(instance, true);
+
+  if (memcached_has_error(instance))
+  {
+    return memcached_instance_error_return(instance);
+  }
+
+  return memcached_set_error(*instance, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT, 
+                             memcached_literal_param("number of attempts to call io_wait() failed"));
+}
+
+static bool io_flush(memcached_instance_st* instance,
+                     const bool with_flush,
+                     memcached_return_t& error)
+{
+  /*
+   ** We might want to purge the input buffer if we haven't consumed
+   ** any output yet... The test for the limits is the purge is inline
+   ** in the purge function to avoid duplicating the logic..
+ */
+  {
+    WATCHPOINT_ASSERT(instance->fd != INVALID_SOCKET);
+
+    if (memcached_purge(instance) == false)
+    {
+      return false;
+    }
+  }
+  char *local_write_ptr= instance->write_buffer;
+  size_t write_length= instance->write_buffer_offset;
+
+  error= MEMCACHED_SUCCESS;
+
+  WATCHPOINT_ASSERT(instance->fd != INVALID_SOCKET);
+
+  /* Looking for memory overflows */
+#if defined(DEBUG)
+  if (write_length == MEMCACHED_MAX_BUFFER)
+    WATCHPOINT_ASSERT(instance->write_buffer == local_write_ptr);
+  WATCHPOINT_ASSERT((instance->write_buffer + MEMCACHED_MAX_BUFFER) >= (local_write_ptr + write_length));
+#endif
+
+  while (write_length)
+  {
+    WATCHPOINT_ASSERT(instance->fd != INVALID_SOCKET);
+    WATCHPOINT_ASSERT(write_length > 0);
+
+    int flags;
+    if (with_flush)
+    {
+      flags= MSG_NOSIGNAL;
+    }
+    else
+    {
+      flags= MSG_NOSIGNAL|MSG_MORE;
+    }
+
+    ssize_t sent_length= ::send(instance->fd, local_write_ptr, write_length, flags);
+    int local_errno= get_socket_errno(); // We cache in case memcached_quit_server() modifies errno
+
+    if (sent_length == SOCKET_ERROR)
+    {
+#if 0 // @todo I should look at why we hit this bit of code hard frequently
+      WATCHPOINT_ERRNO(get_socket_errno());
+      WATCHPOINT_NUMBER(get_socket_errno());
+#endif
+      switch (get_socket_errno())
+      {
+      case ENOBUFS:
+        continue;
+
+#if EWOULDBLOCK != EAGAIN
+      case EWOULDBLOCK:
+#endif
+      case EAGAIN:
+        {
+          /*
+           * We may be blocked on write because the input buffer
+           * is full. Let's check if we have room in our input
+           * buffer for more data and retry the write before
+           * waiting..
+         */
+          if (repack_input_buffer(instance) or process_input_buffer(instance))
+          {
+            continue;
+          }
+
+          memcached_return_t rc= io_wait(instance, POLLOUT);
+          if (memcached_success(rc))
+          {
+            continue;
+          }
+          else if (rc == MEMCACHED_TIMEOUT)
+          {
+            return false;
+          }
+
+          memcached_quit_server(instance, true);
+          error= memcached_set_errno(*instance, local_errno, MEMCACHED_AT);
+          return false;
+        }
+      case ENOTCONN:
+      case EPIPE:
+      default:
+        memcached_quit_server(instance, true);
+        error= memcached_set_errno(*instance, local_errno, MEMCACHED_AT);
+        WATCHPOINT_ASSERT(instance->fd == INVALID_SOCKET);
+        return false;
+      }
+    }
+
+    instance->io_bytes_sent+= uint32_t(sent_length);
+
+    local_write_ptr+= sent_length;
+    write_length-= uint32_t(sent_length);
+  }
+
+  WATCHPOINT_ASSERT(write_length == 0);
+  instance->write_buffer_offset= 0;
+
+  return true;
+}
+
+memcached_return_t memcached_io_wait_for_write(memcached_instance_st* instance)
+{
+  return io_wait(instance, POLLOUT);
+}
+
+memcached_return_t memcached_io_wait_for_read(memcached_instance_st* instance)
+{
+  return io_wait(instance, POLLIN);
+}
+
+static memcached_return_t _io_fill(memcached_instance_st* instance)
+{
+  ssize_t data_read;
+  do
+  {
+    data_read= ::recv(instance->fd, instance->read_buffer, MEMCACHED_MAX_BUFFER, MSG_NOSIGNAL);
+    int local_errno= get_socket_errno(); // We cache in case memcached_quit_server() modifies errno
+
+    if (data_read == SOCKET_ERROR)
+    {
+      switch (get_socket_errno())
+      {
+      case EINTR: // We just retry
+        continue;
+
+      case ETIMEDOUT: // OSX
+#if EWOULDBLOCK != EAGAIN
+      case EWOULDBLOCK:
+#endif
+      case EAGAIN:
+#ifdef __linux
+      case ERESTART:
+#endif
+        {
+          memcached_return_t io_wait_ret;
+          if (memcached_success(io_wait_ret= io_wait(instance, POLLIN)))
+          {
+            continue;
+          }
+
+          return io_wait_ret;
+        }
+
+        /* fall through */
+
+      case ENOTCONN: // Programmer Error
+        WATCHPOINT_ASSERT(0);
+        // fall through
+      case ENOTSOCK:
+        WATCHPOINT_ASSERT(0);
+        // fall through
+      case EBADF:
+        assert_msg(instance->fd != INVALID_SOCKET, "Programmer error, invalid socket");
+        /* fall through */
+      case EINVAL:
+      case EFAULT:
+      case ECONNREFUSED:
+      default:
+        memcached_quit_server(instance, true);
+        memcached_set_errno(*instance, local_errno, MEMCACHED_AT);
+        break;
+      }
+
+      return memcached_instance_error_return(instance);
+    }
+    else if (data_read == 0)
+    {
+      /*
+        EOF. Any data received so far is incomplete
+        so discard it. This always reads by byte in case of TCP
+        and protocol enforcement happens at memcached_response()
+        looking for '\n'. We do not care for UDB which requests 8 bytes
+        at once. Generally, this means that connection went away. Since
+        for blocking I/O we do not return 0 and for non-blocking case
+        it will return EGAIN if data is not immediatly available.
+      */
+      memcached_quit_server(instance, true);
+      return memcached_set_error(*instance, MEMCACHED_CONNECTION_FAILURE, MEMCACHED_AT, 
+                                 memcached_literal_param("::rec() returned zero, server has disconnected"));
+    }
+    instance->io_wait_count._bytes_read+= data_read;
+  } while (data_read <= 0);
+
+  instance->io_bytes_sent= 0;
+  instance->read_buffer_length= (size_t) data_read;
+  instance->read_ptr= instance->read_buffer;
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_io_read(memcached_instance_st* instance,
+                                     void *buffer, size_t length, ssize_t& nread)
+{
+  assert(memcached_is_udp(instance->root) == false);
+  assert_msg(instance, "Programmer error, memcached_io_read() recieved an invalid Instance"); // Programmer error
+  char *buffer_ptr= static_cast<char *>(buffer);
+
+  if (instance->fd == INVALID_SOCKET)
+  {
+#if 0
+    assert_msg(int(instance->state) <= int(MEMCACHED_SERVER_STATE_ADDRINFO), "Programmer error, invalid socket state");
+#endif
+    return MEMCACHED_CONNECTION_FAILURE;
+  }
+
+  while (length)
+  {
+    if (instance->read_buffer_length == 0)
+    {
+      memcached_return_t io_fill_ret;
+      if (memcached_fatal(io_fill_ret= _io_fill(instance)))
+      {
+        nread= -1;
+        return io_fill_ret;
+      }
+    }
+
+    if (length > 1)
+    {
+      size_t difference= (length > instance->read_buffer_length) ? instance->read_buffer_length : length;
+
+      memcpy(buffer_ptr, instance->read_ptr, difference);
+      length -= difference;
+      instance->read_ptr+= difference;
+      instance->read_buffer_length-= difference;
+      buffer_ptr+= difference;
+    }
+    else
+    {
+      *buffer_ptr= *instance->read_ptr;
+      instance->read_ptr++;
+      instance->read_buffer_length--;
+      buffer_ptr++;
+      break;
+    }
+  }
+
+  nread= ssize_t(buffer_ptr - (char*)buffer);
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_io_slurp(memcached_instance_st* instance)
+{
+  assert_msg(instance, "Programmer error, invalid Instance");
+  assert(memcached_is_udp(instance->root) == false);
+
+  if (instance->fd == INVALID_SOCKET)
+  {
+    assert_msg(int(instance->state) <= int(MEMCACHED_SERVER_STATE_ADDRINFO), "Invalid socket state");
+    return MEMCACHED_CONNECTION_FAILURE;
+  }
+
+  ssize_t data_read;
+  char buffer[MEMCACHED_MAX_BUFFER];
+  do
+  {
+    data_read= ::recv(instance->fd, instance->read_buffer, sizeof(buffer), MSG_NOSIGNAL);
+    if (data_read == SOCKET_ERROR)
+    {
+      switch (get_socket_errno())
+      {
+      case EINTR: // We just retry
+        continue;
+
+      case ETIMEDOUT: // OSX
+#if EWOULDBLOCK != EAGAIN
+      case EWOULDBLOCK:
+#endif
+      case EAGAIN:
+#ifdef __linux
+      case ERESTART:
+#endif
+        if (memcached_success(io_wait(instance, POLLIN)))
+        {
+          continue;
+        }
+        return MEMCACHED_IN_PROGRESS;
+
+        /* fall through */
+
+      case ENOTCONN: // Programmer Error
+      case ENOTSOCK:
+        assert(0);
+        /* fall through */
+      case EBADF:
+        assert_msg(instance->fd != INVALID_SOCKET, "Invalid socket state");
+        /* fall through */
+      case EINVAL:
+      case EFAULT:
+      case ECONNREFUSED:
+      default:
+        return MEMCACHED_CONNECTION_FAILURE; // We want this!
+      }
+    }
+  } while (data_read > 0);
+
+  return MEMCACHED_CONNECTION_FAILURE;
+}
+
+static bool _io_write(memcached_instance_st* instance,
+                      const void *buffer, size_t length, bool with_flush,
+                      size_t& written)
+{
+  assert(instance->fd != INVALID_SOCKET);
+  assert(memcached_is_udp(instance->root) == false);
+
+  const char *buffer_ptr= static_cast<const char *>(buffer);
+
+  const size_t original_length= length;
+
+  while (length)
+  {
+    char *write_ptr;
+    size_t buffer_end= MEMCACHED_MAX_BUFFER;
+    size_t should_write= buffer_end -instance->write_buffer_offset;
+    should_write= (should_write < length) ? should_write : length;
+
+    write_ptr= instance->write_buffer + instance->write_buffer_offset;
+    memcpy(write_ptr, buffer_ptr, should_write);
+    instance->write_buffer_offset+= should_write;
+    buffer_ptr+= should_write;
+    length-= should_write;
+
+    if (instance->write_buffer_offset == buffer_end)
+    {
+      WATCHPOINT_ASSERT(instance->fd != INVALID_SOCKET);
+
+      memcached_return_t rc;
+      if (io_flush(instance, with_flush, rc) == false)
+      {
+        written= original_length -length;
+        return false;
+      }
+    }
+  }
+
+  if (with_flush)
+  {
+    memcached_return_t rc;
+    WATCHPOINT_ASSERT(instance->fd != INVALID_SOCKET);
+    if (io_flush(instance, with_flush, rc) == false)
+    {
+      written= original_length -length;
+      return false;
+    }
+  }
+
+  written= original_length -length;
+
+  return true;
+}
+
+bool memcached_io_write(memcached_instance_st* instance)
+{
+  size_t written;
+  return _io_write(instance, NULL, 0, true, written);
+}
+
+ssize_t memcached_io_write(memcached_instance_st* instance,
+                           const void *buffer, const size_t length, const bool with_flush)
+{
+  size_t written;
+
+  if (_io_write(instance, buffer, length, with_flush, written) == false)
+  {
+    return -1;
+  }
+
+  return ssize_t(written);
+}
+
+bool memcached_io_writev(memcached_instance_st* instance,
+                         libmemcached_io_vector_st vector[],
+                         const size_t number_of, const bool with_flush)
+{
+  ssize_t complete_total= 0;
+  ssize_t total= 0;
+
+  for (size_t x= 0; x < number_of; x++, vector++)
+  {
+    complete_total+= vector->length;
+    if (vector->length)
+    {
+      size_t written;
+      if ((_io_write(instance, vector->buffer, vector->length, false, written)) == false)
+      {
+        return false;
+      }
+      total+= written;
+    }
+  }
+
+  if (with_flush)
+  {
+    if (memcached_io_write(instance) == false)
+    {
+      return false;
+    }
+  }
+
+  return (complete_total == total);
+}
+
+void memcached_instance_st::start_close_socket()
+{
+  if (fd != INVALID_SOCKET)
+  {
+    shutdown(fd, SHUT_WR);
+    options.is_shutting_down= true;
+  }
+}
+
+void memcached_instance_st::reset_socket()
+{
+  if (fd != INVALID_SOCKET)
+  {
+    (void)closesocket(fd);
+    fd= INVALID_SOCKET;
+  }
+}
+
+void memcached_instance_st::close_socket()
+{
+  if (fd != INVALID_SOCKET)
+  {
+    int shutdown_options= SHUT_RD;
+    if (options.is_shutting_down == false)
+    {
+      shutdown_options= SHUT_RDWR;
+    }
+
+    /* in case of death shutdown to avoid blocking at close() */
+    if (shutdown(fd, shutdown_options) == SOCKET_ERROR and get_socket_errno() != ENOTCONN)
+    {
+      WATCHPOINT_NUMBER(fd);
+      WATCHPOINT_ERRNO(get_socket_errno());
+      WATCHPOINT_ASSERT(get_socket_errno());
+    }
+
+    reset_socket();
+    state= MEMCACHED_SERVER_STATE_NEW;
+  }
+
+  state= MEMCACHED_SERVER_STATE_NEW;
+  cursor_active_= 0;
+  io_bytes_sent= 0;
+  write_buffer_offset= size_t(root and memcached_is_udp(root) ? UDP_DATAGRAM_HEADER_LENGTH : 0);
+  read_buffer_length= 0;
+  read_ptr= read_buffer;
+  options.is_shutting_down= false;
+  memcached_server_response_reset(this);
+
+  // We reset the version so that if we end up talking to a different server
+  // we don't have stale server version information.
+  major_version= minor_version= micro_version= UINT8_MAX;
+}
+
+memcached_instance_st* memcached_io_get_readable_server(Memcached *memc, memcached_return_t&)
+{
+#define MAX_SERVERS_TO_POLL 100
+  struct pollfd fds[MAX_SERVERS_TO_POLL];
+  nfds_t host_index= 0;
+
+  for (uint32_t x= 0; x < memcached_server_count(memc) and host_index < MAX_SERVERS_TO_POLL; ++x)
+  {
+    memcached_instance_st* instance= memcached_instance_fetch(memc, x);
+
+    if (instance->read_buffer_length > 0) /* I have data in the buffer */
+    {
+      return instance;
+    }
+
+    if (instance->response_count() > 0)
+    {
+      fds[host_index].events= POLLIN;
+      fds[host_index].revents= 0;
+      fds[host_index].fd= instance->fd;
+      ++host_index;
+    }
+  }
+
+  if (host_index < 2)
+  {
+    /* We have 0 or 1 server with pending events.. */
+    for (uint32_t x= 0; x< memcached_server_count(memc); ++x)
+    {
+      memcached_instance_st* instance= memcached_instance_fetch(memc, x);
+
+      if (instance->response_count() > 0)
+      {
+        return instance;
+      }
+    }
+
+    return NULL;
+  }
+
+  int error= poll(fds, host_index, memc->poll_timeout);
+  switch (error)
+  {
+  case -1:
+    memcached_set_errno(*memc, get_socket_errno(), MEMCACHED_AT);
+    /* FALLTHROUGH */
+  case 0:
+    break;
+
+  default:
+    for (nfds_t x= 0; x < host_index; ++x)
+    {
+      if (fds[x].revents & POLLIN)
+      {
+        for (uint32_t y= 0; y < memcached_server_count(memc); ++y)
+        {
+          memcached_instance_st* instance= memcached_instance_fetch(memc, y);
+
+          if (instance->fd == fds[x].fd)
+          {
+            return instance;
+          }
+        }
+      }
+    }
+  }
+
+  return NULL;
+}
+
+/*
+  Eventually we will just kill off the server with the problem.
+*/
+void memcached_io_reset(memcached_instance_st* instance)
+{
+  memcached_quit_server(instance, true);
+}
+
+/**
+ * Read a given number of bytes from the server and place it into a specific
+ * buffer. Reset the IO channel on this server if an error occurs.
+ */
+memcached_return_t memcached_safe_read(memcached_instance_st* instance,
+                                       void *dta,
+                                       const size_t size)
+{
+  size_t offset= 0;
+  char *data= static_cast<char *>(dta);
+
+  while (offset < size)
+  {
+    ssize_t nread;
+    memcached_return_t rc;
+
+    while (memcached_continue(rc= memcached_io_read(instance, data + offset, size - offset, nread))) { };
+
+    if (memcached_failed(rc))
+    {
+      return rc;
+    }
+
+    offset+= size_t(nread);
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_io_readline(memcached_instance_st* instance,
+                                         char *buffer_ptr,
+                                         size_t size,
+                                         size_t& total_nr)
+{
+  total_nr= 0;
+  bool line_complete= false;
+
+  while (line_complete == false)
+  {
+    if (instance->read_buffer_length == 0)
+    {
+      /*
+       * We don't have any data in the buffer, so let's fill the read
+       * buffer. Call the standard read function to avoid duplicating
+       * the logic.
+     */
+      ssize_t nread;
+      memcached_return_t rc= memcached_io_read(instance, buffer_ptr, 1, nread);
+      if (memcached_failed(rc) and rc == MEMCACHED_IN_PROGRESS)
+      {
+        memcached_quit_server(instance, true);
+        return memcached_set_error(*instance, rc, MEMCACHED_AT);
+      }
+      else if (memcached_failed(rc))
+      {
+        return rc;
+      }
+
+      if (*buffer_ptr == '\n')
+      {
+        line_complete= true;
+      }
+
+      ++buffer_ptr;
+      ++total_nr;
+    }
+
+    /* Now let's look in the buffer and copy as we go! */
+    while (instance->read_buffer_length and total_nr < size and line_complete == false)
+    {
+      *buffer_ptr = *instance->read_ptr;
+      if (*buffer_ptr == '\n')
+      {
+        line_complete = true;
+      }
+      --instance->read_buffer_length;
+      ++instance->read_ptr;
+      ++total_nr;
+      ++buffer_ptr;
+    }
+
+    if (total_nr == size)
+    {
+      return MEMCACHED_PROTOCOL_ERROR;
+    }
+  }
+
+  return MEMCACHED_SUCCESS;
+}
diff --git a/src/libmemcached/io.h b/src/libmemcached/io.h
new file mode 100644 (file)
index 0000000..c2711e2
--- /dev/null
@@ -0,0 +1,45 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+struct libmemcached_io_vector_st
+{
+  const void *buffer;
+  size_t length;
+};
diff --git a/src/libmemcached/io.hpp b/src/libmemcached/io.hpp
new file mode 100644 (file)
index 0000000..5480239
--- /dev/null
@@ -0,0 +1,73 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+void initialize_binary_request(memcached_instance_st* server, protocol_binary_request_header&);
+
+bool memcached_io_write(memcached_instance_st* ptr);
+
+ssize_t memcached_io_write(memcached_instance_st* ptr,
+                           const void *buffer, size_t length, bool with_flush);
+
+bool memcached_io_writev(memcached_instance_st* ptr,
+                         libmemcached_io_vector_st vector[],
+                         const size_t number_of, const bool with_flush);
+
+memcached_return_t memcached_io_wait_for_write(memcached_instance_st*);
+memcached_return_t memcached_io_wait_for_read(memcached_instance_st*);
+
+void memcached_io_reset(memcached_instance_st* ptr);
+
+memcached_return_t memcached_io_read(memcached_instance_st* ptr,
+                                     void *buffer, size_t length, ssize_t& nread);
+
+/* Read a line (terminated by '\n') into the buffer */
+memcached_return_t memcached_io_readline(memcached_instance_st* ptr,
+                                         char *buffer_ptr,
+                                         size_t size,
+                                         size_t& total);
+
+/* Read n bytes of data from the server and store them in dta */
+memcached_return_t memcached_safe_read(memcached_instance_st* ptr,
+                                       void *dta,
+                                       const size_t size);
+
+memcached_instance_st* memcached_io_get_readable_server(memcached_st *memc, memcached_return_t&);
+
+memcached_return_t memcached_io_slurp(memcached_instance_st* ptr);
diff --git a/src/libmemcached/is.h b/src/libmemcached/is.h
new file mode 100644 (file)
index 0000000..54f2c2b
--- /dev/null
@@ -0,0 +1,95 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+/* These are private */ 
+#define memcached_is_allocated(__object) ((__object)->options.is_allocated)
+#define memcached_is_encrypted(__object) ((__object)->hashkit._key)
+#define memcached_is_initialized(__object) ((__object)->options.is_initialized)
+#define memcached_is_purging(__object) ((__object)->state.is_purging)
+#define memcached_is_processing_input(__object) ((__object)->state.is_processing_input)
+
+#define memcached_is_aes(__object) ((__object)->flags.is_aes)
+#define memcached_is_udp(__object) ((__object)->flags.use_udp)
+#define memcached_is_verify_key(__object) ((__object)->flags.verify_key)
+#define memcached_is_binary(__object) ((__object)->flags.binary_protocol)
+#define memcached_is_fetching_version(__object) ((__object)->flags.is_fetching_version)
+#define memcached_is_buffering(__object) ((__object)->flags.buffer_requests)
+#define memcached_is_replying(__object) ((__object)->flags.reply)
+#define memcached_is_cas(__object) ((__object)->flags.reply)
+#define memcached_is_randomize_replica_read(__object) ((__object)->flags.randomize_replica_read)
+#define memcached_is_no_block(__object) ((__object)->flags.no_block)
+#define memcached_is_hash_with_namespace(__object) ((__object)->flags.hash_with_namespace)
+#define memcached_is_tcp_nodelay(__object) ((__object)->flags.tcp_nodelay)
+#define memcached_is_auto_eject_hosts(__object) ((__object)->flags.auto_eject_hosts)
+#define memcached_is_use_sort_hosts(__object) ((__object)->flags.use_sort_hosts)
+
+#define memcached_is_ready(__object) ((__object)->options.ready)
+
+#define memcached_is_weighted_ketama(__object) ((__object)->ketama.weighted_)
+
+#define memcached_set_ready(__object, __flag) ((__object)->options.ready= (__flag))
+
+#define memcached_set_aes(__object, __flag) ((__object).flags.is_aes= __flag)
+#define memcached_set_udp(__object, __flag) ((__object).flags.use_udp= __flag)
+#define memcached_set_verify_key(__object, __flag) ((__object).flags.verify_key= __flag)
+#define memcached_set_binary(__object, __flag) ((__object).flags.binary_protocol= __flag)
+#define memcached_set_fetching_version(__object, __flag) ((__object).flags.is_fetching_version= __flag)
+#define memcached_set_buffering(__object, __flag) ((__object).flags.buffer_requests= __flag)
+#define memcached_set_replying(__object, __flag) ((__object).flags.reply= __flag)
+#define memcached_set_cas(__object, __flag) ((__object).flags.reply= __flag)
+#define memcached_set_randomize_replica_read(__object, __flag) ((__object).flags.randomize_replica_read= __flag)
+#define memcached_set_no_block(__object, __flag) ((__object).flags.no_block= __flag)
+#define memcached_set_hash_with_namespace(__object, __flag) ((__object).flags.hash_with_namespace= __flag)
+#define memcached_set_tcp_nodelay(__object, __flag) ((__object).flags.tcp_nodelay= __flag)
+#define memcached_set_auto_eject_hosts(__object, __flag) ((__object).flags.auto_eject_hosts= __flag)
+#define memcached_set_use_sort_hosts(__object, __flag) ((__object).flags.use_sort_hosts= __flag)
+
+#define memcached_has_root(__object) ((__object)->root)
+
+#define memcached_has_error(__object) ((__object)->error_messages)
+
+#define memcached_has_replicas(__object) ((__object)->root->number_of_replicas)
+
+#define memcached_set_processing_input(__object, __value) ((__object)->state.is_processing_input= (__value))
+#define memcached_set_initialized(__object, __value) ((__object)->options.is_initialized= (__value))
+#define memcached_set_allocated(__object, __value) ((__object)->options.is_allocated= (__value))
+
+#define memcached_set_weighted_ketama(__object, __value) ((__object)->ketama.weighted_= (__value))
+
+#define memcached2Memcached(__obj) (__obj)
diff --git a/src/libmemcached/key.cc b/src/libmemcached/key.cc
new file mode 100644 (file)
index 0000000..cec0eec
--- /dev/null
@@ -0,0 +1,111 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+static inline memcached_return_t memcached_validate_key_length(size_t key_length, bool)
+{
+  if (key_length == 0)
+  {
+    return MEMCACHED_BAD_KEY_PROVIDED;
+  }
+
+  // No one ever reimplemented MEMCACHED to use keys longer then the original ascii length
+#if 0
+  if (binary)
+  {
+    if (key_length > 0xffff)
+    {
+      return MEMCACHED_BAD_KEY_PROVIDED;
+    }
+  }
+  else
+#endif
+  {
+    if (key_length >= MEMCACHED_MAX_KEY)
+    {
+      return MEMCACHED_BAD_KEY_PROVIDED;
+    }
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_key_test(memcached_st &memc,
+                                      const char * const *keys,
+                                      const size_t *key_length,
+                                      size_t number_of_keys)
+{
+  if (number_of_keys == 0)
+  {
+    return memcached_set_error(memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Numbers of keys provided was zero"));
+  }
+
+  if (keys == NULL or key_length == NULL)
+  {
+    return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT, memcached_literal_param("Key was NULL or length of key was zero."));
+  }
+
+  const bool is_binary= memcached_flag(memc, MEMCACHED_FLAG_BINARY_PROTOCOL);
+
+  // If we don't need to verify the key, or we are using the binary protoocol,
+  // we just check the size of the key
+  for (size_t x= 0; x < number_of_keys; ++x)
+  {
+    // We should set binary key, but the memcached server is broken for
+    // longer keys at the moment.
+    memcached_return_t rc= memcached_validate_key_length(*(key_length +x), false /* memc.flags.binary_protocol */);
+    if (memcached_failed(rc))
+    {
+      return memcached_set_error(memc, rc, MEMCACHED_AT, memcached_literal_param("Key provided was too long."));
+    }
+
+    if (memc.flags.verify_key and is_binary == false)
+    {
+      for (size_t y= 0; y < *(key_length +x); ++y)
+      {
+        if ((isgraph(keys[x][y])) == 0)
+        {
+          return memcached_set_error(memc, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT, memcached_literal_param("Key provided had invalid character."));
+        }
+      }
+    }
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
diff --git a/src/libmemcached/key.hpp b/src/libmemcached/key.hpp
new file mode 100644 (file)
index 0000000..811a4b7
--- /dev/null
@@ -0,0 +1,43 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+memcached_return_t memcached_key_test(memcached_st& memc,
+                                      const char * const *keys,
+                                      const size_t *key_length,
+                                      size_t number_of_keys);
+
diff --git a/src/libmemcached/libmemcached_probes.d b/src/libmemcached/libmemcached_probes.d
new file mode 100644 (file)
index 0000000..28d8402
--- /dev/null
@@ -0,0 +1,30 @@
+provider libmemcached {
+       probe memcached_delete_start();
+       probe memcached_delete_end();
+       probe memcached_increment_with_initial_start();
+       probe memcached_increment_with_initial_end();
+       probe memcached_decrement_with_initial_start();
+       probe memcached_decrement_with_initial_end();
+       probe memcached_increment_start();
+       probe memcached_increment_end();
+       probe memcached_decrement_start();
+       probe memcached_decrement_end();
+       probe memcached_flush_start();
+       probe memcached_flush_end();
+       probe memcached_set_start();
+       probe memcached_set_end();
+       probe memcached_add_start();
+       probe memcached_add_end();
+       probe memcached_replace_start();
+       probe memcached_replace_end();
+       probe memcached_get_start();
+       probe memcached_get_end();
+       probe memcached_touch_start();
+       probe memcached_touch_end();
+       probe memcached_mget_start();
+       probe memcached_mget_end();
+       probe memcached_connect_start();
+       probe memcached_connect_end();
+       probe memcached_server_add_start();
+       probe memcached_server_add_end();
+};
diff --git a/src/libmemcached/libmemcached_probes.h b/src/libmemcached/libmemcached_probes.h
new file mode 100644 (file)
index 0000000..9dba8aa
--- /dev/null
@@ -0,0 +1,118 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+/*
+ * This file contains the definition of the various probes supported by
+ * libmemcached. Currently it only support DTRACE, but just create an
+ * implementation of the following macros to create your own sort of
+ * probing :)
+ */
+
+#ifdef HAVE_DTRACE
+/*
+ * Create the DTrace probes on the system using it (to support both Solaris
+ * and MacOS X
+ */
+#include "libmemcached/dtrace_probes.h"
+
+#else
+/*
+ * Provide dummy macros so that we don't need to clutter the code with
+ * ifdefs when we want to use the probes.
+ */
+
+#define        LIBMEMCACHED_MEMCACHED_ADD_END()
+#define        LIBMEMCACHED_MEMCACHED_ADD_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_ADD_START()
+#define        LIBMEMCACHED_MEMCACHED_ADD_START_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_CONNECT_END()
+#define        LIBMEMCACHED_MEMCACHED_CONNECT_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_CONNECT_START()
+#define        LIBMEMCACHED_MEMCACHED_CONNECT_START_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_DECREMENT_END()
+#define        LIBMEMCACHED_MEMCACHED_DECREMENT_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_DECREMENT_START()
+#define        LIBMEMCACHED_MEMCACHED_DECREMENT_START_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_END()
+#define        LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_START()
+#define        LIBMEMCACHED_MEMCACHED_DECREMENT_WITH_INITIAL_START_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_DELETE_END()
+#define        LIBMEMCACHED_MEMCACHED_DELETE_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_DELETE_START()
+#define        LIBMEMCACHED_MEMCACHED_DELETE_START_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_FLUSH_END()
+#define        LIBMEMCACHED_MEMCACHED_FLUSH_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_FLUSH_START()
+#define        LIBMEMCACHED_MEMCACHED_FLUSH_START_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_GET_END()
+#define        LIBMEMCACHED_MEMCACHED_GET_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_GET_START()
+#define        LIBMEMCACHED_MEMCACHED_GET_START_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_TOUCH_END()
+#define        LIBMEMCACHED_MEMCACHED_TOUCH_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_TOUCH_START()
+#define        LIBMEMCACHED_MEMCACHED_TOUCH_START_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_INCREMENT_END()
+#define        LIBMEMCACHED_MEMCACHED_INCREMENT_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_INCREMENT_START()
+#define        LIBMEMCACHED_MEMCACHED_INCREMENT_START_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END()
+#define        LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START()
+#define        LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_MGET_END()
+#define        LIBMEMCACHED_MEMCACHED_MGET_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_MGET_START()
+#define        LIBMEMCACHED_MEMCACHED_MGET_START_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_REPLACE_END()
+#define        LIBMEMCACHED_MEMCACHED_REPLACE_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_REPLACE_START()
+#define        LIBMEMCACHED_MEMCACHED_REPLACE_START_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_SERVER_ADD_END()
+#define        LIBMEMCACHED_MEMCACHED_SERVER_ADD_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_SERVER_ADD_START()
+#define        LIBMEMCACHED_MEMCACHED_SERVER_ADD_START_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_SET_END()
+#define        LIBMEMCACHED_MEMCACHED_SET_END_ENABLED() (0)
+#define        LIBMEMCACHED_MEMCACHED_SET_START()
+#define        LIBMEMCACHED_MEMCACHED_SET_START_ENABLED() (0)
+
+#endif
diff --git a/src/libmemcached/memcached.cc b/src/libmemcached/memcached.cc
new file mode 100644 (file)
index 0000000..6e88c25
--- /dev/null
@@ -0,0 +1,495 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+#include <libmemcached/options.hpp>
+#include <libmemcached/virtual_bucket.h>
+
+static inline bool _memcached_init(Memcached *self)
+{
+  self->state.is_purging= false;
+  self->state.is_processing_input= false;
+  self->state.is_time_for_rebuild= false;
+  self->state.is_parsing= false;
+
+  self->flags.auto_eject_hosts= false;
+  self->flags.binary_protocol= false;
+  self->flags.buffer_requests= false;
+  self->flags.hash_with_namespace= false;
+  self->flags.no_block= false;
+  self->flags.reply= true;
+  self->flags.randomize_replica_read= false;
+  self->flags.support_cas= false;
+  self->flags.tcp_nodelay= false;
+  self->flags.use_sort_hosts= false;
+  self->flags.use_udp= false;
+  self->flags.verify_key= false;
+  self->flags.tcp_keepalive= false;
+  self->flags.is_aes= false;
+  self->flags.is_fetching_version= false;
+
+  self->virtual_bucket= NULL;
+
+  self->distribution= MEMCACHED_DISTRIBUTION_MODULA;
+
+  if (hashkit_create(&self->hashkit) == NULL)
+  {
+    return false;
+  }
+
+  self->server_info.version= 0;
+
+  self->ketama.continuum= NULL;
+  self->ketama.continuum_count= 0;
+  self->ketama.continuum_points_counter= 0;
+  self->ketama.next_distribution_rebuild= 0;
+  self->ketama.weighted_= false;
+
+  self->number_of_hosts= 0;
+  self->servers= NULL;
+  self->last_disconnected_server= NULL;
+
+  self->snd_timeout= 0;
+  self->rcv_timeout= 0;
+  self->server_failure_limit= MEMCACHED_SERVER_FAILURE_LIMIT;
+  self->server_timeout_limit= MEMCACHED_SERVER_TIMEOUT_LIMIT;
+  self->query_id= 1; // 0 is considered invalid
+
+  /* TODO, Document why we picked these defaults */
+  self->io_msg_watermark= 500;
+  self->io_bytes_watermark= 65 * 1024;
+
+  self->tcp_keepidle= 0;
+
+  self->io_key_prefetch= 0;
+  self->poll_timeout= MEMCACHED_DEFAULT_TIMEOUT;
+  self->connect_timeout= MEMCACHED_DEFAULT_CONNECT_TIMEOUT;
+  self->retry_timeout= MEMCACHED_SERVER_FAILURE_RETRY_TIMEOUT;
+  self->dead_timeout= MEMCACHED_SERVER_FAILURE_DEAD_TIMEOUT;
+
+  self->send_size= -1;
+  self->recv_size= -1;
+
+  self->user_data= NULL;
+  self->number_of_replicas= 0;
+
+  self->allocators= memcached_allocators_return_default();
+
+  self->on_clone= NULL;
+  self->on_cleanup= NULL;
+  self->get_key_failure= NULL;
+  self->delete_trigger= NULL;
+  self->callbacks= NULL;
+  self->sasl.callbacks= NULL;
+  self->sasl.is_allocated= false;
+
+  self->error_messages= NULL;
+  self->_namespace= NULL;
+  self->configure.initial_pool_size= 1;
+  self->configure.max_pool_size= 1;
+  self->configure.version= -1;
+  self->configure.filename= NULL;
+
+  return true;
+}
+
+static void __memcached_free(Memcached *ptr, bool release_st)
+{
+  /* If we have anything open, lets close it now */
+  send_quit(ptr);
+  memcached_instance_list_free(memcached_instance_list(ptr), memcached_instance_list_count(ptr));
+  memcached_result_free(&ptr->result);
+
+  memcached_virtual_bucket_free(ptr);
+
+  memcached_instance_free((memcached_instance_st*)ptr->last_disconnected_server);
+
+  if (ptr->on_cleanup)
+  {
+    ptr->on_cleanup(ptr);
+  }
+
+  libmemcached_free(ptr, ptr->ketama.continuum);
+  ptr->ketama.continuum= NULL;
+
+  memcached_array_free(ptr->_namespace);
+  ptr->_namespace= NULL;
+
+  memcached_error_free(*ptr);
+
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT and ptr->sasl.callbacks)
+  {
+    memcached_destroy_sasl_auth_data(ptr);
+  }
+
+  if (release_st)
+  {
+    memcached_array_free(ptr->configure.filename);
+    ptr->configure.filename= NULL;
+  }
+
+  hashkit_free(&ptr->hashkit);
+
+  if (memcached_is_allocated(ptr) and release_st)
+  {
+    libmemcached_free(ptr, ptr);
+  }
+}
+
+memcached_st *memcached_create(memcached_st *shell)
+{
+  if (shell)
+  {
+    shell->options.is_allocated= false;
+  }
+  else
+  {
+    shell= (memcached_st *)libmemcached_xmalloc(NULL, memcached_st);
+
+    if (shell == NULL)
+    {
+      return NULL; /*  MEMCACHED_MEMORY_ALLOCATION_FAILURE */
+    }
+
+    shell->options.is_allocated= true;
+  }
+
+  if (_memcached_init(shell) == false)
+  {
+    memcached_free(shell);
+    return NULL;
+  }
+
+  Memcached* memc= memcached2Memcached(shell);
+  if (memcached_result_create(shell, &memc->result) == NULL)
+  {
+    memcached_free(shell);
+    return NULL;
+  }
+
+  WATCHPOINT_ASSERT_INITIALIZED(&memc->result);
+
+  return shell;
+}
+
+memcached_st *memcached(const char *string, size_t length)
+{
+  if (length == 0 and string)
+  {
+    return NULL;
+  }
+
+  if (length and string == NULL)
+  {
+    return NULL;
+  }
+
+  if (length == 0)
+  {
+    if (bool(getenv("LIBMEMCACHED")))
+    {
+      string= getenv("LIBMEMCACHED");
+      length= string ? strlen(string) : 0;
+    }
+  }
+
+  memcached_st *memc= memcached_create(NULL);
+  if (memc == NULL)
+  {
+    return NULL;
+  }
+
+  if (length == 0 or string == NULL)
+  {
+    return memc;
+  }
+
+  memcached_return_t rc= memcached_parse_configuration(memc, string, length);
+  if (memcached_success(rc) and memcached_parse_filename(memc))
+  {
+    rc= memcached_parse_configure_file(*memc, memcached_parse_filename(memc), memcached_parse_filename_length(memc));
+  }
+    
+  if (memcached_failed(rc))
+  {
+    memcached_free(memc);
+    return NULL;
+  }
+
+  return memc;
+}
+
+memcached_return_t memcached_reset(memcached_st *shell)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  WATCHPOINT_ASSERT(ptr);
+  if (ptr == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  bool stored_is_allocated= memcached_is_allocated(ptr);
+  uint64_t query_id= ptr->query_id;
+  __memcached_free(ptr, false);
+  memcached_create(ptr);
+  memcached_set_allocated(ptr, stored_is_allocated);
+  ptr->query_id= query_id;
+
+  if (ptr->configure.filename)
+  {
+    return memcached_parse_configure_file(*ptr, memcached_param_array(ptr->configure.filename));
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+void memcached_servers_reset(memcached_st *shell)
+{
+  Memcached* self= memcached2Memcached(shell);
+  if (self)
+  {
+    libmemcached_free(self, self->ketama.continuum);
+    self->ketama.continuum= NULL;
+    self->ketama.continuum_count= 0;
+    self->ketama.continuum_points_counter= 0;
+
+    memcached_instance_list_free(memcached_instance_list(self), self->number_of_hosts);
+    memcached_instance_set(self, NULL, 0);
+
+    memcached_reset_last_disconnected_server(self);
+  }
+}
+
+void memcached_reset_last_disconnected_server(memcached_st *shell)
+{
+  Memcached* self= memcached2Memcached(shell);
+  if (self)
+  {
+    memcached_instance_free((memcached_instance_st*)self->last_disconnected_server);
+    self->last_disconnected_server= NULL;
+  }
+}
+
+void memcached_free(memcached_st *ptr)
+{
+  if (ptr)
+  {
+    __memcached_free(ptr, true);
+  }
+}
+
+/*
+  clone is the destination, while source is the structure to clone.
+  If source is NULL the call is the same as if a memcached_create() was
+  called.
+*/
+memcached_st *memcached_clone(memcached_st *clone, const memcached_st *source)
+{
+  if (source == NULL)
+  {
+    return memcached_create(clone);
+  }
+
+  if (clone and memcached_is_allocated(clone))
+  {
+    return NULL;
+  }
+
+  memcached_st *new_clone= memcached_create(clone);
+
+  if (new_clone == NULL)
+  {
+    return NULL;
+  }
+
+  new_clone->flags= source->flags;
+  new_clone->send_size= source->send_size;
+  new_clone->recv_size= source->recv_size;
+  new_clone->poll_timeout= source->poll_timeout;
+  new_clone->connect_timeout= source->connect_timeout;
+  new_clone->retry_timeout= source->retry_timeout;
+  new_clone->dead_timeout= source->dead_timeout;
+  new_clone->distribution= source->distribution;
+
+  if (hashkit_clone(&new_clone->hashkit, &source->hashkit) == NULL)
+  {
+    memcached_free(new_clone);
+    return NULL;
+  }
+
+  new_clone->user_data= source->user_data;
+
+  new_clone->snd_timeout= source->snd_timeout;
+  new_clone->rcv_timeout= source->rcv_timeout;
+
+  new_clone->on_clone= source->on_clone;
+  new_clone->on_cleanup= source->on_cleanup;
+
+  new_clone->allocators= source->allocators;
+
+  new_clone->get_key_failure= source->get_key_failure;
+  new_clone->delete_trigger= source->delete_trigger;
+  new_clone->server_failure_limit= source->server_failure_limit;
+  new_clone->server_timeout_limit= source->server_timeout_limit;
+  new_clone->io_msg_watermark= source->io_msg_watermark;
+  new_clone->io_bytes_watermark= source->io_bytes_watermark;
+  new_clone->io_key_prefetch= source->io_key_prefetch;
+  new_clone->number_of_replicas= source->number_of_replicas;
+  new_clone->tcp_keepidle= source->tcp_keepidle;
+
+  if (memcached_server_count(source))
+  {
+    if (memcached_failed(memcached_push(new_clone, source)))
+    {
+      return NULL;
+    }
+  }
+
+
+  new_clone->_namespace= memcached_array_clone(new_clone, source->_namespace);
+  new_clone->configure.filename= memcached_array_clone(new_clone, source->_namespace);
+  new_clone->configure.version= source->configure.version;
+
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT and source->sasl.callbacks)
+  {
+    if (memcached_failed(memcached_clone_sasl(new_clone, source)))
+    {
+      memcached_free(new_clone);
+      return NULL;
+    }
+  }
+
+  if (memcached_failed(run_distribution(new_clone)))
+  {
+    memcached_free(new_clone);
+
+    return NULL;
+  }
+
+  if (source->on_clone)
+  {
+    source->on_clone(new_clone, source);
+  }
+
+  return new_clone;
+}
+
+void *memcached_get_user_data(const memcached_st *shell)
+{
+  const Memcached* memc= memcached2Memcached(shell);
+  if (memc)
+  {
+    return memc->user_data;
+  }
+
+  return NULL;
+}
+
+void *memcached_set_user_data(memcached_st *shell, void *data)
+{
+  Memcached* memc= memcached2Memcached(shell);
+  if (memc)
+  {
+    void *ret= memc->user_data;
+    memc->user_data= data;
+
+    return ret;
+  }
+
+  return NULL;
+}
+
+memcached_return_t memcached_push(memcached_st *destination, const memcached_st *source)
+{
+  return memcached_instance_push(destination, (memcached_instance_st*)source->servers, source->number_of_hosts);
+}
+
+memcached_instance_st* memcached_instance_fetch(Memcached *ptr, uint32_t server_key)
+{
+  if (ptr == NULL)
+  {
+    return NULL;
+  }
+
+  return &ptr->servers[server_key];
+}
+
+const memcached_instance_st * memcached_server_instance_by_position(const memcached_st *shell, uint32_t server_key)
+{
+  const Memcached* memc= memcached2Memcached(shell);
+  if (memc)
+  {
+    return &memc->servers[server_key];
+  }
+
+  return NULL;
+}
+
+memcached_instance_st* memcached_instance_by_position(const memcached_st *shell, uint32_t server_key)
+{
+  const Memcached* memc= memcached2Memcached(shell);
+  if (memc)
+  {
+    return &memc->servers[server_key];
+  }
+
+  return NULL;
+}
+
+uint64_t memcached_query_id(const memcached_st *shell)
+{
+  const Memcached* memc= memcached2Memcached(shell);
+  if (memc)
+  {
+    return memc->query_id;
+  }
+
+  return 0;
+}
+
+memcached_instance_st* memcached_instance_list(const memcached_st *shell)
+{
+  const Memcached* memc= memcached2Memcached(shell);
+  if (memc)
+  {
+    return (memcached_instance_st*)memc->servers;
+  }
+
+  return NULL;
+}
+
diff --git a/src/libmemcached/memcached.h b/src/libmemcached/memcached.h
new file mode 100644 (file)
index 0000000..a45077e
--- /dev/null
@@ -0,0 +1,39 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libmemcached-1.0/memcached.h>
diff --git a/src/libmemcached/memcached.hpp b/src/libmemcached/memcached.hpp
new file mode 100644 (file)
index 0000000..d38e6d2
--- /dev/null
@@ -0,0 +1,40 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libmemcached-1.0/memcached.hpp>
+
diff --git a/src/libmemcached/memcached/README.txt b/src/libmemcached/memcached/README.txt
new file mode 100644 (file)
index 0000000..adcac80
--- /dev/null
@@ -0,0 +1,7 @@
+For your convenience libmemcached contains a copy of protocol_binary.h so that
+you may compile libmemcached without having a memcached server with support
+for the binary protocol installed on your computer. Please do not modify this
+fine, but replace it with a fresh copy from a new distribution if they are 
+out of sync.
+
+Trond Norbye
diff --git a/src/libmemcached/memcached/protocol_binary.h b/src/libmemcached/memcached/protocol_binary.h
new file mode 100644 (file)
index 0000000..51e2c42
--- /dev/null
@@ -0,0 +1,728 @@
+/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (c) <2008>, Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the  nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SUN MICROSYSTEMS, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Summary: Constants used by to implement the binary protocol.
+ *
+ * Copy: See Copyright for the status of this software.
+ *
+ * Author: Trond Norbye <trond.norbye@sun.com>
+ */
+
+#ifndef PROTOCOL_BINARY_H
+#define PROTOCOL_BINARY_H
+
+#include <libmemcachedprotocol-0.0/vbucket.h>
+
+/**
+ * \addtogroup Protocol
+ * @{
+ */
+
+/**
+ * This file contains definitions of the constants and packet formats
+ * defined in the binary specification. Please note that you _MUST_ remember
+ * to convert each multibyte field to / from network byte order to / from
+ * host order.
+ */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    /**
+     * Definition of the legal "magic" values used in a packet.
+     * See section 3.1 Magic byte
+     */
+    typedef enum {
+        PROTOCOL_BINARY_REQ = 0x80,
+        PROTOCOL_BINARY_RES = 0x81
+    } protocol_binary_magic;
+
+    /**
+     * Definition of the valid response status numbers.
+     * See section 3.2 Response Status
+     */
+    typedef enum {
+        PROTOCOL_BINARY_RESPONSE_SUCCESS = 0x00,
+        PROTOCOL_BINARY_RESPONSE_KEY_ENOENT = 0x01,
+        PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS = 0x02,
+        PROTOCOL_BINARY_RESPONSE_E2BIG = 0x03,
+        PROTOCOL_BINARY_RESPONSE_EINVAL = 0x04,
+        PROTOCOL_BINARY_RESPONSE_NOT_STORED = 0x05,
+        PROTOCOL_BINARY_RESPONSE_DELTA_BADVAL = 0x06,
+        PROTOCOL_BINARY_RESPONSE_NOT_MY_VBUCKET = 0x07,
+        PROTOCOL_BINARY_RESPONSE_AUTH_ERROR = 0x20,
+        PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE = 0x21,
+        PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND = 0x81,
+        PROTOCOL_BINARY_RESPONSE_ENOMEM = 0x82,
+        PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED = 0x83,
+        PROTOCOL_BINARY_RESPONSE_EINTERNAL = 0x84,
+        PROTOCOL_BINARY_RESPONSE_EBUSY = 0x85,
+        PROTOCOL_BINARY_RESPONSE_ETMPFAIL = 0x86
+    } protocol_binary_response_status;
+
+    /**
+     * Defintion of the different command opcodes.
+     * See section 3.3 Command Opcodes
+     */
+    typedef enum {
+        PROTOCOL_BINARY_CMD_GET = 0x00,
+        PROTOCOL_BINARY_CMD_SET = 0x01,
+        PROTOCOL_BINARY_CMD_ADD = 0x02,
+        PROTOCOL_BINARY_CMD_REPLACE = 0x03,
+        PROTOCOL_BINARY_CMD_DELETE = 0x04,
+        PROTOCOL_BINARY_CMD_INCREMENT = 0x05,
+        PROTOCOL_BINARY_CMD_DECREMENT = 0x06,
+        PROTOCOL_BINARY_CMD_QUIT = 0x07,
+        PROTOCOL_BINARY_CMD_FLUSH = 0x08,
+        PROTOCOL_BINARY_CMD_GETQ = 0x09,
+        PROTOCOL_BINARY_CMD_NOOP = 0x0a,
+        PROTOCOL_BINARY_CMD_VERSION = 0x0b,
+        PROTOCOL_BINARY_CMD_GETK = 0x0c,
+        PROTOCOL_BINARY_CMD_GETKQ = 0x0d,
+        PROTOCOL_BINARY_CMD_APPEND = 0x0e,
+        PROTOCOL_BINARY_CMD_PREPEND = 0x0f,
+        PROTOCOL_BINARY_CMD_STAT = 0x10,
+        PROTOCOL_BINARY_CMD_SETQ = 0x11,
+        PROTOCOL_BINARY_CMD_ADDQ = 0x12,
+        PROTOCOL_BINARY_CMD_REPLACEQ = 0x13,
+        PROTOCOL_BINARY_CMD_DELETEQ = 0x14,
+        PROTOCOL_BINARY_CMD_INCREMENTQ = 0x15,
+        PROTOCOL_BINARY_CMD_DECREMENTQ = 0x16,
+        PROTOCOL_BINARY_CMD_QUITQ = 0x17,
+        PROTOCOL_BINARY_CMD_FLUSHQ = 0x18,
+        PROTOCOL_BINARY_CMD_APPENDQ = 0x19,
+        PROTOCOL_BINARY_CMD_PREPENDQ = 0x1a,
+        PROTOCOL_BINARY_CMD_VERBOSITY = 0x1b,
+        PROTOCOL_BINARY_CMD_TOUCH = 0x1c,
+        PROTOCOL_BINARY_CMD_GAT = 0x1d,
+        PROTOCOL_BINARY_CMD_GATQ = 0x1e,
+        PROTOCOL_BINARY_CMD_GATK = 0x23,
+        PROTOCOL_BINARY_CMD_GATKQ = 0x24,
+
+        PROTOCOL_BINARY_CMD_SASL_LIST_MECHS = 0x20,
+        PROTOCOL_BINARY_CMD_SASL_AUTH = 0x21,
+        PROTOCOL_BINARY_CMD_SASL_STEP = 0x22,
+
+        /* These commands are used for range operations and exist within
+         * this header for use in other projects.  Range operations are
+         * not expected to be implemented in the memcached server itself.
+         */
+        PROTOCOL_BINARY_CMD_RGET      = 0x30,
+        PROTOCOL_BINARY_CMD_RSET      = 0x31,
+        PROTOCOL_BINARY_CMD_RSETQ     = 0x32,
+        PROTOCOL_BINARY_CMD_RAPPEND   = 0x33,
+        PROTOCOL_BINARY_CMD_RAPPENDQ  = 0x34,
+        PROTOCOL_BINARY_CMD_RPREPEND  = 0x35,
+        PROTOCOL_BINARY_CMD_RPREPENDQ = 0x36,
+        PROTOCOL_BINARY_CMD_RDELETE   = 0x37,
+        PROTOCOL_BINARY_CMD_RDELETEQ  = 0x38,
+        PROTOCOL_BINARY_CMD_RINCR     = 0x39,
+        PROTOCOL_BINARY_CMD_RINCRQ    = 0x3a,
+        PROTOCOL_BINARY_CMD_RDECR     = 0x3b,
+        PROTOCOL_BINARY_CMD_RDECRQ    = 0x3c,
+        /* End Range operations */
+
+        /* VBucket commands */
+        PROTOCOL_BINARY_CMD_SET_VBUCKET = 0x3d,
+        PROTOCOL_BINARY_CMD_GET_VBUCKET = 0x3e,
+        PROTOCOL_BINARY_CMD_DEL_VBUCKET = 0x3f,
+        /* End VBucket commands */
+
+        /* TAP commands */
+        PROTOCOL_BINARY_CMD_TAP_CONNECT = 0x40,
+        PROTOCOL_BINARY_CMD_TAP_MUTATION = 0x41,
+        PROTOCOL_BINARY_CMD_TAP_DELETE = 0x42,
+        PROTOCOL_BINARY_CMD_TAP_FLUSH = 0x43,
+        PROTOCOL_BINARY_CMD_TAP_OPAQUE = 0x44,
+        PROTOCOL_BINARY_CMD_TAP_VBUCKET_SET = 0x45,
+        PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_START = 0x46,
+        PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_END = 0x47,
+        /* End TAP */
+
+        PROTOCOL_BINARY_CMD_LAST_RESERVED = 0xef,
+
+        /* Scrub the data */
+        PROTOCOL_BINARY_CMD_SCRUB = 0xf0
+    } protocol_binary_command;
+
+    /**
+     * Definition of the data types in the packet
+     * See section 3.4 Data Types
+     */
+    typedef enum {
+        PROTOCOL_BINARY_RAW_BYTES = 0x00
+    } protocol_binary_datatypes;
+
+    /**
+     * Definition of the header structure for a request packet.
+     * See section 2
+     */
+    typedef union {
+        struct {
+            uint8_t magic;
+            uint8_t opcode;
+            uint16_t keylen;
+            uint8_t extlen;
+            uint8_t datatype;
+            uint16_t vbucket;
+            uint32_t bodylen;
+            uint32_t opaque;
+            uint64_t cas;
+        } request;
+        uint8_t bytes[24];
+    } protocol_binary_request_header;
+
+    /**
+     * Definition of the header structure for a response packet.
+     * See section 2
+     */
+    typedef union {
+        struct {
+            uint8_t magic;
+            uint8_t opcode;
+            uint16_t keylen;
+            uint8_t extlen;
+            uint8_t datatype;
+            uint16_t status;
+            uint32_t bodylen;
+            uint32_t opaque;
+            uint64_t cas;
+        } response;
+        uint8_t bytes[24];
+    } protocol_binary_response_header;
+
+    /**
+     * Definition of a request-packet containing no extras
+     */
+    union protocol_binary_request_no_extras {
+        struct {
+            protocol_binary_request_header header;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header)];
+    };
+    typedef union protocol_binary_request_no_extras protocol_binary_request_no_extras;
+
+    /**
+     * Definition of a response-packet containing no extras
+     */
+    typedef union {
+        struct {
+            protocol_binary_response_header header;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_response_header)];
+    } protocol_binary_response_no_extras;
+
+    /**
+     * Definition of the packet used by the get, getq, getk and getkq command.
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_get;
+    typedef protocol_binary_request_no_extras protocol_binary_request_getq;
+    typedef protocol_binary_request_no_extras protocol_binary_request_getk;
+    typedef protocol_binary_request_no_extras protocol_binary_request_getkq;
+
+    /**
+     * Definition of the packet returned from a successful get, getq, getk and
+     * getkq.
+     * See section 4
+     */
+    typedef union {
+        struct {
+            protocol_binary_response_header header;
+            struct {
+                uint32_t flags;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_response_header) + 4];
+    } protocol_binary_response_get;
+
+    typedef protocol_binary_response_get protocol_binary_response_getq;
+    typedef protocol_binary_response_get protocol_binary_response_getk;
+    typedef protocol_binary_response_get protocol_binary_response_getkq;
+
+    /**
+     * Definition of the packet used by the delete command
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_delete;
+
+    /**
+     * Definition of the packet returned by the delete command
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_delete;
+
+    /**
+     * Definition of the packet used by the flush command
+     * See section 4
+     * Please note that the expiration field is optional, so remember to see
+     * check the header.bodysize to see if it is present.
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                uint32_t expiration;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+    } protocol_binary_request_flush;
+
+    /**
+     * Definition of the packet returned by the flush command
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_flush;
+
+    /**
+     * Definition of the packet used by set, add and replace
+     * See section 4
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                uint32_t flags;
+                uint32_t expiration;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
+    } protocol_binary_request_set;
+    typedef protocol_binary_request_set protocol_binary_request_add;
+    typedef protocol_binary_request_set protocol_binary_request_replace;
+
+    /**
+     * Definition of the packet returned by set, add and replace
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_set;
+    typedef protocol_binary_response_no_extras protocol_binary_response_add;
+    typedef protocol_binary_response_no_extras protocol_binary_response_replace;
+
+    /**
+     * Definition of the noop packet
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_noop;
+
+    /**
+     * Definition of the packet returned by the noop command
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_noop;
+
+    /**
+     * Definition of the structure used by the increment and decrement
+     * command.
+     * See section 4
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                uint64_t delta;
+                uint64_t initial;
+                uint32_t expiration;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 20];
+    } protocol_binary_request_incr;
+    typedef protocol_binary_request_incr protocol_binary_request_decr;
+
+    /**
+     * Definition of the response from an incr or decr command
+     * command.
+     * See section 4
+     */
+    typedef union {
+        struct {
+            protocol_binary_response_header header;
+            struct {
+                uint64_t value;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_response_header) + 8];
+    } protocol_binary_response_incr;
+    typedef protocol_binary_response_incr protocol_binary_response_decr;
+
+    /**
+     * Definition of the quit
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_quit;
+
+    /**
+     * Definition of the packet returned by the quit command
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_quit;
+
+    /**
+     * Definition of the packet used by append and prepend command
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_append;
+    typedef protocol_binary_request_no_extras protocol_binary_request_prepend;
+
+    /**
+     * Definition of the packet returned from a successful append or prepend
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_append;
+    typedef protocol_binary_response_no_extras protocol_binary_response_prepend;
+
+    /**
+     * Definition of the packet used by the version command
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_version;
+
+    /**
+     * Definition of the packet returned from a successful version command
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_version;
+
+
+    /**
+     * Definition of the packet used by the stats command.
+     * See section 4
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_stats;
+
+    /**
+     * Definition of the packet returned from a successful stats command
+     * See section 4
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_stats;
+
+    /**
+     * Definition of the packet used by the verbosity command
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                uint32_t level;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+    } protocol_binary_request_verbosity;
+
+    /**
+     * Definition of the packet returned from the verbosity command
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_verbosity;
+
+    /**
+     * Definition of the packet used by the touch command.
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                uint32_t expiration;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+    } protocol_binary_request_touch;
+
+    /**
+     * Definition of the packet returned from the touch command
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_touch;
+
+    /**
+     * Definition of the packet used by the GAT(Q) command.
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                uint32_t expiration;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+    } protocol_binary_request_gat;
+
+    typedef protocol_binary_request_gat protocol_binary_request_gatq;
+
+    /**
+     * Definition of the packet returned from the GAT(Q)
+     */
+    typedef protocol_binary_response_get protocol_binary_response_gat;
+    typedef protocol_binary_response_get protocol_binary_response_gatq;
+
+
+    /**
+     * Definition of a request for a range operation.
+     * See http://code.google.com/p/memcached/wiki/RangeOps
+     *
+     * These types are used for range operations and exist within
+     * this header for use in other projects.  Range operations are
+     * not expected to be implemented in the memcached server itself.
+     */
+    typedef union {
+        struct {
+            protocol_binary_response_header header;
+            struct {
+                uint16_t size;
+                uint8_t  reserved;
+                uint8_t  flags;
+                uint32_t max_results;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+    } protocol_binary_request_rangeop;
+
+    typedef protocol_binary_request_rangeop protocol_binary_request_rget;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rset;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rsetq;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rappend;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rappendq;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rprepend;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rprependq;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rdelete;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rdeleteq;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rincr;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rincrq;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rdecr;
+    typedef protocol_binary_request_rangeop protocol_binary_request_rdecrq;
+
+
+    /**
+     * Definition of tap commands
+     * See To be written
+     *
+     */
+
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                /**
+                 * flags is a bitmask used to set properties for the
+                 * the connection. Please In order to be forward compatible
+                 * you should set all undefined bits to 0.
+                 *
+                 * If the bit require extra userdata, it will be stored
+                 * in the user-data field of the body (passed to the engine
+                 * as enginespeciffic). That means that when you parse the
+                 * flags and the engine-specific data, you have to work your
+                 * way from bit 0 and upwards to find the correct offset for
+                 * the data.
+                 *
+                 */
+                uint32_t flags;
+
+                /**
+                 * Backfill age
+                 *
+                 * By using this flag you can limit the amount of data being
+                 * transmitted. If you don't specify a backfill age, the
+                 * server will transmit everything it contains.
+                 *
+                 * The first 8 bytes in the engine specific data contains
+                 * the oldest entry (from epoc) you're interested in.
+                 * Specifying a time in the future (for the server you are
+                 * connecting to), will cause it to start streaming current
+                 * changes.
+                 */
+#define TAP_CONNECT_FLAG_BACKFILL 0x01
+                /**
+                 * Dump will cause the server to send the data stored on the
+                 * server, but disconnect when the keys stored in the server
+                 * are transmitted.
+                 */
+#define TAP_CONNECT_FLAG_DUMP 0x02
+                /**
+                 * The body contains a list of 16 bits words in network byte
+                 * order specifying the vbucket ids to monitor. The first 16
+                 * bit word contains the number of buckets. The number of 0
+                 * means "all buckets"
+                 */
+#define TAP_CONNECT_FLAG_LIST_VBUCKETS 0x04
+                /**
+                 * The responsibility of the vbuckets is to be transferred
+                 * over to the caller when all items are transferred.
+                 */
+#define TAP_CONNECT_FLAG_TAKEOVER_VBUCKETS 0x08
+                /**
+                 * The tap consumer supports ack'ing of tap messages
+                 */
+#define TAP_CONNECT_SUPPORT_ACK 0x10
+                /**
+                 * The tap consumer would prefer to just get the keys
+                 * back. If the engine supports this it will set
+                 * the TAP_FLAG_NO_VALUE flag in each of the
+                 * tap packets returned.
+                 */
+#define TAP_CONNECT_REQUEST_KEYS_ONLY 0x20
+                /**
+                 * The body contains a list of (vbucket_id, last_checkpoint_id)
+                 * pairs. This provides the checkpoint support in TAP streams.
+                 * The last checkpoint id represents the last checkpoint that
+                 * was successfully persisted.
+                 */
+#define TAP_CONNECT_CHECKPOINT 0x40
+                /**
+                 * The tap consumer is a registered tap client, which means that
+                 * the tap server will maintain its checkpoint cursor permanently.
+                 */
+#define TAP_CONNECT_REGISTERED_CLIENT 0x80
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 4];
+    } protocol_binary_request_tap_connect;
+
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                struct {
+                    uint16_t enginespecific_length;
+                    /*
+                     * The flag section support the following flags
+                     */
+                    /**
+                     * Request that the consumer send a response packet
+                     * for this packet. The opaque field must be preserved
+                     * in the response.
+                     */
+#define TAP_FLAG_ACK 0x01
+                    /**
+                     * The value for the key is not included in the packet
+                     */
+#define TAP_FLAG_NO_VALUE 0x02
+                    uint16_t flags;
+                    uint8_t  ttl;
+                    uint8_t  res1;
+                    uint8_t  res2;
+                    uint8_t  res3;
+                } tap;
+                struct {
+                    uint32_t flags;
+                    uint32_t expiration;
+                } item;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 16];
+    } protocol_binary_request_tap_mutation;
+
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                struct {
+                    uint16_t enginespecific_length;
+                    /**
+                     * See the definition of the flags for
+                     * protocol_binary_request_tap_mutation for a description
+                     * of the available flags.
+                     */
+                    uint16_t flags;
+                    uint8_t  ttl;
+                    uint8_t  res1;
+                    uint8_t  res2;
+                    uint8_t  res3;
+                } tap;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + 8];
+    } protocol_binary_request_tap_no_extras;
+
+    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_delete;
+    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_flush;
+    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_opaque;
+    typedef protocol_binary_request_tap_no_extras protocol_binary_request_tap_vbucket_set;
+
+
+    /**
+     * Definition of the packet used by the scrub.
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_scrub;
+
+    /**
+     * Definition of the packet returned from scrub.
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_scrub;
+
+
+    /**
+     * Definition of the packet used by set vbucket
+     */
+    typedef union {
+        struct {
+            protocol_binary_request_header header;
+            struct {
+                vbucket_state_t state;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_request_header) + sizeof(vbucket_state_t)];
+    } protocol_binary_request_set_vbucket;
+    /**
+     * Definition of the packet returned from set vbucket
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_set_vbucket;
+    /**
+     * Definition of the packet used by del vbucket
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_del_vbucket;
+    /**
+     * Definition of the packet returned from del vbucket
+     */
+    typedef protocol_binary_response_no_extras protocol_binary_response_del_vbucket;
+
+    /**
+     * Definition of the packet used by get vbucket
+     */
+    typedef protocol_binary_request_no_extras protocol_binary_request_get_vbucket;
+
+    /**
+     * Definition of the packet returned from get vbucket
+     */
+    typedef union {
+        struct {
+            protocol_binary_response_header header;
+            struct {
+                vbucket_state_t state;
+            } body;
+        } message;
+        uint8_t bytes[sizeof(protocol_binary_response_header) + sizeof(vbucket_state_t)];
+    } protocol_binary_response_get_vbucket;
+
+
+    /**
+     * @}
+     */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* PROTOCOL_BINARY_H */
diff --git a/src/libmemcached/memcached/vbucket.h b/src/libmemcached/memcached/vbucket.h
new file mode 100644 (file)
index 0000000..e2cc563
--- /dev/null
@@ -0,0 +1,59 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef enum {
+    vbucket_state_active = 1, /**< Actively servicing a vbucket. */
+    vbucket_state_replica, /**< Servicing a vbucket as a replica only. */
+    vbucket_state_pending, /**< Pending active. */
+    vbucket_state_dead /**< Not in use, pending deletion. */
+} vbucket_state_t;
+
+#define is_valid_vbucket_state_t(state) \
+    (state == vbucket_state_active || \
+     state == vbucket_state_replica || \
+     state == vbucket_state_pending || \
+     state == vbucket_state_dead)
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/libmemcached/memory.h b/src/libmemcached/memory.h
new file mode 100644 (file)
index 0000000..12d0284
--- /dev/null
@@ -0,0 +1,111 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <mem_config.h>
+
+#include <libmemcached/common.h>
+
+#ifdef __cplusplus
+#include <cstddef>
+#include <cstdlib>
+#else
+#include <stddef.h>
+#include <stdlib.h>
+#endif
+
+static inline void libmemcached_free(const memcached_st *self, void *mem)
+{
+  if (self)
+  {
+    self->allocators.free(self, mem, self->allocators.context);
+  }
+  else if (mem)
+  {
+#ifdef __cplusplus
+    std::free(mem);
+#else
+    free(mem);
+#endif
+  }
+}
+
+static inline void *libmemcached_malloc(const memcached_st *self, const size_t size)
+{
+  if (self)
+  {
+    return self->allocators.malloc(self, size, self->allocators.context);
+  }
+
+#ifdef __cplusplus
+  return std::malloc(size);
+#else
+  return malloc(size);
+#endif
+}
+#define libmemcached_xmalloc(__memcachd_st, __type) ((__type *)libmemcached_malloc((__memcachd_st), sizeof(__type)))
+
+static inline void *libmemcached_realloc(const memcached_st *self, void *mem, size_t nmemb,  const size_t size)
+{
+  if (self)
+  {
+    return self->allocators.realloc(self, mem, nmemb * size, self->allocators.context);
+  }
+
+#ifdef __cplusplus
+    return std::realloc(mem, size);
+#else
+    return realloc(mem, size);
+#endif
+}
+#define libmemcached_xrealloc(__memcachd_st, __mem, __nelem, __type) ((__type *)libmemcached_realloc((__memcachd_st), (__mem), (__nelem), sizeof(__type)))
+#define libmemcached_xvalloc(__memcachd_st, __nelem, __type) ((__type *)libmemcached_realloc((__memcachd_st), NULL, (__nelem), sizeof(__type)))
+
+static inline void *libmemcached_calloc(const memcached_st *self, size_t nelem, size_t size)
+{
+  if (self)
+  {
+    return self->allocators.calloc(self, nelem, size, self->allocators.context);
+  }
+
+#ifdef __cplusplus
+    return std::calloc(nelem, size);
+#else
+    return calloc(nelem, size);
+#endif
+}
+#define libmemcached_xcalloc(__memcachd_st, __nelem, __type) ((__type *)libmemcached_calloc((__memcachd_st), (__nelem), sizeof(__type)))
diff --git a/src/libmemcached/namespace.cc b/src/libmemcached/namespace.cc
new file mode 100644 (file)
index 0000000..664ebc4
--- /dev/null
@@ -0,0 +1,94 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libmemcached/common.h"
+#include "libmemcached/assert.hpp"
+
+memcached_return_t memcached_set_namespace(Memcached& memc, const char *key, size_t key_length)
+{
+  if (key and key_length == 0)
+  { 
+    WATCHPOINT_ASSERT(key_length);
+    return memcached_set_error(memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid namespace, namespace string had value but length was 0"));
+  }
+  else if (key_length and key == NULL)
+  {
+    WATCHPOINT_ASSERT(key);
+    return memcached_set_error(memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid namespace, namespace string length was > 1 but namespace string was null "));
+  }
+  else if (key and key_length)
+  {
+    bool orig= memc.flags.verify_key;
+    memc.flags.verify_key= true;
+    if (memcached_failed(memcached_key_test(memc, (const char **)&key, &key_length, 1)))
+    {
+      memc.flags.verify_key= orig;
+      return memcached_last_error(&memc);
+    }
+    memc.flags.verify_key= orig;
+
+    if ((key_length > MEMCACHED_PREFIX_KEY_MAX_SIZE -1))
+    {
+      return memcached_set_error(memc, MEMCACHED_KEY_TOO_BIG, MEMCACHED_AT);
+    }
+
+    memcached_array_free(memc._namespace);
+    memc._namespace= memcached_strcpy(&memc, key, key_length);
+
+    if (memc._namespace == NULL)
+    {
+      return memcached_set_error(memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+    }
+  }
+  else
+  {
+    memcached_array_free(memc._namespace);
+    memc._namespace= NULL;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+const char * memcached_get_namespace(Memcached& memc)
+{
+  if (memc._namespace == NULL)
+  {
+    return NULL;
+  }
+
+  return memcached_array_string(memc._namespace);
+}
diff --git a/src/libmemcached/namespace.h b/src/libmemcached/namespace.h
new file mode 100644 (file)
index 0000000..0c98ce4
--- /dev/null
@@ -0,0 +1,46 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+
+memcached_return_t memcached_set_namespace(Memcached&, const char *str, size_t length);
+
+const char * memcached_get_namespace(Memcached&);
+
+#endif // __cplusplus
diff --git a/src/libmemcached/options.cc b/src/libmemcached/options.cc
new file mode 100644 (file)
index 0000000..290cfc8
--- /dev/null
@@ -0,0 +1,185 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+#include <libmemcached/options.hpp>
+
+#include <libmemcached/csl/context.h>
+
+const char *memcached_parse_filename(memcached_st *memc)
+{
+  assert_msg(memc, "Invalid memcached_st");
+  return memcached_array_string(memc->configure.filename);
+}
+
+size_t memcached_parse_filename_length(memcached_st *memc)
+{
+  return memcached_array_size(memc->configure.filename);
+}
+
+static memcached_return_t _parse_file_options(memcached_st& self, memcached_array_st *real_name)
+{
+  FILE *fp= fopen(memcached_array_string(real_name), "r");
+  if (not fp)
+  {
+    memcached_string_t error_message= memcached_array_to_string(real_name);
+    memcached_return_t rc=  memcached_set_errno(self, errno, MEMCACHED_AT, error_message);
+    return rc;
+  }
+
+  char buffer[BUFSIZ];
+  memcached_return_t rc= MEMCACHED_INVALID_ARGUMENTS;
+  while (fgets(buffer, sizeof(buffer), fp))
+  {
+    size_t length= strlen(buffer);
+    
+    if (length == 1 and buffer[0] == '\n')
+      continue;
+
+    if (memcached_failed(rc= memcached_parse_configuration(&self, buffer, length)))
+      break;
+  }
+  fclose(fp);
+
+  return rc;
+}
+
+memcached_return_t libmemcached_check_configuration(const char *option_string, size_t length, char *error_buffer, size_t error_buffer_size)
+{
+  memcached_st memc, *memc_ptr;
+
+  if (option_string == NULL or length == 0)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  if (error_buffer and error_buffer_size)
+  {
+    error_buffer[0]= 0;
+  }
+
+  if (not (memc_ptr= memcached_create(&memc)))
+  {
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+  }
+
+  memcached_return_t rc= memcached_parse_configuration(memc_ptr, option_string, length);
+  if (memcached_failed(rc) and error_buffer and error_buffer_size)
+  {
+    strncpy(error_buffer, memcached_last_error_message(memc_ptr), error_buffer_size);
+    error_buffer[error_buffer_size -1]= 0;
+  }
+
+  bool has_filename= memcached_behavior_get(memc_ptr, MEMCACHED_BEHAVIOR_LOAD_FROM_FILE);
+  if (memcached_success(rc) and has_filename)
+  {
+    assert_msg(memcached_parse_filename(memc_ptr), "Invalid configuration file");
+    assert_msg(memcached_parse_filename_length(memc_ptr), "Invalid configuration file");
+    rc= _parse_file_options(*memc_ptr, memc_ptr->configure.filename);
+
+    if (memcached_failed(rc) and error_buffer and error_buffer_size)
+    {
+      strncpy(error_buffer, memcached_last_error_message(memc_ptr), error_buffer_size);
+      error_buffer[error_buffer_size -1]= 0;
+    }
+  }
+
+  memcached_free(memc_ptr);
+
+  return rc;
+}
+
+memcached_return_t memcached_parse_configuration(memcached_st *self, char const *option_string, size_t length)
+{
+  WATCHPOINT_ASSERT(self);
+  if (not self)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  memcached_return_t rc;
+  Context context(option_string, length, self, rc);
+
+  context.start();
+
+  return rc;
+}
+
+void memcached_set_configuration_file(memcached_st *self, const char *filename, size_t filename_length)
+{
+  assert_msg(filename, "Invalid filename");
+  assert_msg(filename_length, "Invalid filename_length");
+  memcached_array_free(self->configure.filename);
+  self->configure.filename= memcached_strcpy(self, filename, filename_length);
+}
+
+memcached_return_t memcached_parse_configure_file(memcached_st& self, const char *filename, size_t length)
+{
+  if (not filename)
+  {
+    return memcached_set_error(self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT);
+  }
+
+  WATCHPOINT_ASSERT(self);
+  if (not length)
+  {
+    return memcached_set_error(self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT);
+  }
+
+  memcached_array_st *tmp_array= memcached_strcpy(&self, filename, length);
+
+  if (not tmp_array)
+  {
+    return memcached_set_error(self, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+  }
+
+  memcached_return_t rc= memcached_parse_configure_file(self, *tmp_array);
+  memcached_array_free(tmp_array);
+
+  return rc;
+}
+
+memcached_return_t memcached_parse_configure_file(memcached_st& self, memcached_array_st& filename)
+{
+  WATCHPOINT_ASSERT(memcached_array_size(&filename));
+  if (not memcached_array_size(&filename))
+  {
+    return memcached_set_error(self, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT);
+  }
+
+  return _parse_file_options(self, &filename);
+}
diff --git a/src/libmemcached/options.hpp b/src/libmemcached/options.hpp
new file mode 100644 (file)
index 0000000..bc71732
--- /dev/null
@@ -0,0 +1,56 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+LIBMEMCACHED_LOCAL
+  void memcached_set_configuration_file(memcached_st *self, const char *filename, size_t filename_length);
+
+LIBMEMCACHED_LOCAL
+  const char *memcached_parse_filename(memcached_st *memc);
+
+LIBMEMCACHED_LOCAL
+  memcached_return_t memcached_parse_configuration(memcached_st *ptr, const char *option_string, size_t length);
+
+LIBMEMCACHED_LOCAL
+  size_t memcached_parse_filename_length(memcached_st *memc);
+
+LIBMEMCACHED_LOCAL
+  memcached_return_t memcached_parse_configure_file(memcached_st&, const char *filename, size_t length);
+
+LIBMEMCACHED_LOCAL
+  memcached_return_t memcached_parse_configure_file(memcached_st&, memcached_array_st& filename);
diff --git a/src/libmemcached/parse.cc b/src/libmemcached/parse.cc
new file mode 100644 (file)
index 0000000..7665b73
--- /dev/null
@@ -0,0 +1,124 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* 
+  I debated about putting this in the client library since it does an 
+  action I don't really believe belongs in the library.
+
+  Frankly its too damn useful not to be here though.
+*/
+
+#include <libmemcached/common.h>
+
+memcached_server_list_st memcached_servers_parse(const char *server_strings)
+{
+  char *string;
+  const char *begin_ptr;
+  const char *end_ptr;
+  memcached_server_st *servers= NULL;
+  memcached_return_t rc;
+
+  WATCHPOINT_ASSERT(server_strings);
+
+  end_ptr= server_strings + strlen(server_strings);
+
+  for (begin_ptr= server_strings, string= (char *)index(server_strings, ','); 
+       begin_ptr != end_ptr; 
+       string= (char *)index(begin_ptr, ','))
+  {
+    char buffer[HUGE_STRING_LEN];
+    char *ptr, *ptr2;
+    uint32_t weight= 0;
+
+    if (string)
+    {
+      memcpy(buffer, begin_ptr, (size_t) (string - begin_ptr));
+      buffer[(unsigned int)(string - begin_ptr)]= 0;
+      begin_ptr= string+1;
+    }
+    else
+    {
+      size_t length= strlen(begin_ptr);
+      memcpy(buffer, begin_ptr, length);
+      buffer[length]= 0;
+      begin_ptr= end_ptr;
+    }
+
+    ptr= index(buffer, ':');
+
+    in_port_t port= 0;
+    if (ptr)
+    {
+      ptr[0]= 0;
+
+      ptr++;
+
+      errno= 0;
+      port= (in_port_t) strtoul(ptr, (char **)NULL, 10);
+      if (errno != 0)
+      {
+        memcached_server_free(servers);
+        return NULL;
+      }
+
+      ptr2= index(ptr, ' ');
+      if (! ptr2)
+        ptr2= index(ptr, ':');
+
+      if (ptr2)
+      {
+        ptr2++;
+        errno= 0;
+        weight= uint32_t(strtoul(ptr2, (char **)NULL, 10));
+        if (errno != 0)
+        {
+          memcached_server_free(servers);
+          return NULL;
+        }
+      }
+    }
+
+    servers= memcached_server_list_append_with_weight(servers, buffer, port, weight, &rc);
+
+    if (isspace(*begin_ptr))
+    {
+      begin_ptr++;
+    }
+  }
+
+  return servers;
+}
diff --git a/src/libmemcached/poll.cc b/src/libmemcached/poll.cc
new file mode 100644 (file)
index 0000000..6fdf242
--- /dev/null
@@ -0,0 +1,85 @@
+/* LibMemcached
+ * Copyright (C) 2013 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker, Trond Norbye
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Implementation of poll by using select
+ *
+ */
+
+#include "libmemcached/common.h"
+
+#if defined(_WIN32)
+#include "libmemcached/poll.h"
+
+#include <sys/time.h>
+#include <strings.h>
+
+int poll(struct pollfd fds[], nfds_t nfds, int tmo)
+{
+  fd_set readfds, writefds, errorfds;
+  FD_ZERO(&readfds);
+  FD_ZERO(&writefds);
+  FD_ZERO(&errorfds);
+
+  int maxfd= 0;
+
+  for (nfds_t x= 0; x < nfds; ++x)
+  {
+    if (fds[x].events & (POLLIN | POLLOUT))
+    {
+#ifndef _WIN32
+      if (fds[x].fd > maxfd)
+      {
+        maxfd= fds[x].fd;
+      }
+#endif
+      if (fds[x].events & POLLIN)
+      {
+        FD_SET(fds[x].fd, &readfds);
+      }
+      if (fds[x].events & POLLOUT)
+      {
+        FD_SET(fds[x].fd, &writefds);
+      }
+    }
+  }
+
+  struct timeval timeout= { .tv_sec = tmo / 1000,
+                            .tv_usec= (tmo % 1000) * 1000 };
+  struct timeval *tp= &timeout;
+  if (tmo == -1)
+  {
+    tp= NULL;
+  }
+  int ret= select(maxfd + 1, &readfds, &writefds, &errorfds, tp);
+  if (ret <= 0)
+  {
+    return ret;
+  }
+
+  /* Iterate through all of them because I need to clear the revent map */
+  for (nfds_t x= 0; x < nfds; ++x)
+  {
+    fds[x].revents= 0;
+    if (FD_ISSET(fds[x].fd, &readfds))
+    {
+      fds[x].revents |= POLLIN;
+    }
+    if (FD_ISSET(fds[x].fd, &writefds))
+    {
+      fds[x].revents |= POLLOUT;
+    }
+    if (FD_ISSET(fds[x].fd, &errorfds))
+    {
+      fds[x].revents |= POLLERR;
+    }
+  }
+
+   return ret;
+}
+
+#endif // defined(_WIN32)
diff --git a/src/libmemcached/poll.h b/src/libmemcached/poll.h
new file mode 100644 (file)
index 0000000..46636c4
--- /dev/null
@@ -0,0 +1,48 @@
+/* LibMemcached
+ * Copyright (C) 2013 Data Differential, http://datadifferential.com/
+ * Copyright (C) 2010 Brian Aker, Trond Norbye
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Implementation of poll by using select
+ *
+ */
+
+#pragma once
+
+#if defined(_WIN32)
+
+#include <winsock2.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pollfd
+{
+#if defined(_WIN32)
+  SOCKET fd;
+#else
+  int fd;
+#endif
+  short events;
+  short revents;
+} pollfd_t;
+
+typedef int nfds_t;
+
+#define POLLIN 0x0001
+#define POLLOUT 0x0004
+#define POLLERR 0x0008
+#define POLLHUP                0x010           /* Hung up.  */
+#define POLLNVAL       0x020           /* Invalid polling request.  */
+
+int poll(struct pollfd fds[], nfds_t nfds, int tmo);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // defined(_WIN32)
diff --git a/src/libmemcached/purge.cc b/src/libmemcached/purge.cc
new file mode 100644 (file)
index 0000000..4dbe24d
--- /dev/null
@@ -0,0 +1,165 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libmemcached/common.h>
+
+#define memcached_set_purging(__object, __value) ((__object)->state.is_purging= (__value))
+
+class Purge
+{
+public:
+  Purge(Memcached* arg) :
+    _memc(arg)
+  {
+    memcached_set_purging(_memc, true);
+  }
+
+  ~Purge()
+  {
+    memcached_set_purging(_memc, false);
+  }
+
+private:
+  Memcached* _memc;
+};
+
+class PollTimeout
+{
+public:
+  PollTimeout(Memcached* arg) :
+    _timeout(arg->poll_timeout),
+    _origin(arg->poll_timeout)
+  {
+    _origin = 2000;
+  }
+
+  ~PollTimeout()
+  {
+    _origin= _timeout;
+  }
+
+private:
+  int32_t _timeout;
+  int32_t& _origin;
+};
+
+bool memcached_purge(memcached_instance_st* ptr)
+{
+  Memcached *root= (Memcached *)ptr->root;
+
+  if (memcached_is_purging(ptr->root) || /* already purging */
+      (memcached_server_response_count(ptr) < ptr->root->io_msg_watermark &&
+       ptr->io_bytes_sent < ptr->root->io_bytes_watermark) ||
+      (ptr->io_bytes_sent >= ptr->root->io_bytes_watermark &&
+       memcached_server_response_count(ptr) < 2))
+  {
+    return true;
+  }
+
+  /*
+    memcached_io_write and memcached_response may call memcached_purge
+    so we need to be able stop any recursion.. 
+  */
+  Purge set_purge(root);
+
+  WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
+  /* 
+    Force a flush of the buffer to ensure that we don't have the n-1 pending
+    requests buffered up.. 
+  */
+  if (memcached_io_write(ptr) == false)
+  {
+    memcached_io_reset(ptr);
+    memcached_set_error(*ptr, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+    return false;
+  }
+  WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
+
+  bool is_successful= true;
+  uint32_t no_msg= memcached_server_response_count(ptr);
+  if (no_msg > 1)
+  {
+    memcached_result_st result;
+
+    /*
+     * We need to increase the timeout, because we might be waiting for
+     * data to be sent from the server (the commands was in the output buffer
+     * and just flushed
+   */
+    PollTimeout poll_timeout(ptr->root);
+
+    memcached_result_st* result_ptr= memcached_result_create(root, &result);
+    assert(result_ptr);
+
+    for (uint32_t x= 0; x < no_msg - 1; x++)
+    {
+      memcached_result_reset(result_ptr);
+      memcached_return_t rc= memcached_read_one_response(ptr, result_ptr);
+      /*
+       * Purge doesn't care for what kind of command results that is received.
+       * The only kind of errors I care about if is I'm out of sync with the
+       * protocol or have problems reading data from the network..
+     */
+      if (rc== MEMCACHED_PROTOCOL_ERROR or rc == MEMCACHED_UNKNOWN_READ_FAILURE or rc == MEMCACHED_READ_FAILURE)
+      {
+        WATCHPOINT_ERROR(rc);
+        is_successful= false;
+      }
+
+      if (ptr->root->callbacks != NULL)
+      {
+        memcached_callback_st cb = *ptr->root->callbacks;
+        if (memcached_success(rc))
+        {
+          for (uint32_t y= 0; y < cb.number_of_callback; y++)
+          {
+            if (memcached_fatal((*cb.callback[y])(ptr->root, result_ptr, cb.context)))
+            {
+              break;
+            }
+          }
+        }
+      }
+    }
+
+    memcached_result_free(result_ptr);
+  }
+
+  return is_successful;
+}
diff --git a/src/libmemcached/quit.cc b/src/libmemcached/quit.cc
new file mode 100644 (file)
index 0000000..5d17b31
--- /dev/null
@@ -0,0 +1,157 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+namespace {
+  memcached_return_t send_quit_message(memcached_instance_st* instance)
+  {
+    memcached_return_t rc;
+    if (instance->root->flags.binary_protocol)
+    {
+      protocol_binary_request_quit request= {}; // = {.bytes= {0}};
+
+      initialize_binary_request(instance, request.message.header);
+
+      request.message.header.request.opcode = PROTOCOL_BINARY_CMD_QUIT;
+      request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
+
+      libmemcached_io_vector_st vector[]=
+      {
+        { request.bytes, sizeof(request.bytes) }
+      };
+
+      rc= memcached_vdo(instance, vector, 1, true);
+    }
+    else
+    {
+      libmemcached_io_vector_st vector[]=
+      {
+        { memcached_literal_param("quit\r\n") }
+      };
+
+      rc= memcached_vdo(instance, vector, 1, true);
+    }
+
+    return rc;
+  }
+
+  void drain_instance(memcached_instance_st* instance)
+  {
+    /* read until socket is closed, or there is an error
+     * closing the socket before all data is read
+     * results in server throwing away all data which is
+     * not read
+     *
+     * In .40 we began to only do this if we had been doing buffered
+     * requests of had replication enabled.
+     */
+    if (instance->root->flags.buffer_requests or instance->root->number_of_replicas)
+    {
+      memcached_io_slurp(instance);
+    }
+
+    /*
+     * memcached_io_read may call memcached_quit_server with io_death if
+     * it encounters problems, but we don't care about those occurences.
+     * The intention of that loop is to drain the data sent from the
+     * server to ensure that the server processed all of the data we
+     * sent to the server.
+     */
+    instance->server_failure_counter= 0;
+    instance->server_timeout_counter= 0;
+  }
+}
+
+/*
+  This closes all connections (forces flush of input as well).
+
+  Maybe add a host specific, or key specific version?
+
+  The reason we send "quit" is that in case we have buffered IO, this
+  will force data to be completed.
+*/
+
+void memcached_quit_server(memcached_instance_st* instance, bool io_death)
+{
+  if (instance->valid())
+  {
+    if (io_death == false and memcached_is_udp(instance->root) == false and instance->is_shutting_down() == false)
+    {
+      send_quit_message(instance);
+
+      instance->start_close_socket();
+      drain_instance(instance);
+    }
+  }
+
+  instance->close_socket();
+
+  if (io_death and memcached_is_udp(instance->root))
+  {
+    /*
+       If using UDP, we should stop using the server briefly on every IO
+       failure. If using TCP, it may be that the connection went down a
+       short while ago (e.g. the server failed) and we've only just
+       noticed, so we should only set the retry timeout on a connect
+       failure (which doesn't call this method).
+       */
+    memcached_mark_server_for_timeout(instance);
+  }
+}
+
+void send_quit(Memcached *memc)
+{
+  for (uint32_t x= 0; x < memcached_server_count(memc); x++)
+  {
+    memcached_instance_st* instance= memcached_instance_fetch(memc, x);
+
+    memcached_quit_server(instance, false);
+  }
+}
+
+void memcached_quit(memcached_st *shell)
+{
+  Memcached* memc= memcached2Memcached(shell);
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(memc, true)))
+  {
+    return;
+  }
+
+  send_quit(memc);
+}
diff --git a/src/libmemcached/quit.hpp b/src/libmemcached/quit.hpp
new file mode 100644 (file)
index 0000000..a48a8a7
--- /dev/null
@@ -0,0 +1,41 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+void memcached_quit_server(memcached_instance_st* ptr, bool io_death);
+
+void send_quit(memcached_st *ptr);
diff --git a/src/libmemcached/response.cc b/src/libmemcached/response.cc
new file mode 100644 (file)
index 0000000..3d1e764
--- /dev/null
@@ -0,0 +1,940 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+#include <libmemcached/string.hpp>
+
+static memcached_return_t textual_value_fetch(memcached_instance_st* instance,
+                                              char *buffer,
+                                              memcached_result_st *result)
+{
+  char *next_ptr;
+  ssize_t read_length= 0;
+  size_t value_length;
+
+  WATCHPOINT_ASSERT(instance->root);
+  char *end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
+
+  memcached_result_reset(result);
+
+  char *string_ptr= buffer;
+  string_ptr+= 6; /* "VALUE " */
+
+
+  // Just used for cases of AES decrypt currently
+  memcached_return_t rc= MEMCACHED_SUCCESS;
+
+  /* We load the key */
+  {
+    char *key= result->item_key;
+    result->key_length= 0;
+
+    for (ptrdiff_t prefix_length= memcached_array_size(instance->root->_namespace); !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
+    {
+      if (prefix_length == 0)
+      {
+        *key= *string_ptr;
+        key++;
+        result->key_length++;
+      }
+      else
+        prefix_length--;
+    }
+    result->item_key[result->key_length]= 0;
+  }
+
+  if (end_ptr == string_ptr)
+  {
+    goto read_error;
+  }
+
+  /* Flags fetch move past space */
+  string_ptr++;
+  if (end_ptr == string_ptr)
+  {
+    goto read_error;
+  }
+
+  for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
+  errno= 0;
+  result->item_flags= (uint32_t) strtoul(next_ptr, &string_ptr, 10);
+
+  if (errno != 0 or end_ptr == string_ptr)
+  {
+    goto read_error;
+  }
+
+  /* Length fetch move past space*/
+  string_ptr++;
+  if (end_ptr == string_ptr)
+  {
+    goto read_error;
+  }
+
+  for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
+  errno= 0;
+  value_length= (size_t)strtoull(next_ptr, &string_ptr, 10);
+
+  if (errno != 0 or end_ptr == string_ptr)
+  {
+    goto read_error;
+  }
+
+  /* Skip spaces */
+  if (*string_ptr == '\r')
+  {
+    /* Skip past the \r\n */
+    string_ptr+= 2;
+  }
+  else
+  {
+    string_ptr++;
+    for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++) {};
+    errno= 0;
+    result->item_cas= strtoull(next_ptr, &string_ptr, 10);
+  }
+
+  if (errno != 0 or end_ptr < string_ptr)
+  {
+    goto read_error;
+  }
+
+  /* We add two bytes so that we can walk the \r\n */
+  if (memcached_failed(memcached_string_check(&result->value, value_length +2)))
+  {
+    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+  }
+
+  {
+    char *value_ptr= memcached_string_value_mutable(&result->value);
+    /*
+      We read the \r\n into the string since not doing so is more
+      cycles then the waster of memory to do so.
+
+      We are null terminating through, which will most likely make
+      some people lazy about using the return length.
+    */
+    size_t to_read= (value_length) + 2;
+    memcached_return_t rrc= memcached_io_read(instance, value_ptr, to_read, read_length);
+    if (memcached_failed(rrc) and rrc == MEMCACHED_IN_PROGRESS)
+    {
+      memcached_quit_server(instance, true);
+      return memcached_set_error(*instance, MEMCACHED_IN_PROGRESS, MEMCACHED_AT);
+    }
+    else if (memcached_failed(rrc))
+    {
+      return rrc;
+    }
+  }
+
+  if (read_length != (ssize_t)(value_length + 2))
+  {
+    goto read_error;
+  }
+
+  /* This next bit blows the API, but this is internal....*/
+  {
+    char *char_ptr;
+    char_ptr= memcached_string_value_mutable(&result->value);;
+    char_ptr[value_length]= 0;
+    char_ptr[value_length +1]= 0;
+    memcached_string_set_length(&result->value, value_length);
+  }
+
+  if (memcached_is_encrypted(instance->root) and memcached_result_length(result))
+  {
+    hashkit_string_st *destination;
+
+    if ((destination= hashkit_decrypt(&instance->root->hashkit,
+                                      memcached_result_value(result), memcached_result_length(result))) == NULL)
+    {
+      rc= memcached_set_error(*instance->root, MEMCACHED_FAILURE, 
+                              MEMCACHED_AT, memcached_literal_param("hashkit_decrypt() failed"));
+    }
+    else
+    {
+      memcached_result_reset_value(result);
+      if (memcached_failed(memcached_result_set_value(result, hashkit_string_c_str(destination), hashkit_string_length(destination))))
+      {
+        rc= memcached_set_error(*instance->root, MEMCACHED_FAILURE, 
+                                MEMCACHED_AT, memcached_literal_param("hashkit_decrypt() failed"));
+      }
+    }
+
+    if (memcached_failed(rc))
+    {
+      memcached_result_reset(result);
+    }
+    hashkit_string_free(destination);
+  }
+
+  return rc;
+
+read_error:
+  memcached_io_reset(instance);
+
+  return MEMCACHED_PARTIAL_READ;
+}
+
+static memcached_return_t textual_read_one_response(memcached_instance_st* instance,
+                                                    char *buffer, const size_t buffer_length,
+                                                    memcached_result_st *result)
+{
+  size_t total_read;
+  memcached_return_t rc= memcached_io_readline(instance, buffer, buffer_length, total_read);
+
+  if (memcached_failed(rc))
+  {
+    return rc;
+  }
+  assert(total_read);
+
+  switch(buffer[0])
+  {
+  case 'V':
+    {
+      // VALUE
+      if (buffer[1] == 'A' and buffer[2] == 'L' and buffer[3] == 'U' and buffer[4] == 'E') /* VALUE */
+      {
+        /* We add back in one because we will need to search for END */
+        memcached_server_response_increment(instance);
+        return textual_value_fetch(instance, buffer, result);
+      }
+      // VERSION
+      else if (buffer[1] == 'E' and buffer[2] == 'R' and buffer[3] == 'S' and buffer[4] == 'I' and buffer[5] == 'O' and buffer[6] == 'N') /* VERSION */
+      {
+        /* Find the space, and then move one past it to copy version */
+        char *response_ptr= index(buffer, ' ');
+
+        char *endptr;
+        errno= 0;
+        long int version= strtol(response_ptr, &endptr, 10);
+        if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX or version == 0)
+        {
+          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version"));
+        }
+        instance->major_version= uint8_t(version);
+
+        endptr++;
+        errno= 0;
+        version= strtol(endptr, &endptr, 10);
+        if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX)
+        {
+          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse minor version"));
+        }
+        instance->minor_version= uint8_t(version);
+
+        endptr++;
+        errno= 0;
+        version= strtol(endptr, &endptr, 10);
+        if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX)
+        {
+          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
+        }
+        instance->micro_version= uint8_t(version);
+
+        return MEMCACHED_SUCCESS;
+      }
+    }
+    break;
+
+  case 'O':
+    {
+      // OK
+      if (buffer[1] == 'K')
+      {
+        return MEMCACHED_SUCCESS;
+      }
+    }
+    break;
+
+  case 'S':
+    {
+      // STAT
+      if (buffer[1] == 'T' and buffer[2] == 'A' and buffer[3] == 'T') /* STORED STATS */
+      {
+        memcached_server_response_increment(instance);
+        return MEMCACHED_STAT;
+      }
+      // SERVER_ERROR
+      else if (buffer[1] == 'E' and buffer[2] == 'R' and buffer[3] == 'V' and buffer[4] == 'E' and buffer[5] == 'R'
+               and buffer[6] == '_' 
+               and buffer[7] == 'E' and buffer[8] == 'R' and buffer[9] == 'R' and buffer[10] == 'O' and buffer[11] == 'R' )
+      {
+        if (total_read == memcached_literal_param_size("SERVER_ERROR"))
+        {
+          return MEMCACHED_SERVER_ERROR;
+        }
+
+        if (total_read >= memcached_literal_param_size("SERVER_ERROR object too large for cache") and
+            (memcmp(buffer, memcached_literal_param("SERVER_ERROR object too large for cache")) == 0))
+        {
+          return MEMCACHED_E2BIG;
+        }
+
+        if (total_read >= memcached_literal_param_size("SERVER_ERROR out of memory") and
+            ((memcmp(buffer, memcached_literal_param("SERVER_ERROR out of memory")) == 0) or
+                (memcmp(buffer, memcached_literal_param("SERVER_ERROR Out of memory")) == 0)))
+        {
+          return MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE;
+        }
+
+        // Move past the basic error message and whitespace
+        char *startptr= buffer + memcached_literal_param_size("SERVER_ERROR");
+        if (startptr[0] == ' ')
+        {
+          startptr++;
+        }
+
+        char *endptr= startptr;
+        while (*endptr != '\r' && *endptr != '\n') endptr++;
+
+        return memcached_set_error(*instance, MEMCACHED_SERVER_ERROR, MEMCACHED_AT, startptr, size_t(endptr - startptr));
+      }
+      // STORED
+      else if (buffer[1] == 'T' and buffer[2] == 'O' and buffer[3] == 'R') //  and buffer[4] == 'E' and buffer[5] == 'D')
+      {
+        return MEMCACHED_STORED;
+      }
+    }
+    break;
+
+  case 'D':
+    {
+      // DELETED
+      if (buffer[1] == 'E' and buffer[2] == 'L' and buffer[3] == 'E' and buffer[4] == 'T' and buffer[5] == 'E' and buffer[6] == 'D')
+      {
+        return MEMCACHED_DELETED;
+      }
+    }
+    break;
+
+  case 'N':
+    {
+      // NOT_FOUND
+      if (buffer[1] == 'O' and buffer[2] == 'T' 
+          and buffer[3] == '_'
+          and buffer[4] == 'F' and buffer[5] == 'O' and buffer[6] == 'U' and buffer[7] == 'N' and buffer[8] == 'D')
+      {
+        return MEMCACHED_NOTFOUND;
+      }
+      // NOT_STORED
+      else if (buffer[1] == 'O' and buffer[2] == 'T' 
+               and buffer[3] == '_'
+               and buffer[4] == 'S' and buffer[5] == 'T' and buffer[6] == 'O' and buffer[7] == 'R' and buffer[8] == 'E' and buffer[9] == 'D')
+      {
+        return MEMCACHED_NOTSTORED;
+      }
+    }
+    break;
+
+  case 'E': /* PROTOCOL ERROR or END */
+    {
+      // END
+      if (buffer[1] == 'N' and buffer[2] == 'D')
+      {
+        return MEMCACHED_END;
+      }
+#if 0
+      // PROTOCOL_ERROR
+      else if (buffer[1] == 'R' and buffer[2] == 'O' and buffer[3] == 'T' and buffer[4] == 'O' and buffer[5] == 'C' and buffer[6] == 'O' and buffer[7] == 'L'
+               and buffer[8] == '_'
+               and buffer[9] == 'E' and buffer[10] == 'R' and buffer[11] == 'R' and buffer[12] == 'O' and buffer[13] == 'R')
+      {
+        return MEMCACHED_PROTOCOL_ERROR;
+      }
+#endif
+      // ERROR
+      else if (buffer[1] == 'R' and buffer[2] == 'R' and buffer[3] == 'O' and buffer[4] == 'R')
+      {
+        return MEMCACHED_ERROR;
+      }
+      // EXISTS
+      else if (buffer[1] == 'X' and buffer[2] == 'I' and buffer[3] == 'S' and buffer[4] == 'T' and buffer[5] == 'S')
+      {
+        return MEMCACHED_DATA_EXISTS;
+      }
+    }
+    break;
+
+  case 'T': /* TOUCHED */
+    {
+      // TOUCHED
+      if (buffer[1] == 'O' and buffer[2] == 'U' and buffer[3] == 'C' and buffer[4] == 'H' and buffer[5] == 'E' and buffer[6] == 'D')
+      {
+        return MEMCACHED_SUCCESS;
+      }
+    }
+    break;
+
+  case 'I': /* ITEM */
+    {
+      // ITEM
+      if (buffer[1] == 'T' and buffer[2] == 'E' and buffer[3] == 'M')
+      {
+        /* We add back in one because we will need to search for END */
+        memcached_server_response_increment(instance);
+        return MEMCACHED_ITEM;
+      }
+    }
+    break;
+
+  case 'C': /* CLIENT ERROR */
+    {
+      // CLIENT_ERROR
+      if (buffer[1] == 'L' and buffer[2] == 'I' and buffer[3] == 'E' and buffer[4] == 'N' and buffer[5] == 'T'
+          and buffer[6] == '_'
+          and buffer[7] == 'E' and buffer[8] == 'R' and buffer[9] == 'R' and buffer[10] == 'O' and buffer[11] == 'R')
+      {
+        // Move past the basic error message and whitespace
+        char *startptr= buffer + memcached_literal_param_size("CLIENT_ERROR");
+        if (startptr[0] == ' ')
+        {
+          startptr++;
+        }
+
+        char *endptr= startptr;
+        while (*endptr != '\r' && *endptr != '\n') endptr++;
+
+        return memcached_set_error(*instance, MEMCACHED_CLIENT_ERROR, MEMCACHED_AT, startptr, size_t(endptr - startptr));
+      }
+    }
+    break;
+
+  case '0': /* INCR/DECR response */
+  case '1': /* INCR/DECR response */
+  case '2': /* INCR/DECR response */
+  case '3': /* INCR/DECR response */
+  case '4': /* INCR/DECR response */
+  case '5': /* INCR/DECR response */
+  case '6': /* INCR/DECR response */
+  case '7': /* INCR/DECR response */
+  case '8': /* INCR/DECR response */
+  case '9': /* INCR/DECR response */
+    {
+      errno= 0;
+      unsigned long long int auto_return_value= strtoull(buffer, (char **)NULL, 10);
+
+      if (auto_return_value == ULLONG_MAX and errno == ERANGE)
+      {
+        result->numeric_value= UINT64_MAX;
+        return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
+                                   memcached_literal_param("Numeric response was out of range"));
+      }
+      else if (errno == EINVAL)
+      {
+        result->numeric_value= UINT64_MAX;
+        return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
+                                   memcached_literal_param("Numeric response was out of range"));
+      }
+      else if (errno != 0)
+      {
+        result->numeric_value= UINT64_MAX;
+        return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
+                                   memcached_literal_param("Numeric response was out of range"));
+      }
+
+      result->numeric_value= uint64_t(auto_return_value);
+
+      WATCHPOINT_STRING(buffer);
+      return MEMCACHED_SUCCESS;
+    }
+
+  default:
+    break;
+  }
+
+  buffer[total_read]= 0;
+#if 0
+  if (total_read >= sizeof("STORSTORED") -1)
+  {
+    fprintf(stderr, "%s:%d '%s', %.*s\n", __FILE__, __LINE__,
+            buffer, MEMCACHED_MAX_BUFFER, instance->read_buffer);
+    assert(memcmp(buffer,"STORSTORED", sizeof("STORSTORED") -1));
+  }
+#endif
+  return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT,
+                             buffer, total_read);
+}
+
+static memcached_return_t binary_read_one_response(memcached_instance_st* instance,
+                                                   char *buffer, const size_t buffer_length,
+                                                   memcached_result_st *result)
+{
+  memcached_return_t rc;
+  protocol_binary_response_header header;
+
+  assert(memcached_is_binary(instance->root));
+
+  if ((rc= memcached_safe_read(instance, &header.bytes, sizeof(header.bytes))) != MEMCACHED_SUCCESS)
+  {
+    WATCHPOINT_ERROR(rc);
+    return rc;
+  }
+
+  if (header.response.magic != PROTOCOL_BINARY_RES)
+  {
+    return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+  }
+
+  /*
+   ** Convert the header to host local endian!
+ */
+  header.response.keylen= ntohs(header.response.keylen);
+  header.response.status= ntohs(header.response.status);
+  header.response.bodylen= ntohl(header.response.bodylen);
+  header.response.cas= memcached_ntohll(header.response.cas);
+  uint32_t bodylen= header.response.bodylen;
+
+  if (header.response.status == PROTOCOL_BINARY_RESPONSE_SUCCESS or
+      header.response.status == PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE)
+  {
+    switch (header.response.opcode)
+    {
+    case PROTOCOL_BINARY_CMD_GETKQ:
+      /*
+       * We didn't increment the response counter for the GETKQ packet
+       * (only the final NOOP), so we need to increment the counter again.
+       */
+      memcached_server_response_increment(instance);
+      /* fall through */
+    case PROTOCOL_BINARY_CMD_GETK:
+      {
+        uint16_t keylen= header.response.keylen;
+        memcached_result_reset(result);
+        result->item_cas= header.response.cas;
+
+        if ((rc= memcached_safe_read(instance, &result->item_flags, sizeof (result->item_flags))) != MEMCACHED_SUCCESS)
+        {
+          WATCHPOINT_ERROR(rc);
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+        }
+
+        result->item_flags= ntohl(result->item_flags);
+        bodylen -= header.response.extlen;
+
+        result->key_length= keylen;
+        if (memcached_failed(rc= memcached_safe_read(instance, result->item_key, keylen)))
+        {
+          WATCHPOINT_ERROR(rc);
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+        }
+
+        // Only bother with doing this if key_length > 0
+        if (result->key_length)
+        {
+          if (memcached_array_size(instance->root->_namespace) and memcached_array_size(instance->root->_namespace) >= result->key_length)
+          {
+            return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+          }
+
+          if (memcached_array_size(instance->root->_namespace))
+          {
+            result->key_length-= memcached_array_size(instance->root->_namespace);
+            memmove(result->item_key, result->item_key +memcached_array_size(instance->root->_namespace), result->key_length);
+          }
+        }
+
+        bodylen -= keylen;
+        if (memcached_failed(memcached_string_check(&result->value, bodylen)))
+        {
+          return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+        }
+
+        char *vptr= memcached_string_value_mutable(&result->value);
+        if (memcached_failed(rc= memcached_safe_read(instance, vptr, bodylen)))
+        {
+          WATCHPOINT_ERROR(rc);
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+        }
+
+        memcached_string_set_length(&result->value, bodylen);
+      }
+      break;
+
+    case PROTOCOL_BINARY_CMD_INCREMENT:
+    case PROTOCOL_BINARY_CMD_DECREMENT:
+      {
+        if (bodylen != sizeof(uint64_t))
+        {
+          result->numeric_value= UINT64_MAX;
+          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+        }
+
+        uint64_t val;
+        if ((rc= memcached_safe_read(instance, &val, sizeof(val))) != MEMCACHED_SUCCESS)
+        {
+          result->numeric_value= UINT64_MAX;
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+        }
+
+        result->numeric_value= memcached_ntohll(val);
+      }
+      break;
+
+    case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS:
+      {
+        if (header.response.keylen != 0 || bodylen + 1 > buffer_length)
+        {
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+        }
+        else
+        {
+          if ((rc= memcached_safe_read(instance, buffer, bodylen)) != MEMCACHED_SUCCESS)
+          {
+            return MEMCACHED_UNKNOWN_READ_FAILURE;
+          }
+        }
+      }
+      break;
+
+    case PROTOCOL_BINARY_CMD_VERSION:
+      {
+        char version_buffer[32]; // @todo document this number
+        memset(version_buffer, 0, sizeof(version_buffer));
+
+        if (memcached_safe_read(instance, version_buffer, bodylen) != MEMCACHED_SUCCESS)
+        {
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+        }
+
+        char *endptr;
+        errno= 0;
+        long int version= strtol(version_buffer, &endptr, 10);
+        if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX or version == 0)
+        {
+          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse major version"));
+        }
+        instance->major_version= uint8_t(version);
+
+        endptr++;
+        errno= 0;
+        version= strtol(endptr, &endptr, 10);
+        if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX)
+        {
+          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse minor version"));
+        }
+        instance->minor_version= uint8_t(version);
+
+        endptr++;
+        errno= 0;
+        version= strtol(endptr, &endptr, 10);
+        if (errno != 0 or version == LONG_MIN or version == LONG_MAX or version > UINT8_MAX)
+        {
+          instance->major_version= instance->minor_version= instance->micro_version= UINT8_MAX;
+          return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT, memcached_literal_param("strtol() failed to parse micro version"));
+        }
+        instance->micro_version= uint8_t(version);
+      }
+      break;
+
+    case PROTOCOL_BINARY_CMD_TOUCH:
+      {
+        rc= MEMCACHED_SUCCESS;
+        if (bodylen == 4) // The four byte read is a bug?
+        {
+          char touch_buffer[4]; // @todo document this number
+          rc= memcached_safe_read(instance, touch_buffer, sizeof(touch_buffer));
+#if 0
+          fprintf(stderr, "%s:%d %d %d %d %d %.*s(%d)\n", __FILE__, __LINE__,
+                  int(touch_buffer[0]),
+                  int(touch_buffer[1]),
+                  int(touch_buffer[2]),
+                  int(touch_buffer[3]),
+                  int(bodylen), touch_buffer, int(bodylen));
+#endif
+        }
+        return memcached_set_error(*instance, rc, MEMCACHED_AT);
+      }
+
+    case PROTOCOL_BINARY_CMD_FLUSH:
+    case PROTOCOL_BINARY_CMD_QUIT:
+    case PROTOCOL_BINARY_CMD_SET:
+    case PROTOCOL_BINARY_CMD_ADD:
+    case PROTOCOL_BINARY_CMD_REPLACE:
+    case PROTOCOL_BINARY_CMD_APPEND:
+    case PROTOCOL_BINARY_CMD_PREPEND:
+    case PROTOCOL_BINARY_CMD_DELETE:
+      {
+        WATCHPOINT_ASSERT(bodylen == 0);
+        return MEMCACHED_SUCCESS;
+      }
+
+    case PROTOCOL_BINARY_CMD_NOOP:
+      {
+        WATCHPOINT_ASSERT(bodylen == 0);
+        return MEMCACHED_END;
+      }
+
+    case PROTOCOL_BINARY_CMD_STAT:
+      {
+        if (bodylen == 0)
+        {
+          return MEMCACHED_END;
+        }
+        else if (bodylen + 1 > buffer_length)
+        {
+          /* not enough space in buffer.. should not happen... */
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+        }
+        else
+        {
+          size_t keylen= header.response.keylen;
+          memset(buffer, 0, buffer_length);
+          if ((rc= memcached_safe_read(instance, buffer, keylen)) != MEMCACHED_SUCCESS ||
+              (rc= memcached_safe_read(instance, buffer + keylen + 1, bodylen - keylen)) != MEMCACHED_SUCCESS)
+          {
+            WATCHPOINT_ERROR(rc);
+            return MEMCACHED_UNKNOWN_READ_FAILURE;
+          }
+        }
+      }
+      break;
+
+    case PROTOCOL_BINARY_CMD_SASL_AUTH:
+    case PROTOCOL_BINARY_CMD_SASL_STEP:
+      {
+        memcached_result_reset(result);
+        result->item_cas= header.response.cas;
+
+        if (memcached_string_check(&result->value,
+                                   bodylen) != MEMCACHED_SUCCESS)
+          return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+
+        char *vptr= memcached_string_value_mutable(&result->value);
+        if ((rc= memcached_safe_read(instance, vptr, bodylen)) != MEMCACHED_SUCCESS)
+        {
+          WATCHPOINT_ERROR(rc);
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+        }
+
+        memcached_string_set_length(&result->value, bodylen);
+      }
+      break;
+    default:
+      {
+        /* Command not implemented yet! */
+        return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+      }
+    }
+  }
+  else if (header.response.bodylen)
+  {
+    /* What should I do with the error message??? just discard it for now */
+    char hole[SMALL_STRING_LEN];
+    while (bodylen > 0)
+    {
+      size_t nr= (bodylen > SMALL_STRING_LEN) ? SMALL_STRING_LEN : bodylen;
+      if ((rc= memcached_safe_read(instance, hole, nr)) != MEMCACHED_SUCCESS)
+      {
+        WATCHPOINT_ERROR(rc);
+        return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+      }
+      bodylen-= (uint32_t) nr;
+    }
+
+    /* This might be an error from one of the quiet commands.. if
+     * so, just throw it away and get the next one. What about creating
+     * a callback to the user with the error information?
+   */
+    switch (header.response.opcode)
+    {
+    case PROTOCOL_BINARY_CMD_SETQ:
+    case PROTOCOL_BINARY_CMD_ADDQ:
+    case PROTOCOL_BINARY_CMD_REPLACEQ:
+    case PROTOCOL_BINARY_CMD_APPENDQ:
+    case PROTOCOL_BINARY_CMD_PREPENDQ:
+      return MEMCACHED_FETCH_NOTFINISHED;
+
+    default:
+      break;
+    }
+  }
+
+  rc= MEMCACHED_SUCCESS;
+  if (header.response.status != 0)
+  {
+    switch (header.response.status)
+    {
+    case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT:
+      rc= MEMCACHED_NOTFOUND;
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS:
+      rc= MEMCACHED_DATA_EXISTS;
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_NOT_STORED:
+      rc= MEMCACHED_NOTSTORED;
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_E2BIG:
+      rc= MEMCACHED_E2BIG;
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_ENOMEM:
+      rc= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_AUTH_CONTINUE:
+      rc= MEMCACHED_AUTH_CONTINUE;
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_AUTH_ERROR:
+      rc= MEMCACHED_AUTH_FAILURE;
+      break;
+
+    case PROTOCOL_BINARY_RESPONSE_EINVAL:
+    case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
+    default:
+      return memcached_set_error(*instance, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+      break;
+    }
+  }
+
+  return rc;
+}
+
+static memcached_return_t _read_one_response(memcached_instance_st* instance,
+                                             char *buffer, const size_t buffer_length,
+                                             memcached_result_st *result)
+{
+  memcached_server_response_decrement(instance);
+
+  if (result == NULL)
+  {
+    Memcached *root= (Memcached *)instance->root;
+    result = &root->result;
+  }
+
+  memcached_return_t rc;
+  if (memcached_is_binary(instance->root))
+  {
+    do {
+      rc= binary_read_one_response(instance, buffer, buffer_length, result);
+    } while (rc == MEMCACHED_FETCH_NOTFINISHED);
+  }
+  else
+  {
+    rc= textual_read_one_response(instance, buffer, buffer_length, result);
+  }
+
+  if (memcached_fatal(rc))
+  {
+    memcached_io_reset(instance);
+  }
+
+  return rc;
+}
+
+memcached_return_t memcached_read_one_response(memcached_instance_st* instance,
+                                               memcached_result_st *result)
+{
+  char buffer[SMALL_STRING_LEN];
+
+  if (memcached_is_udp(instance->root))
+  {
+    return memcached_set_error(*instance, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+  }
+
+
+  return _read_one_response(instance, buffer, sizeof(buffer), result);
+}
+
+memcached_return_t memcached_response(memcached_instance_st* instance,
+                                      memcached_result_st *result)
+{
+  char buffer[1024];
+
+  return memcached_response(instance, buffer, sizeof(buffer), result);
+}
+
+memcached_return_t memcached_response(memcached_instance_st* instance,
+                                      char *buffer, size_t buffer_length,
+                                      memcached_result_st *result)
+{
+  if (memcached_is_udp(instance->root))
+  {
+    return memcached_set_error(*instance, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+  }
+
+  /* We may have old commands in the buffer not sent, first purge */
+  if ((instance->root->flags.no_block) and (memcached_is_processing_input(instance->root) == false))
+  {
+    (void)memcached_io_write(instance);
+  }
+
+  /*  Before going into loop wait to see if we have any IO waiting for us */
+  if (0)
+  {
+    memcached_return_t read_rc= memcached_io_wait_for_read(instance);
+    fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, memcached_strerror(NULL, read_rc));
+  }
+
+  /*
+   * The previous implementation purged all pending requests and just
+   * returned the last one. Purge all pending messages to ensure backwards
+   * compatibility.
+ */
+  if (memcached_is_binary(instance->root) == false and memcached_server_response_count(instance) > 1)
+  {
+    memcached_result_st junked_result;
+    memcached_result_st *junked_result_ptr= memcached_result_create(instance->root, &junked_result);
+
+    assert(junked_result_ptr);
+
+    while (memcached_server_response_count(instance) > 1)
+    {
+      memcached_return_t rc= _read_one_response(instance, buffer, buffer_length, junked_result_ptr);
+
+      // @TODO should we return an error on another but a bad read case?
+      if (memcached_fatal(rc))
+      {
+        memcached_result_free(junked_result_ptr);
+        return rc;
+      }
+    }
+    memcached_result_free(junked_result_ptr);
+  }
+
+  return _read_one_response(instance, buffer, buffer_length, result);
+}
diff --git a/src/libmemcached/response.h b/src/libmemcached/response.h
new file mode 100644 (file)
index 0000000..c066f3b
--- /dev/null
@@ -0,0 +1,49 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+/* Read a single response from the server */
+memcached_return_t memcached_read_one_response(memcached_instance_st* ptr,
+                                               memcached_result_st *result);
+
+memcached_return_t memcached_response(memcached_instance_st* ptr,
+                                      memcached_result_st *result);
+
+memcached_return_t memcached_response(memcached_instance_st* ptr,
+                                      char *buffer, size_t buffer_length,
+                                      memcached_result_st *result);
diff --git a/src/libmemcached/result.cc b/src/libmemcached/result.cc
new file mode 100644 (file)
index 0000000..6fa507b
--- /dev/null
@@ -0,0 +1,189 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+/*
+  memcached_result_st are used to internally represent the return values from
+  memcached. We use a structure so that long term as identifiers are added
+  to memcached we will be able to absorb new attributes without having
+  to addjust the entire API.
+*/
+#include <libmemcached/common.h>
+
+static inline void _result_init(memcached_result_st *self,
+                                Memcached *memc)
+{
+  self->item_flags= 0;
+  self->item_expiration= 0;
+  self->key_length= 0;
+  self->item_cas= 0;
+  self->root= memc;
+  self->numeric_value= UINT64_MAX;
+  self->count= 0;
+  self->item_key[0]= 0;
+}
+
+memcached_result_st *memcached_result_create(const memcached_st *shell,
+                                             memcached_result_st *ptr)
+{
+  const Memcached* memc= memcached2Memcached(shell);
+
+  /* Saving malloc calls :) */
+  if (ptr)
+  {
+    ptr->options.is_allocated= false;
+  }
+  else
+  {
+    ptr= libmemcached_xmalloc(memc, memcached_result_st);
+
+    if (not ptr)
+    {
+      return NULL;
+    }
+
+    ptr->options.is_allocated= true;
+  }
+
+  ptr->options.is_initialized= true;
+
+  _result_init(ptr, (memcached_st *)memc);
+
+  WATCHPOINT_SET(ptr->value.options.is_initialized= false);
+  memcached_string_create((memcached_st*)memc, &ptr->value, 0);
+  WATCHPOINT_ASSERT_INITIALIZED(&ptr->value);
+  WATCHPOINT_ASSERT(ptr->value.string == NULL);
+
+  return ptr;
+}
+
+void memcached_result_reset(memcached_result_st *ptr)
+{
+  ptr->key_length= 0;
+  memcached_string_reset(&ptr->value);
+  ptr->item_flags= 0;
+  ptr->item_cas= 0;
+  ptr->item_expiration= 0;
+  ptr->numeric_value= UINT64_MAX;
+}
+
+void memcached_result_free(memcached_result_st *ptr)
+{
+  if (ptr == NULL)
+  {
+    return;
+  }
+
+  memcached_string_free(&ptr->value);
+  ptr->numeric_value= UINT64_MAX;
+
+  if (memcached_is_allocated(ptr))
+  {
+    WATCHPOINT_ASSERT(ptr->root); // Without a root, that means that result was not properly initialized.
+    libmemcached_free(ptr->root, ptr);
+  }
+  else
+  {
+    ptr->count= 0;
+    ptr->options.is_initialized= false;
+  }
+}
+
+void memcached_result_reset_value(memcached_result_st *ptr)
+{
+  memcached_string_reset(&ptr->value);
+}
+
+memcached_return_t memcached_result_set_value(memcached_result_st *ptr,
+                                              const char *value,
+                                              size_t length)
+{
+  if (memcached_failed(memcached_string_append(&ptr->value, value, length)))
+  {
+    return memcached_set_errno(*ptr->root, errno, MEMCACHED_AT);
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+const char *memcached_result_key_value(const memcached_result_st *self)
+{
+  return self->key_length ? self->item_key : NULL;
+}
+
+size_t memcached_result_key_length(const memcached_result_st *self)
+{
+  return self->key_length;
+}
+
+const char *memcached_result_value(const memcached_result_st *self)
+{
+  const memcached_string_st *sptr= &self->value;
+  return memcached_string_value(sptr);
+}
+
+size_t memcached_result_length(const memcached_result_st *self)
+{
+  const memcached_string_st *sptr= &self->value;
+  return memcached_string_length(sptr);
+}
+
+char *memcached_result_take_value(memcached_result_st *self)
+{
+  memcached_string_st *sptr= &self->value;
+  return memcached_string_take_value(sptr);
+}
+
+uint32_t memcached_result_flags(const memcached_result_st *self)
+{
+  return self->item_flags;
+}
+
+uint64_t memcached_result_cas(const memcached_result_st *self)
+{
+  return self->item_cas;
+}
+
+void memcached_result_set_flags(memcached_result_st *self, uint32_t flags)
+{
+  self->item_flags= flags;
+}
+
+void memcached_result_set_expiration(memcached_result_st *self, time_t expiration)
+{
+  self->item_expiration= expiration;
+}
diff --git a/src/libmemcached/result.h b/src/libmemcached/result.h
new file mode 100644 (file)
index 0000000..624ff5a
--- /dev/null
@@ -0,0 +1,39 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+void memcached_result_reset_value(memcached_result_st *ptr);
diff --git a/src/libmemcached/sasl.cc b/src/libmemcached/sasl.cc
new file mode 100644 (file)
index 0000000..89462e5
--- /dev/null
@@ -0,0 +1,544 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libmemcached/common.h"
+#include <cassert>
+#include <atomic>
+
+#if defined(LIBMEMCACHED_WITH_SASL_SUPPORT) && LIBMEMCACHED_WITH_SASL_SUPPORT
+
+#if defined(HAVE_LIBSASL) && HAVE_LIBSASL
+#include <sasl/sasl.h>
+#endif
+
+#define CAST_SASL_CB(cb) reinterpret_cast<int(*)()>(reinterpret_cast<intptr_t>(cb))
+
+#include <pthread.h>
+
+void memcached_set_sasl_callbacks(memcached_st *shell,
+                                  const sasl_callback_t *callbacks)
+{
+  Memcached* self= memcached2Memcached(shell);
+  if (self)
+  {
+    self->sasl.callbacks= const_cast<sasl_callback_t *>(callbacks);
+    self->sasl.is_allocated= false;
+  }
+}
+
+sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *shell)
+{
+  Memcached* self= memcached2Memcached(shell);
+  if (self)
+  {
+    return self->sasl.callbacks;
+  }
+
+  return NULL;
+}
+
+/**
+ * Resolve the names for both ends of a connection
+ * @param fd socket to check
+ * @param laddr local address (out)
+ * @param raddr remote address (out)
+ * @return true on success false otherwise (errno contains more info)
+ */
+static memcached_return_t resolve_names(memcached_instance_st& server, char *laddr, size_t laddr_length, char *raddr, size_t raddr_length)
+{
+  char host[MEMCACHED_NI_MAXHOST];
+  char port[MEMCACHED_NI_MAXSERV];
+  struct sockaddr_storage saddr;
+  socklen_t salen= sizeof(saddr);
+
+  if (getsockname(server.fd, (struct sockaddr *)&saddr, &salen) < 0)
+  {
+    return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
+  }
+
+  if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host), port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
+  {
+    return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
+  }
+
+  (void)snprintf(laddr, laddr_length, "%s;%s", host, port);
+  salen= sizeof(saddr);
+
+  if (getpeername(server.fd, (struct sockaddr *)&saddr, &salen) < 0)
+  {
+    return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
+  }
+
+  if (getnameinfo((struct sockaddr *)&saddr, salen, host, sizeof(host),
+                   port, sizeof(port), NI_NUMERICHOST | NI_NUMERICSERV) < 0)
+  {
+    return memcached_set_error(server, MEMCACHED_HOST_LOOKUP_FAILURE, MEMCACHED_AT);
+  }
+
+  (void)snprintf(raddr, raddr_length, "%s;%s", host, port);
+
+  return MEMCACHED_SUCCESS;
+}
+
+extern "C" {
+
+static void sasl_shutdown_function()
+{
+  sasl_done();
+}
+
+static std::atomic<int> sasl_startup_state(SASL_OK);
+pthread_mutex_t sasl_startup_state_LOCK= PTHREAD_MUTEX_INITIALIZER;
+static pthread_once_t sasl_startup_once= PTHREAD_ONCE_INIT;
+static void sasl_startup_function(void)
+{
+  sasl_startup_state= sasl_client_init(NULL);
+
+  if (sasl_startup_state == SASL_OK)
+  {
+    (void)atexit(sasl_shutdown_function);
+  }
+}
+
+} // extern "C"
+
+memcached_return_t memcached_sasl_authenticate_connection(memcached_instance_st* server)
+{
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    return MEMCACHED_NOT_SUPPORTED;
+  }
+
+  if (server == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  /* SANITY CHECK: SASL can only be used with the binary protocol */
+  if (memcached_is_binary(server->root) == false)
+  {
+    return  memcached_set_error(*server, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
+                                memcached_literal_param("memcached_sasl_authenticate_connection() is not supported via the ASCII protocol"));
+  }
+
+  /* Try to get the supported mech from the server. Servers without SASL
+   * support will return UNKNOWN COMMAND, so we can just treat that
+   * as authenticated
+ */
+  protocol_binary_request_no_extras request= { };
+
+  initialize_binary_request(server, request.message.header);
+
+  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SASL_LIST_MECHS;
+
+  if (memcached_io_write(server, request.bytes, sizeof(request.bytes), true) != sizeof(request.bytes))
+  {
+    return MEMCACHED_WRITE_FAILURE;
+  }
+  assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
+
+  memcached_server_response_increment(server);
+
+  char mech[MEMCACHED_MAX_BUFFER];
+  memcached_return_t rc= memcached_response(server, mech, sizeof(mech), NULL);
+  if (memcached_failed(rc))
+  {
+    if (rc == MEMCACHED_PROTOCOL_ERROR)
+    {
+      /* If the server doesn't support SASL it will return PROTOCOL_ERROR.
+       * This error may also be returned for other errors, but let's assume
+       * that the server don't support SASL and treat it as success and
+       * let the client fail with the next operation if the error was
+       * caused by another problem....
+     */
+      rc= MEMCACHED_SUCCESS;
+    }
+
+    return rc;
+  }
+  assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
+
+  /* set ip addresses */
+  char laddr[MEMCACHED_NI_MAXHOST + MEMCACHED_NI_MAXSERV];
+  char raddr[MEMCACHED_NI_MAXHOST + MEMCACHED_NI_MAXSERV];
+
+  if (memcached_failed(rc= resolve_names(*server, laddr, sizeof(laddr), raddr, sizeof(raddr))))
+  {
+    return rc;
+  }
+
+  int pthread_error;
+  if ((pthread_error= pthread_once(&sasl_startup_once, sasl_startup_function)) != 0)
+  {
+    return memcached_set_errno(*server, pthread_error, MEMCACHED_AT);
+  }
+
+  (void)pthread_mutex_lock(&sasl_startup_state_LOCK);
+  if (sasl_startup_state != SASL_OK)
+  {
+    const char *sasl_error_msg= sasl_errstring(sasl_startup_state, NULL, NULL);
+    return memcached_set_error(*server, MEMCACHED_AUTH_PROBLEM, MEMCACHED_AT, 
+                               memcached_string_make_from_cstr(sasl_error_msg));
+  }
+  (void)pthread_mutex_unlock(&sasl_startup_state_LOCK);
+
+  sasl_conn_t *conn;
+  int ret;
+  if ((ret= sasl_client_new("memcached", server->_hostname, laddr, raddr, server->root->sasl.callbacks, 0, &conn) ) != SASL_OK)
+  {
+    const char *sasl_error_msg= sasl_errstring(ret, NULL, NULL);
+
+    sasl_dispose(&conn);
+
+    return memcached_set_error(*server, MEMCACHED_AUTH_PROBLEM, MEMCACHED_AT, 
+                               memcached_string_make_from_cstr(sasl_error_msg));
+  }
+
+  const char *data;
+  const char *chosenmech;
+  unsigned int len;
+  ret= sasl_client_start(conn, mech, NULL, &data, &len, &chosenmech);
+  if (ret != SASL_OK and ret != SASL_CONTINUE)
+  {
+    const char *sasl_error_msg= sasl_errstring(ret, NULL, NULL);
+
+    sasl_dispose(&conn);
+
+    return memcached_set_error(*server, MEMCACHED_AUTH_PROBLEM, MEMCACHED_AT, 
+                               memcached_string_make_from_cstr(sasl_error_msg));
+  }
+  uint16_t keylen= (uint16_t)strlen(chosenmech);
+  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SASL_AUTH;
+  request.message.header.request.keylen= htons(keylen);
+  request.message.header.request.bodylen= htonl(len + keylen);
+
+  do {
+    /* send the packet */
+
+    libmemcached_io_vector_st vector[]=
+    {
+      { request.bytes, sizeof(request.bytes) },
+      { chosenmech, keylen },
+      { data, len }
+    };
+
+    assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
+    if (memcached_io_writev(server, vector, 3, true) == false)
+    {
+      rc= MEMCACHED_WRITE_FAILURE;
+      break;
+    }
+    assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
+    memcached_server_response_increment(server);
+
+    /* read the response */
+    assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
+    rc= memcached_response(server, NULL, 0, NULL);
+    if (rc != MEMCACHED_AUTH_CONTINUE)
+    {
+      break;
+    }
+    assert_msg(server->fd != INVALID_SOCKET, "Programmer error, invalid socket");
+
+    ret= sasl_client_step(conn, memcached_result_value(&server->root->result),
+                          (unsigned int)memcached_result_length(&server->root->result),
+                          NULL, &data, &len);
+
+    if (ret != SASL_OK && ret != SASL_CONTINUE)
+    {
+      rc= MEMCACHED_AUTH_PROBLEM;
+      break;
+    }
+
+    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SASL_STEP;
+    request.message.header.request.bodylen= htonl(len + keylen);
+  } while (true);
+
+  /* Release resources */
+  sasl_dispose(&conn);
+
+  return memcached_set_error(*server, rc, MEMCACHED_AT);
+}
+
+static int get_username(void *context, int id, const char **result, unsigned int *len)
+{
+  if (!context || !result || (id != SASL_CB_USER && id != SASL_CB_AUTHNAME))
+  {
+    return SASL_BADPARAM;
+  }
+
+  *result= (char *)context;
+  if (len)
+  {
+    *len= (unsigned int)strlen(*result);
+  }
+
+  return SASL_OK;
+}
+
+static int get_password(sasl_conn_t *conn, void *context, int id,
+                        sasl_secret_t **psecret)
+{
+  if (!conn || ! psecret || id != SASL_CB_PASS)
+  {
+    return SASL_BADPARAM;
+  }
+
+  *psecret= (sasl_secret_t *)context;
+
+  return SASL_OK;
+}
+
+memcached_return_t memcached_set_sasl_auth_data(memcached_st *shell,
+                                                const char *username,
+                                                const char *password)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    return MEMCACHED_NOT_SUPPORTED;
+  }
+
+  if (ptr == NULL or username == NULL or password == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  memcached_return_t ret;
+  if (memcached_failed(ret= memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1)))
+  {
+    return memcached_set_error(*ptr, ret, MEMCACHED_AT, memcached_literal_param("Unable change to binary protocol which is required for SASL."));
+  }
+
+  memcached_destroy_sasl_auth_data(ptr);
+
+  sasl_callback_t *callbacks= libmemcached_xcalloc(ptr, 4, sasl_callback_t);
+  size_t password_length= strlen(password);
+  size_t username_length= strlen(username);
+  char *name= (char *)libmemcached_malloc(ptr, username_length +1);
+  sasl_secret_t *secret= (sasl_secret_t*)libmemcached_malloc(ptr, password_length +1 + sizeof(sasl_secret_t));
+
+  if (callbacks == NULL or name == NULL or secret == NULL)
+  {
+    libmemcached_free(ptr, callbacks);
+    libmemcached_free(ptr, name);
+    libmemcached_free(ptr, secret);
+    return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+  }
+
+  secret->len= password_length;
+  memcpy(secret->data, password, password_length);
+  secret->data[password_length]= 0;
+
+  callbacks[0].id= SASL_CB_USER;
+  callbacks[0].proc= CAST_SASL_CB(get_username);
+  callbacks[0].context= strncpy(name, username, username_length +1);
+  callbacks[1].id= SASL_CB_AUTHNAME;
+  callbacks[1].proc= CAST_SASL_CB(get_username);
+  callbacks[1].context= name;
+  callbacks[2].id= SASL_CB_PASS;
+  callbacks[2].proc= CAST_SASL_CB(get_password);
+  callbacks[2].context= secret;
+  callbacks[3].id= SASL_CB_LIST_END;
+
+  ptr->sasl.callbacks= callbacks;
+  ptr->sasl.is_allocated= true;
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *shell)
+{
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    return MEMCACHED_NOT_SUPPORTED;
+  }
+
+  Memcached* ptr= memcached2Memcached(shell);
+  if (ptr == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  if (ptr->sasl.callbacks == NULL)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  if (ptr->sasl.is_allocated)
+  {
+    libmemcached_free(ptr, ptr->sasl.callbacks[0].context);
+    libmemcached_free(ptr, ptr->sasl.callbacks[2].context);
+    libmemcached_free(ptr, (void*)ptr->sasl.callbacks);
+    ptr->sasl.is_allocated= false;
+  }
+
+  ptr->sasl.callbacks= NULL;
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_clone_sasl(memcached_st *clone, const  memcached_st *source)
+{
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    return MEMCACHED_NOT_SUPPORTED;
+  }
+
+  if (clone == NULL or source == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  if (source->sasl.callbacks == NULL)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  /* Hopefully we are using our own callback mechanisms.. */
+  if (source->sasl.callbacks[0].id == SASL_CB_USER &&
+      source->sasl.callbacks[0].proc ==  CAST_SASL_CB(get_username) &&
+      source->sasl.callbacks[1].id == SASL_CB_AUTHNAME &&
+      source->sasl.callbacks[1].proc ==  CAST_SASL_CB(get_username) &&
+      source->sasl.callbacks[2].id == SASL_CB_PASS &&
+      source->sasl.callbacks[2].proc ==  CAST_SASL_CB(get_password) &&
+      source->sasl.callbacks[3].id == SASL_CB_LIST_END)
+  {
+    sasl_secret_t *secret= (sasl_secret_t *)source->sasl.callbacks[2].context;
+    return memcached_set_sasl_auth_data(clone,
+                                        (const char*)source->sasl.callbacks[0].context,
+                                        (const char*)secret->data);
+  }
+
+  /*
+   * But we're not. It may work if we know what the user tries to pass
+   * into the list, but if we don't know the ID we don't know how to handle
+   * the context...
+ */
+  ptrdiff_t total= 0;
+
+  while (source->sasl.callbacks[total].id != SASL_CB_LIST_END)
+  {
+    switch (source->sasl.callbacks[total].id)
+    {
+    case SASL_CB_USER:
+    case SASL_CB_AUTHNAME:
+    case SASL_CB_PASS:
+      break;
+    default:
+      /* I don't know how to deal with this... */
+      return MEMCACHED_NOT_SUPPORTED;
+    }
+
+    ++total;
+  }
+
+  sasl_callback_t *callbacks= libmemcached_xcalloc(clone, total +1, sasl_callback_t);
+  if (callbacks == NULL)
+  {
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+  }
+  memcpy(callbacks, source->sasl.callbacks, (total + 1) * sizeof(sasl_callback_t));
+
+  /* Now update the context... */
+  for (ptrdiff_t x= 0; x < total; ++x)
+  {
+    if (callbacks[x].id == SASL_CB_USER || callbacks[x].id == SASL_CB_AUTHNAME)
+    {
+      callbacks[x].context= (sasl_callback_t*)libmemcached_malloc(clone, strlen((const char*)source->sasl.callbacks[x].context));
+
+      if (callbacks[x].context == NULL)
+      {
+        /* Failed to allocate memory, clean up previously allocated memory */
+        for (ptrdiff_t y= 0; y < x; ++y)
+        {
+          libmemcached_free(clone, clone->sasl.callbacks[y].context);
+        }
+
+        libmemcached_free(clone, callbacks);
+        return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+      }
+      strncpy((char*)callbacks[x].context, (const char*)source->sasl.callbacks[x].context, sizeof(callbacks[x].context));
+    }
+    else
+    {
+      sasl_secret_t *src= (sasl_secret_t *)source->sasl.callbacks[x].context;
+      sasl_secret_t *n= (sasl_secret_t*)libmemcached_malloc(clone, src->len + 1 + sizeof(*n));
+      if (n == NULL)
+      {
+        /* Failed to allocate memory, clean up previously allocated memory */
+        for (ptrdiff_t y= 0; y < x; ++y)
+        {
+          libmemcached_free(clone, clone->sasl.callbacks[y].context);
+        }
+
+        libmemcached_free(clone, callbacks);
+        return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+      }
+      memcpy(n, src, src->len + 1 + sizeof(*n));
+      callbacks[x].context= n;
+    }
+  }
+
+  clone->sasl.callbacks= callbacks;
+  clone->sasl.is_allocated= true;
+
+  return MEMCACHED_SUCCESS;
+}
+
+#else
+
+void memcached_set_sasl_callbacks(memcached_st *, const sasl_callback_t *)
+{
+}
+
+sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *)
+{
+  return NULL;
+}
+
+memcached_return_t memcached_set_sasl_auth_data(memcached_st *, const char *, const char *)
+{
+  return MEMCACHED_NOT_SUPPORTED;
+}
+
+memcached_return_t memcached_clone_sasl(memcached_st *, const  memcached_st *)
+{
+  return MEMCACHED_NOT_SUPPORTED;
+}
+
+#endif
diff --git a/src/libmemcached/sasl.hpp b/src/libmemcached/sasl.hpp
new file mode 100644 (file)
index 0000000..bda6b22
--- /dev/null
@@ -0,0 +1,42 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+memcached_return_t memcached_clone_sasl(memcached_st *clone, const  memcached_st *source);
+
+memcached_return_t memcached_sasl_authenticate_connection(memcached_instance_st* server);
diff --git a/src/libmemcached/server.cc b/src/libmemcached/server.cc
new file mode 100644 (file)
index 0000000..e2837c7
--- /dev/null
@@ -0,0 +1,295 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+  This is a partial implementation for fetching/creating memcached_server_st objects.
+*/
+#include <libmemcached/common.h>
+
+static inline void _server_init(memcached_server_st *self, Memcached *root,
+                                const memcached_string_t& hostname,
+                                in_port_t port,
+                                uint32_t weight, memcached_connection_t type)
+{
+  self->options.is_shutting_down= false;
+  self->options.is_dead= false;
+  self->number_of_hosts= 0;
+  self->cursor_active= 0;
+  self->port= port;
+  self->io_bytes_sent= 0;
+  self->request_id= 0;
+  self->server_failure_counter= 0;
+  self->server_failure_counter_query_id= 0;
+  self->server_timeout_counter= 0;
+  self->server_timeout_counter_query_id= 0;
+  self->weight= weight ? weight : 1; // 1 is the default weight value
+  self->io_wait_count.read= 0;
+  self->io_wait_count.write= 0;
+  self->io_wait_count.timeouts= 0;
+  self->io_wait_count._bytes_read= 0;
+  self->major_version= UINT8_MAX;
+  self->micro_version= UINT8_MAX;
+  self->minor_version= UINT8_MAX;
+  self->type= type;
+  self->error_messages= NULL;
+
+  self->state= MEMCACHED_SERVER_STATE_NEW;
+  self->next_retry= 0;
+
+  self->root= root;
+  if (root)
+  {
+    self->version= ++root->server_info.version;
+  }
+  else
+  {
+    self->version= UINT_MAX;
+  }
+  self->limit_maxbytes= 0;
+  memcpy(self->hostname, hostname.c_str, hostname.size);
+  self->hostname[hostname.size]= 0;
+}
+
+static memcached_server_st *_server_create(memcached_server_st *self, const Memcached *memc)
+{
+  if (self == NULL)
+  {
+   self= libmemcached_xmalloc(memc, struct memcached_server_st);
+
+    if (self == NULL)
+    {
+      return NULL; /*  MEMCACHED_MEMORY_ALLOCATION_FAILURE */
+    }
+
+    self->options.is_allocated= true;
+  }
+  else
+  {
+    self->options.is_allocated= false;
+  }
+
+  self->options.is_initialized= true;
+
+  return self;
+}
+
+memcached_server_st *__server_create_with(Memcached *memc,
+                                          memcached_server_st* allocated_instance,
+                                          const memcached_string_t& hostname,
+                                          const in_port_t port,
+                                          uint32_t weight, 
+                                          const memcached_connection_t type)
+{
+  if (memcached_is_valid_servername(hostname) == false)
+  {
+    memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid hostname provided"));
+    return NULL;
+  }
+
+  allocated_instance= _server_create(allocated_instance, memc);
+
+  if (allocated_instance == NULL)
+  {
+    return NULL;
+  }
+
+  _server_init(allocated_instance, const_cast<Memcached *>(memc), hostname, port, weight, type);
+
+  return allocated_instance;
+}
+
+void __server_free(memcached_server_st *self)
+{
+  memcached_error_free(*self);
+
+  if (memcached_is_allocated(self))
+  {
+    libmemcached_free(self->root, self);
+  }
+  else
+  {
+    self->options.is_initialized= false;
+  }
+}
+
+void memcached_server_free(memcached_server_st *self)
+{
+  if (self == NULL)
+  {
+    return;
+  }
+
+  if (memcached_server_list_count(self))
+  {
+    memcached_server_list_free(self);
+    return;
+  }
+
+  __server_free(self);
+}
+
+void memcached_server_error_reset(memcached_server_st *self)
+{
+  WATCHPOINT_ASSERT(self);
+  if (self == NULL)
+  {
+    return;
+  }
+
+  memcached_error_free(*self);
+}
+
+uint32_t memcached_servers_set_count(memcached_server_st *servers, uint32_t count)
+{
+  WATCHPOINT_ASSERT(servers);
+  if (servers == NULL)
+  {
+    return 0;
+  }
+
+  return servers->number_of_hosts= count;
+}
+
+uint32_t memcached_server_count(const memcached_st *self)
+{
+  WATCHPOINT_ASSERT(self);
+  if (self == NULL)
+    return 0;
+
+  return self->number_of_hosts;
+}
+
+const char *memcached_server_name(const memcached_instance_st * self)
+{
+  WATCHPOINT_ASSERT(self);
+  if (self)
+  {
+    return self->_hostname;
+  }
+
+  return NULL;
+}
+
+in_port_t memcached_server_port(const memcached_instance_st * self)
+{
+  WATCHPOINT_ASSERT(self);
+  if (self == NULL)
+  {
+    return 0;
+  }
+
+  return self->port();
+}
+
+in_port_t memcached_server_srcport(const memcached_instance_st * self)
+{
+  WATCHPOINT_ASSERT(self);
+  if (self == NULL || self->fd == INVALID_SOCKET || (self->type != MEMCACHED_CONNECTION_TCP && self->type != MEMCACHED_CONNECTION_UDP))
+  {
+    return 0;
+  }
+
+  struct sockaddr_in sin;
+  socklen_t addrlen= sizeof(sin);
+  if (getsockname(self->fd, (struct sockaddr*)&sin, &addrlen) != -1)
+  {
+    return ntohs(sin.sin_port);
+  }
+
+  return -1;
+}
+
+uint32_t memcached_server_response_count(const memcached_instance_st * self)
+{
+  WATCHPOINT_ASSERT(self);
+  if (self == NULL)
+  {
+    return 0;
+  }
+
+  return self->cursor_active_;
+}
+
+const char *memcached_server_type(const memcached_instance_st * ptr)
+{
+  if (ptr)
+  {
+    switch (ptr->type)
+    {
+    case MEMCACHED_CONNECTION_TCP:
+      return "TCP";
+
+    case MEMCACHED_CONNECTION_UDP:
+      return "UDP";
+
+    case MEMCACHED_CONNECTION_UNIX_SOCKET:
+      return "SOCKET";
+    }
+  }
+
+  return "UNKNOWN";
+}
+
+uint8_t memcached_server_major_version(const memcached_instance_st * instance)
+{
+  if (instance)
+  {
+    return instance->major_version;
+  }
+
+  return UINT8_MAX;
+}
+
+uint8_t memcached_server_minor_version(const memcached_instance_st * instance)
+{
+  if (instance)
+  {
+    return instance->minor_version;
+  }
+
+  return UINT8_MAX;
+}
+
+uint8_t memcached_server_micro_version(const memcached_instance_st * instance)
+{
+  if (instance)
+  {
+    return instance->micro_version;
+  }
+
+  return UINT8_MAX;
+}
diff --git a/src/libmemcached/server.hpp b/src/libmemcached/server.hpp
new file mode 100644 (file)
index 0000000..582356d
--- /dev/null
@@ -0,0 +1,106 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <cassert>
+
+memcached_server_st *__server_create_with(memcached_st *memc,
+                                          memcached_server_st* self,
+                                          const memcached_string_t& hostname,
+                                          const in_port_t port,
+                                          uint32_t weight, 
+                                          const memcached_connection_t type);
+
+memcached_return_t memcached_server_add_parsed(memcached_st *ptr,
+                                               const char *hostname,
+                                               size_t hostname_length,
+                                               in_port_t port,
+                                               uint32_t weight);
+
+void __server_free(memcached_server_st *);
+
+static inline bool memcached_is_valid_servername(const memcached_string_t& arg)
+{
+  return (arg.c_str != NULL or arg.size == 0) and arg.size < MEMCACHED_NI_MAXHOST;
+}
+
+static inline bool memcached_is_valid_filename(const memcached_string_t& arg)
+{
+  return arg.c_str != NULL and arg.size > 0 and arg.size < MEMCACHED_NI_MAXHOST;
+}
+
+void memcached_instance_free(memcached_instance_st *);
+
+void set_last_disconnected_host(memcached_instance_st* self);
+
+static inline void memcached_mark_server_for_timeout(memcached_instance_st* server)
+{
+  if (server->state != MEMCACHED_SERVER_STATE_IN_TIMEOUT)
+  {
+    if (server->server_timeout_counter_query_id != server->root->query_id)
+    {
+      server->server_timeout_counter++;
+      server->server_timeout_counter_query_id= server->root->query_id;
+    }
+
+    if (server->server_timeout_counter >= server->root->server_timeout_limit)
+    {
+      struct timeval next_time;
+      if (gettimeofday(&next_time, NULL) == 0)
+      {
+        server->next_retry= next_time.tv_sec +server->root->retry_timeout;
+      }
+      else
+      {
+        server->next_retry= 1; // Setting the value to 1 causes the timeout to occur immediately
+      }
+
+      server->state= MEMCACHED_SERVER_STATE_IN_TIMEOUT;
+      if (server->server_failure_counter_query_id != server->root->query_id)
+      {
+        server->server_failure_counter++;
+        server->server_failure_counter_query_id= server->root->query_id;
+      }
+      set_last_disconnected_host(server);
+    }
+  }
+}
diff --git a/src/libmemcached/server_instance.h b/src/libmemcached/server_instance.h
new file mode 100644 (file)
index 0000000..187f274
--- /dev/null
@@ -0,0 +1,60 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+typedef struct memcached_instance_st* memcached_server_write_instance_st;
+#else
+typedef void* memcached_server_write_instance_st;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef memcached_return_t (*memcached_server_execute_fn)(memcached_st *ptr, memcached_server_write_instance_st server, void *context);
+
+memcached_return_t memcached_server_execute(memcached_st *ptr,
+                                            memcached_server_execute_fn callback,
+                                            void *context);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+
diff --git a/src/libmemcached/server_list.cc b/src/libmemcached/server_list.cc
new file mode 100644 (file)
index 0000000..b5d5b72
--- /dev/null
@@ -0,0 +1,163 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+
+#include <libmemcached/common.h>
+
+memcached_server_list_st 
+memcached_server_list_append_with_weight(memcached_server_list_st ptr,
+                                         const char *hostname, in_port_t port,
+                                         uint32_t weight,
+                                         memcached_return_t *error)
+{
+  memcached_return_t unused;
+  if (error == NULL)
+  {
+    error= &unused;
+  }
+
+  if (hostname == NULL)
+  {
+    hostname= "localhost";
+  }
+
+  if (hostname[0] == '/')
+  {
+    port = 0;
+  }
+  else if (port == 0)
+  {
+    port= MEMCACHED_DEFAULT_PORT;
+  }
+
+
+  /* Increment count for hosts */
+  uint32_t count= 1;
+  if (ptr != NULL)
+  {
+    count+= memcached_server_list_count(ptr);
+  }
+
+  memcached_server_list_st new_host_list= (memcached_server_st*)realloc(ptr, sizeof(memcached_server_st) * count);
+  if (new_host_list == NULL)
+  {
+#if 0
+    *error= memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+#endif
+    return NULL;
+  }
+
+  memcached_string_t _hostname= { memcached_string_make_from_cstr(hostname) };
+  /* @todo Check return type */
+  if (__server_create_with(NULL, &new_host_list[count-1], _hostname, port, weight, port ? MEMCACHED_CONNECTION_TCP : MEMCACHED_CONNECTION_UNIX_SOCKET) == NULL)
+  {
+#if 0
+    *error= memcached_set_errno(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+#endif
+    free(new_host_list);
+    return NULL;
+  }
+
+#if 0
+  // Handset allocated since 
+  new_host_list->options.is_allocated= true;
+#endif
+
+  /* Backwards compatibility hack */
+  memcached_servers_set_count(new_host_list, count);
+
+  *error= MEMCACHED_SUCCESS;
+  return new_host_list;
+}
+
+memcached_server_list_st
+memcached_server_list_append(memcached_server_list_st ptr,
+                             const char *hostname, in_port_t port,
+                             memcached_return_t *error)
+{
+  return memcached_server_list_append_with_weight(ptr, hostname, port, 0, error);
+}
+
+uint32_t memcached_server_list_count(const memcached_server_list_st self)
+{
+  return (self == NULL)
+    ? 0
+    : self->number_of_hosts;
+}
+
+uint32_t memcached_instance_list_count(const memcached_st* self)
+{
+  return (self == NULL)
+    ? 0
+    : self->number_of_hosts;
+}
+
+void memcached_instance_set(memcached_st* memc, memcached_instance_st* list, const uint32_t host_list_size)
+{
+  assert(memc);
+  memc->servers= list;
+  memc->number_of_hosts= host_list_size;
+}
+
+void memcached_server_list_free(memcached_server_list_st self)
+{
+  if (self)
+  {
+    for (uint32_t x= 0; x < memcached_server_list_count(self); x++)
+    {
+      assert_msg(not memcached_is_allocated(&self[x]), "You have called memcached_server_list_free(), but you did not pass it a valid memcached_server_list_st");
+      __server_free(&self[x]);
+    }
+
+    libmemcached_free(self->root, self);
+  }
+}
+
+void memcached_instance_list_free(memcached_instance_st* self, uint32_t instance_count)
+{
+  if (self)
+  {
+    for (uint32_t x= 0; x < instance_count; x++)
+    {
+      assert_msg(memcached_is_allocated(&self[x]) == false, "You have called memcached_server_list_free(), but you did not pass it a valid memcached_server_list_st");
+      __instance_free(&self[x]);
+    }
+
+    libmemcached_free(self->root, self);
+  }
+}
diff --git a/src/libmemcached/server_list.hpp b/src/libmemcached/server_list.hpp
new file mode 100644 (file)
index 0000000..0280332
--- /dev/null
@@ -0,0 +1,47 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+memcached_instance_st* memcached_instance_list(const memcached_st *);
+
+uint32_t memcached_instance_list_count(const memcached_st*);
+
+uint32_t memcached_servers_set_count(memcached_server_list_st servers, uint32_t count);
+
+void memcached_instance_list_free(memcached_instance_st* self, uint32_t count);
+
+void memcached_instance_set(memcached_st*, memcached_instance_st*, const uint32_t host_list_size);
diff --git a/src/libmemcached/socket.hpp b/src/libmemcached/socket.hpp
new file mode 100644 (file)
index 0000000..a2ee941
--- /dev/null
@@ -0,0 +1,80 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+/* To hide the platform differences between MS Windows and Unix, I am
+ * going to use the Microsoft way and #define the Microsoft-specific
+ * functions to the unix way. Microsoft use a separate subsystem for sockets,
+ * but Unix normally just use a filedescriptor on the same functions. It is
+ * a lot easier to map back to the unix way with macros than going the other
+ * way without side effect ;-)
+ */
+#if defined(WIN32) || defined(__MINGW32__)
+# include "win32/wrappers.h"
+# define get_socket_errno() WSAGetLastError()
+#else
+# include <unistd.h>
+# define INVALID_SOCKET -1
+# define SOCKET_ERROR -1
+# define closesocket(a) close(a)
+# define get_socket_errno() errno
+#endif
+
+#ifdef __cplusplus
+static inline void memcached_close_socket(memcached_socket_t& socket_fd)
+{
+  closesocket(socket_fd);
+  socket_fd= INVALID_SOCKET;
+}
+#endif
+
+#ifndef HAVE_MSG_NOSIGNAL
+# define MSG_NOSIGNAL 0
+#endif
+
+#ifndef HAVE_MSG_DONTWAIT
+# define MSG_DONTWAIT 0
+#endif
+
+#ifndef HAVE_MSG_MORE
+# define MSG_MORE 0
+#endif
+
+
diff --git a/src/libmemcached/stats.cc b/src/libmemcached/stats.cc
new file mode 100644 (file)
index 0000000..9e6083e
--- /dev/null
@@ -0,0 +1,846 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+static const char *memcached_stat_keys[] = {
+  "pid",
+  "uptime",
+  "time",
+  "version",
+  "pointer_size",
+  "rusage_user",
+  "rusage_system",
+  "curr_items",
+  "total_items",
+  "bytes",
+  "curr_connections",
+  "total_connections",
+  "connection_structures",
+  "cmd_get",
+  "cmd_set",
+  "get_hits",
+  "get_misses",
+  "evictions",
+  "bytes_read",
+  "bytes_written",
+  "limit_maxbytes",
+  "threads",
+  NULL
+};
+
+struct local_context
+{
+  memcached_stat_fn func;
+  void *context;
+  const char *args;
+  const size_t args_length;
+
+  local_context(memcached_stat_fn func_arg,
+                void *context_arg,
+                const char *args_arg,
+                const size_t args_length_arg) :
+    func(func_arg),
+    context(context_arg),
+    args(args_arg),
+    args_length(args_length_arg)
+  { }
+};
+
+
+static memcached_return_t set_data(memcached_stat_st *memc_stat, const char *key, const char *value)
+{
+
+  if (strlen(key) < 1)
+  {
+    WATCHPOINT_STRING(key);
+    return MEMCACHED_UNKNOWN_STAT_KEY;
+  }
+  else if (strcmp("pid", key) == 0)
+  {
+    errno= 0;
+    int64_t temp= strtoll(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+
+    if (temp <= INT32_MAX and ( sizeof(pid_t) == sizeof(int32_t) ))
+    {
+      memc_stat->pid= pid_t(temp);
+    }
+    else if (temp > -1)
+    {
+      memc_stat->pid= pid_t(temp);
+    }
+    else
+    {
+      // If we got a value less then -1 then something went wrong in the
+      // protocol
+    }
+  }
+  else if (not strcmp("uptime", key))
+  {
+    errno= 0;
+    memc_stat->uptime= strtoul(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("time", key))
+  {
+    errno= 0;
+    memc_stat->time= strtoul(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("version", key))
+  {
+    memcpy(memc_stat->version, value, strlen(value));
+    memc_stat->version[strlen(value)]= 0;
+  }
+  else if (not strcmp("pointer_size", key))
+  {
+    errno= 0;
+    memc_stat->pointer_size= strtoul(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("rusage_user", key))
+  {
+    char *walk_ptr;
+    for (walk_ptr= (char*)value; (!ispunct(*walk_ptr)); walk_ptr++) {};
+    *walk_ptr= 0;
+    walk_ptr++;
+
+    errno= 0;
+    memc_stat->rusage_user_seconds= strtoul(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+
+    errno= 0;
+    memc_stat->rusage_user_microseconds= strtoul(walk_ptr, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("rusage_system", key))
+  {
+    char *walk_ptr;
+    for (walk_ptr= (char*)value; (!ispunct(*walk_ptr)); walk_ptr++) {};
+    *walk_ptr= 0;
+    walk_ptr++;
+
+    errno= 0;
+    memc_stat->rusage_system_seconds= strtoul(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+
+    errno= 0;
+    memc_stat->rusage_system_microseconds= strtoul(walk_ptr, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("curr_items", key))
+  {
+    errno= 0;
+    memc_stat->curr_items= strtoul(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("total_items", key))
+  {
+    errno= 0;
+    memc_stat->total_items= strtoul(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("bytes_read", key))
+  {
+    errno= 0;
+    memc_stat->bytes_read= strtoull(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("bytes_written", key))
+  {
+    errno= 0;
+    memc_stat->bytes_written= strtoull(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("bytes", key))
+  {
+    errno= 0;
+    memc_stat->bytes= strtoull(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("curr_connections", key))
+  {
+    errno= 0;
+    memc_stat->curr_connections= strtoull(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("total_connections", key))
+  {
+    errno= 0;
+    memc_stat->total_connections= strtoull(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("connection_structures", key))
+  {
+    errno= 0;
+    memc_stat->connection_structures= strtoul(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("cmd_get", key))
+  {
+    errno= 0;
+    memc_stat->cmd_get= strtoull(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("cmd_set", key))
+  {
+    errno= 0;
+    memc_stat->cmd_set= strtoull(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("get_hits", key))
+  {
+    errno= 0;
+    memc_stat->get_hits= strtoull(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("get_misses", key))
+  {
+    errno= 0;
+    memc_stat->get_misses= strtoull(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("evictions", key))
+  {
+    errno= 0;
+    memc_stat->evictions= strtoull(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("limit_maxbytes", key))
+  {
+    errno= 0;
+    memc_stat->limit_maxbytes= strtoull(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if (not strcmp("threads", key))
+  {
+    errno= 0;
+    memc_stat->threads= strtoul(value, (char **)NULL, 10);
+    if (errno != 0)
+    {
+      return MEMCACHED_FAILURE;
+    }
+  }
+  else if ((strcmp("delete_misses", key) == 0 or /* New stats in the 1.3 beta */
+            strcmp("delete_hits", key) == 0 or /* Just swallow them for now.. */
+            strcmp("incr_misses", key) == 0 or
+            strcmp("incr_hits", key) == 0 or
+            strcmp("decr_misses", key) == 0 or
+            strcmp("decr_hits", key) == 0 or
+            strcmp("cas_misses", key) == 0 or
+            strcmp("cas_hits", key) == 0 or
+            strcmp("cas_badval", key) == 0 or
+            strcmp("cmd_flush", key) == 0 or
+            strcmp("accepting_conns", key) == 0 or
+            strcmp("listen_disabled_num", key) == 0 or
+            strcmp("conn_yields", key) == 0 or
+            strcmp("auth_cmds", key) == 0 or
+            strcmp("auth_errors", key) == 0 or
+            strcmp("reclaimed", key) == 0) == 0)
+  {
+    WATCHPOINT_STRING(key);
+    /* return MEMCACHED_UNKNOWN_STAT_KEY; */
+    return MEMCACHED_SUCCESS;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+char *memcached_stat_get_value(const memcached_st* shell, memcached_stat_st *memc_stat,
+                               const char *key, memcached_return_t *error)
+{
+  memcached_return_t not_used;
+  if (error == NULL)
+  {
+    error= &not_used;
+  }
+
+  if (memc_stat == NULL)
+  {
+    *error= MEMCACHED_INVALID_ARGUMENTS;
+    return NULL;
+  }
+
+  char buffer[SMALL_STRING_LEN];
+  int length;
+
+  *error= MEMCACHED_SUCCESS;
+
+  if (memcmp("pid", key, sizeof("pid") -1) == 0)
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%lld", (signed long long)memc_stat->pid);
+  }
+  else if (not memcmp("uptime", key, sizeof("uptime") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->uptime);
+  }
+  else if (not memcmp("time", key, sizeof("time") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->time);
+  }
+  else if (not memcmp("version", key, sizeof("version") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%s", memc_stat->version);
+  }
+  else if (not memcmp("pointer_size", key, sizeof("pointer_size") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->pointer_size);
+  }
+  else if (not memcmp("rusage_user", key, sizeof("rusage_user") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%lu.%lu", memc_stat->rusage_user_seconds, memc_stat->rusage_user_microseconds);
+  }
+  else if (not memcmp("rusage_system", key, sizeof("rusage_system") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%lu.%lu", memc_stat->rusage_system_seconds, memc_stat->rusage_system_microseconds);
+  }
+  else if (not memcmp("curr_items", key, sizeof("curr_items") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->curr_items);
+  }
+  else if (not memcmp("total_items", key, sizeof("total_items") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->total_items);
+  }
+  else if (not memcmp("curr_connections", key, sizeof("curr_connections") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->curr_connections);
+  }
+  else if (not memcmp("total_connections", key, sizeof("total_connections") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->total_connections);
+  }
+  else if (not memcmp("connection_structures", key, sizeof("connection_structures") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->connection_structures);
+  }
+  else if (not memcmp("cmd_get", key, sizeof("cmd_get") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->cmd_get);
+  }
+  else if (not memcmp("cmd_set", key, sizeof("cmd_set") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->cmd_set);
+  }
+  else if (not memcmp("get_hits", key, sizeof("get_hits") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->get_hits);
+  }
+  else if (not memcmp("get_misses", key, sizeof("get_misses") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->get_misses);
+  }
+  else if (not memcmp("evictions", key, sizeof("evictions") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->evictions);
+  }
+  else if (not memcmp("bytes_read", key, sizeof("bytes_read") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes_read);
+  }
+  else if (not memcmp("bytes_written", key, sizeof("bytes_written") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes_written);
+  }
+  else if (not memcmp("bytes", key, sizeof("bytes") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes);
+  }
+  else if (not memcmp("limit_maxbytes", key, sizeof("limit_maxbytes") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->limit_maxbytes);
+  }
+  else if (not memcmp("threads", key, sizeof("threads") -1))
+  {
+    length= snprintf(buffer, SMALL_STRING_LEN,"%lu", memc_stat->threads);
+  }
+  else
+  {
+    Memcached* memc= (Memcached*)memcached2Memcached(shell);
+    *error= memcached_set_error(*memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT, memcached_literal_param("Invalid key provided"));
+    return NULL;
+  }
+
+  if (length >= SMALL_STRING_LEN || length < 0)
+  {
+    Memcached* memc= (Memcached*)memcached2Memcached(shell);
+    *error= memcached_set_error(*memc, MEMCACHED_FAILURE, MEMCACHED_AT, memcached_literal_param("Internal failure occured with buffer, please report this bug."));
+    return NULL;
+  }
+
+  // User is responsible for free() memory, so use malloc()
+  char *ret= static_cast<char *>(malloc(size_t(length +1)));
+  memcpy(ret, buffer, (size_t) length);
+  ret[length]= '\0';
+
+  return ret;
+}
+
+static memcached_return_t binary_stats_fetch(memcached_stat_st *memc_stat,
+                                             const char *args,
+                                             const size_t args_length,
+                                             memcached_instance_st* instance,
+                                             struct local_context *check)
+{
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+  protocol_binary_request_stats request= {}; // = {.bytes= {0}};
+  memcached_return_t rc;
+
+  initialize_binary_request(instance, request.message.header);
+
+  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_STAT;
+  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+
+  if (args_length)
+  {
+    request.message.header.request.keylen= htons(uint16_t(args_length));
+    request.message.header.request.bodylen= htonl(uint32_t( args_length));
+
+    libmemcached_io_vector_st vector[]=
+    {
+      { request.bytes, sizeof(request.bytes) },
+      { args, args_length }
+    };
+
+    if (memcached_failed(rc = memcached_vdo(instance, vector, 2, true)))
+    {
+      return rc;
+    }
+  }
+  else
+  {
+    libmemcached_io_vector_st vector[]=
+    {
+      { request.bytes, sizeof(request.bytes) }
+    };
+
+    if (memcached_failed(rc = memcached_vdo(instance, vector, 1, true)))
+    {
+      return rc;
+    }
+  }
+
+  memcached_server_response_decrement(instance);
+  while (1)
+  {
+    rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
+
+    if (rc == MEMCACHED_END)
+    {
+      break;
+    }
+
+    if (rc != MEMCACHED_SUCCESS)
+    {
+      return rc;
+    }
+
+    if (check && check->func)
+    {
+      size_t key_length= strlen(buffer);
+
+      check->func(instance,
+                  buffer, key_length,
+                  buffer+key_length+1, strlen(buffer+key_length+1),
+                  check->context);
+    }
+
+    if (memc_stat)
+    {
+      if ((set_data(memc_stat, buffer, buffer + strlen(buffer) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY)
+      {
+        WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
+        WATCHPOINT_ASSERT(0);
+      }
+    }
+  }
+
+  /* 
+   * memcached_response will decrement the counter, so I need to reset it..
+   * todo: look at this and try to find a better solution.  
+   * */
+  instance->cursor_active_= 0;
+
+  return MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t ascii_stats_fetch(memcached_stat_st *memc_stat,
+                                            const char *args,
+                                            const size_t args_length,
+                                            memcached_instance_st* instance,
+                                            struct local_context *check)
+{
+  libmemcached_io_vector_st vector[]=
+  {
+    { memcached_literal_param("stats ") },
+    { args, args_length },
+    { memcached_literal_param("\r\n") }
+  };
+
+  memcached_return_t rc= memcached_vdo(instance, vector, 3, true);
+  if (memcached_success(rc))
+  {
+    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+    while ((rc= memcached_response(instance, buffer, sizeof(buffer), NULL)) == MEMCACHED_STAT)
+    {
+      char *string_ptr= buffer;
+      string_ptr+= 5; /* Move past STAT */
+
+      char *end_ptr;
+      for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++) {};
+      char *key= string_ptr;
+      key[size_t(end_ptr-string_ptr)]= 0;
+
+      string_ptr= end_ptr + 1;
+      for (end_ptr= string_ptr; !(isspace(*end_ptr)); end_ptr++) {};
+      char *value= string_ptr;
+      value[(size_t)(end_ptr -string_ptr)]= 0;
+#if 0
+      bool check_bool= bool(check);
+      bool check_func_bool= bool(check) ? bool(check->func) : false;
+      fprintf(stderr, "%s:%d %s %s %d:%d\n", __FILE__, __LINE__, key, value, check_bool, check_func_bool);
+#endif
+
+      if (check and check->func)
+      {
+        check->func(instance,
+                    key, strlen(key),
+                    value, strlen(value),
+                    check->context);
+      }
+
+      if (memc_stat)
+      {
+        if((set_data(memc_stat, key, value)) == MEMCACHED_UNKNOWN_STAT_KEY)
+        {
+          WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
+          WATCHPOINT_ASSERT(0);
+        }
+      }
+    }
+  }
+
+  if (rc == MEMCACHED_ERROR)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  if (rc == MEMCACHED_END)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  return rc;
+}
+
+memcached_stat_st *memcached_stat(memcached_st *shell, char *args, memcached_return_t *error)
+{
+  Memcached* self= memcached2Memcached(shell);
+  memcached_return_t unused;
+  if (error == NULL)
+  {
+    error= &unused;
+  }
+
+  if (memcached_failed(*error= initialize_query(self, true)))
+  {
+    return NULL;
+  }
+
+  if (memcached_is_udp(self))
+  {
+    *error= memcached_set_error(*self, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
+    return NULL;
+  }
+
+  memcached_return_t rc;
+  size_t args_length= 0;
+  if (args)
+  {
+    args_length= strlen(args);
+    if (memcached_failed(rc= memcached_key_test(*self, (const char **)&args, &args_length, 1)))
+    {
+      *error= memcached_set_error(*self, rc, MEMCACHED_AT);
+      return NULL;
+    }
+  }
+
+  WATCHPOINT_ASSERT(error);
+
+  memcached_stat_st *stats= libmemcached_xcalloc(self, memcached_server_count(self), memcached_stat_st);
+  if (stats == NULL)
+  {
+    *error= memcached_set_error(*self, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+    return NULL;
+  }
+
+  WATCHPOINT_ASSERT(rc == MEMCACHED_SUCCESS);
+  rc= MEMCACHED_SUCCESS;
+  for (uint32_t x= 0; x < memcached_server_count(self); x++)
+  {
+    memcached_stat_st* stat_instance= stats +x;
+
+    stat_instance->pid= -1;
+    stat_instance->root= self;
+
+    memcached_instance_st* instance= memcached_instance_fetch(self, x);
+
+    memcached_return_t temp_return;
+    if (memcached_is_binary(self))
+    {
+      temp_return= binary_stats_fetch(stat_instance, args, args_length, instance, NULL);
+    }
+    else
+    {
+      temp_return= ascii_stats_fetch(stat_instance, args, args_length, instance, NULL);
+    }
+
+    // Special case where "args" is invalid
+    if (temp_return == MEMCACHED_INVALID_ARGUMENTS)
+    {
+      rc= MEMCACHED_INVALID_ARGUMENTS;
+      break;
+    }
+
+    if (memcached_failed(temp_return))
+    {
+      rc= MEMCACHED_SOME_ERRORS;
+    }
+  }
+
+  *error= rc;
+
+  return stats;
+}
+
+memcached_return_t memcached_stat_servername(memcached_stat_st *memc_stat, char *args,
+                                             const char *hostname, in_port_t port)
+{
+  memcached_st memc;
+
+  memcached_stat_st unused_memc_stat;
+  if (memc_stat == NULL)
+  {
+    memc_stat= &unused_memc_stat;
+  }
+
+  memset(memc_stat, 0, sizeof(memcached_stat_st));
+
+  memcached_st *memc_ptr= memcached_create(&memc);
+  if (memc_ptr == NULL)
+  {
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+  }
+
+  memcached_return_t rc;
+  if (memcached_failed(rc= memcached_server_add(&memc, hostname, port)))
+  {
+    memcached_free(&memc);
+    return rc;
+  }
+
+  if (memcached_success(rc= initialize_query(memc_ptr, true)))
+  {
+    size_t args_length= 0;
+    if (args)
+    {
+      args_length= strlen(args);
+      rc= memcached_key_test(*memc_ptr, (const char **)&args, &args_length, 1);
+    }
+
+    if (memcached_success(rc))
+    {
+      memcached_instance_st* instance= memcached_instance_fetch(memc_ptr, 0);
+      if (memc.flags.binary_protocol)
+      {
+        rc= binary_stats_fetch(memc_stat, args, args_length, instance, NULL);
+      }
+      else
+      {
+        rc= ascii_stats_fetch(memc_stat, args, args_length, instance, NULL);
+      }
+    }
+  }
+
+  memcached_free(&memc);
+
+  return rc;
+}
+
+/*
+  We make a copy of the keys since at some point in the not so distant future
+  we will add support for "found" keys.
+*/
+char ** memcached_stat_get_keys(memcached_st *shell,
+                                memcached_stat_st *,
+                                memcached_return_t *error)
+{
+  Memcached* memc= memcached2Memcached(shell);
+  if (memc)
+  {
+    char **list= static_cast<char **>(libmemcached_malloc(memc, sizeof(memcached_stat_keys)));
+    if (list == NULL)
+    {
+      if (error)
+      {
+        *error= memcached_set_error(*memc, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+      }
+
+      return NULL;
+    }
+
+    memcpy(list, memcached_stat_keys, sizeof(memcached_stat_keys));
+
+    if (error)
+    {
+      *error= MEMCACHED_SUCCESS;
+    }
+
+    return list;
+  }
+
+  return NULL;
+}
+
+void memcached_stat_free(const memcached_st *, memcached_stat_st *memc_stat)
+{
+  WATCHPOINT_ASSERT(memc_stat); // Be polite, but when debugging catch this as an error
+  if (memc_stat)
+  {
+    libmemcached_free(memc_stat->root, memc_stat);
+  }
+}
+
+static memcached_return_t call_stat_fn(memcached_st *memc,
+                                       memcached_instance_st* instance,
+                                       void *context)
+{
+  if (memc)
+  {
+    local_context *check= (struct local_context *)context;
+
+    if (memcached_is_binary(memc))
+    {
+      return binary_stats_fetch(NULL, check->args, check->args_length, instance, check);
+    }
+    else
+    {
+      return ascii_stats_fetch(NULL, check->args, check->args_length, instance, check);
+    }
+  }
+
+  return MEMCACHED_INVALID_ARGUMENTS;
+}
+
+memcached_return_t memcached_stat_execute(memcached_st *shell, const char *args,  memcached_stat_fn func, void *context)
+{
+  Memcached* memc= memcached2Memcached(shell);
+  if (memcached_fatal(memcached_version(memc)))
+  {
+    return memcached_last_error(memc);
+  }
+
+ local_context check(func, context, args, args ? strlen(args) : 0);
+
+ return memcached_server_execute(memc, call_stat_fn, (void *)&check);
+}
diff --git a/src/libmemcached/storage.cc b/src/libmemcached/storage.cc
new file mode 100644 (file)
index 0000000..61ca827
--- /dev/null
@@ -0,0 +1,580 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libmemcached/common.h>
+
+enum memcached_storage_action_t {
+  SET_OP,
+  REPLACE_OP,
+  ADD_OP,
+  PREPEND_OP,
+  APPEND_OP,
+  CAS_OP
+};
+
+/* Inline this */
+static inline const char *storage_op_string(memcached_storage_action_t verb)
+{
+  switch (verb)
+  {
+  case REPLACE_OP:
+    return "replace ";
+
+  case ADD_OP:
+    return "add ";
+
+  case PREPEND_OP:
+    return "prepend ";
+
+  case APPEND_OP:
+    return "append ";
+
+  case CAS_OP:
+    return "cas ";
+
+  case SET_OP:
+    break;
+  }
+
+  return "set ";
+}
+
+static inline bool can_by_encrypted(const memcached_storage_action_t verb)
+{
+  switch (verb)
+  {
+  case SET_OP:
+  case ADD_OP:
+  case CAS_OP:
+  case REPLACE_OP:
+    return true;
+    
+  case APPEND_OP:
+  case PREPEND_OP:
+    break;
+  }
+
+  return false;
+}
+
+static inline uint8_t get_com_code(const memcached_storage_action_t verb, const bool reply)
+{
+  if (reply == false)
+  {
+    switch (verb)
+    {
+    case SET_OP:
+      return PROTOCOL_BINARY_CMD_SETQ;
+
+    case ADD_OP:
+      return PROTOCOL_BINARY_CMD_ADDQ;
+
+    case CAS_OP: /* FALLTHROUGH */
+    case REPLACE_OP:
+      return PROTOCOL_BINARY_CMD_REPLACEQ;
+
+    case APPEND_OP:
+      return PROTOCOL_BINARY_CMD_APPENDQ;
+
+    case PREPEND_OP:
+      return PROTOCOL_BINARY_CMD_PREPENDQ;
+    }
+  }
+
+  switch (verb)
+  {
+  case SET_OP:
+    break;
+
+  case ADD_OP:
+    return PROTOCOL_BINARY_CMD_ADD;
+
+  case CAS_OP: /* FALLTHROUGH */
+  case REPLACE_OP:
+    return PROTOCOL_BINARY_CMD_REPLACE;
+
+  case APPEND_OP:
+    return PROTOCOL_BINARY_CMD_APPEND;
+
+  case PREPEND_OP:
+    return PROTOCOL_BINARY_CMD_PREPEND;
+  }
+
+  return PROTOCOL_BINARY_CMD_SET;
+}
+
+static memcached_return_t memcached_send_binary(Memcached *ptr,
+                                                memcached_instance_st* server,
+                                                uint32_t server_key,
+                                                const char *key,
+                                                const size_t key_length,
+                                                const char *value,
+                                                const size_t value_length,
+                                                const time_t expiration,
+                                                const uint32_t flags,
+                                                const uint64_t cas,
+                                                const bool flush,
+                                                const bool reply,
+                                                memcached_storage_action_t verb)
+{
+  protocol_binary_request_set request= {};
+  size_t send_length= sizeof(request.bytes);
+
+  initialize_binary_request(server, request.message.header);
+
+  request.message.header.request.opcode= get_com_code(verb, reply);
+  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->_namespace)));
+  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+  if (verb == APPEND_OP or verb == PREPEND_OP)
+  {
+    send_length -= 8; /* append & prepend does not contain extras! */
+  }
+  else
+  {
+    request.message.header.request.extlen= 8;
+    request.message.body.flags= htonl(flags);
+    request.message.body.expiration= htonl((uint32_t)expiration);
+  }
+
+  request.message.header.request.bodylen= htonl((uint32_t) (key_length + memcached_array_size(ptr->_namespace) + value_length +
+                                                            request.message.header.request.extlen));
+
+  if (cas)
+  {
+    request.message.header.request.cas= memcached_htonll(cas);
+  }
+
+  libmemcached_io_vector_st vector[]=
+  {
+    { NULL, 0 },
+    { request.bytes, send_length },
+    { memcached_array_string(ptr->_namespace),  memcached_array_size(ptr->_namespace) },
+    { key, key_length },
+    { value, value_length }
+  };
+
+  /* write the header */
+  memcached_return_t rc;
+  if ((rc= memcached_vdo(server, vector, 5, flush)) != MEMCACHED_SUCCESS)
+  {
+    assert(memcached_last_error(server->root) != MEMCACHED_SUCCESS);
+    return memcached_last_error(server->root);
+  }
+
+  if (verb == SET_OP and ptr->number_of_replicas > 0)
+  {
+    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SETQ;
+    WATCHPOINT_STRING("replicating");
+
+    for (uint32_t x= 0; x < ptr->number_of_replicas; x++)
+    {
+      ++server_key;
+      if (server_key == memcached_server_count(ptr))
+      {
+        server_key= 0;
+      }
+
+      memcached_instance_st* instance= memcached_instance_fetch(ptr, server_key);
+
+      if (memcached_success(memcached_vdo(instance, vector, 5, false)))
+      {
+        memcached_server_response_decrement(instance);
+      }
+    }
+  }
+
+  if (flush == false)
+  {
+    return MEMCACHED_BUFFERED;
+  }
+
+  // No reply always assumes success
+  if (reply == false)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  return memcached_response(server, NULL, 0, NULL);
+}
+
+static memcached_return_t memcached_send_ascii(Memcached *ptr,
+                                               memcached_instance_st* instance,
+                                               const char *key,
+                                               const size_t key_length,
+                                               const char *value,
+                                               const size_t value_length,
+                                               const time_t expiration,
+                                               const uint32_t flags,
+                                               const uint64_t cas,
+                                               const bool flush,
+                                               const bool reply,
+                                               const memcached_storage_action_t verb)
+{
+  char flags_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+  int flags_buffer_length= snprintf(flags_buffer, sizeof(flags_buffer), " %u", flags);
+  if (size_t(flags_buffer_length) >= sizeof(flags_buffer) or flags_buffer_length < 0)
+  {
+    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                               memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
+  }
+
+  char expiration_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+  int expiration_buffer_length= snprintf(expiration_buffer, sizeof(expiration_buffer), " %llu", (unsigned long long)expiration);
+  if (size_t(expiration_buffer_length) >= sizeof(expiration_buffer) or expiration_buffer_length < 0)
+  {
+    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                               memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
+  }
+
+  char value_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+  int value_buffer_length= snprintf(value_buffer, sizeof(value_buffer), " %llu", (unsigned long long)value_length);
+  if (size_t(value_buffer_length) >= sizeof(value_buffer) or value_buffer_length < 0)
+  {
+    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                               memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
+  }
+
+  char cas_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+  int cas_buffer_length= 0;
+  if (cas)
+  {
+    cas_buffer_length= snprintf(cas_buffer, sizeof(cas_buffer), " %llu", (unsigned long long)cas);
+    if (size_t(cas_buffer_length) >= sizeof(cas_buffer) or cas_buffer_length < 0)
+    {
+      return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                                 memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
+    }
+  }
+
+  libmemcached_io_vector_st vector[]=
+  {
+    { NULL, 0 },
+    { storage_op_string(verb), strlen(storage_op_string(verb))},
+    { memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace) },
+    { key, key_length },
+    { flags_buffer, size_t(flags_buffer_length) },
+    { expiration_buffer, size_t(expiration_buffer_length) },
+    { value_buffer, size_t(value_buffer_length) },
+    { cas_buffer, size_t(cas_buffer_length) },
+    { " noreply", reply ? 0 : memcached_literal_param_size(" noreply") },
+    { memcached_literal_param("\r\n") },
+    { value, value_length },
+    { memcached_literal_param("\r\n") }
+  };
+
+  /* Send command header */
+  memcached_return_t rc=  memcached_vdo(instance, vector, 12, flush);
+
+  // If we should not reply, return with MEMCACHED_SUCCESS, unless error
+  if (reply == false)
+  {
+    return memcached_success(rc) ? MEMCACHED_SUCCESS : rc; 
+  }
+
+  if (flush == false)
+  {
+    return memcached_success(rc) ? MEMCACHED_BUFFERED : rc; 
+  }
+
+  if (rc == MEMCACHED_SUCCESS)
+  {
+    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+    rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
+
+    if (rc == MEMCACHED_STORED)
+    {
+      return MEMCACHED_SUCCESS;
+    }
+  }
+
+  assert(memcached_failed(rc));
+#if 0
+  if (memcached_has_error(ptr) == false)
+  {
+    return memcached_set_error(*ptr, rc, MEMCACHED_AT);
+  }
+#endif
+
+  return rc;
+}
+
+static inline memcached_return_t memcached_send(memcached_st *shell,
+                                                const char *group_key, size_t group_key_length,
+                                                const char *key, size_t key_length,
+                                                const char *value, size_t value_length,
+                                                const time_t expiration,
+                                                const uint32_t flags,
+                                                const uint64_t cas,
+                                                memcached_storage_action_t verb)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(ptr, true)))
+  {
+    return rc;
+  }
+
+  if (memcached_failed(memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
+  {
+    return memcached_last_error(ptr);
+  }
+
+  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+  memcached_instance_st* instance= memcached_instance_fetch(ptr, server_key);
+
+  WATCHPOINT_SET(instance->io_wait_count.read= 0);
+  WATCHPOINT_SET(instance->io_wait_count.write= 0);
+
+  bool flush= true;
+  if (memcached_is_buffering(instance->root) and verb == SET_OP)
+  {
+    flush= false;
+  }
+
+  bool reply= memcached_is_replying(ptr);
+
+  hashkit_string_st* destination= NULL;
+
+  if (memcached_is_encrypted(ptr))
+  {
+    if (can_by_encrypted(verb) == false)
+    {
+      return memcached_set_error(*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT, 
+                                 memcached_literal_param("Operation not allowed while encyrption is enabled"));
+    }
+
+    if ((destination= hashkit_encrypt(&ptr->hashkit, value, value_length)) == NULL)
+    {
+      return rc;
+    }
+    value= hashkit_string_c_str(destination);
+    value_length= hashkit_string_length(destination);
+  }
+
+  if (memcached_is_binary(ptr))
+  {
+    rc= memcached_send_binary(ptr, instance, server_key,
+                              key, key_length,
+                              value, value_length, expiration,
+                              flags, cas, flush, reply, verb);
+  }
+  else
+  {
+    rc= memcached_send_ascii(ptr, instance,
+                             key, key_length,
+                             value, value_length, expiration,
+                             flags, cas, flush, reply, verb);
+  }
+
+  hashkit_string_free(destination);
+
+  return rc;
+}
+
+
+memcached_return_t memcached_set(memcached_st *ptr, const char *key, size_t key_length,
+                                 const char *value, size_t value_length,
+                                 time_t expiration,
+                                 uint32_t flags)
+{
+  memcached_return_t rc;
+  LIBMEMCACHED_MEMCACHED_SET_START();
+  rc= memcached_send(ptr, key, key_length,
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, SET_OP);
+  LIBMEMCACHED_MEMCACHED_SET_END();
+  return rc;
+}
+
+memcached_return_t memcached_add(memcached_st *ptr,
+                                 const char *key, size_t key_length,
+                                 const char *value, size_t value_length,
+                                 time_t expiration,
+                                 uint32_t flags)
+{
+  memcached_return_t rc;
+  LIBMEMCACHED_MEMCACHED_ADD_START();
+  rc= memcached_send(ptr, key, key_length,
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, ADD_OP);
+
+  LIBMEMCACHED_MEMCACHED_ADD_END();
+  return rc;
+}
+
+memcached_return_t memcached_replace(memcached_st *ptr,
+                                     const char *key, size_t key_length,
+                                     const char *value, size_t value_length,
+                                     time_t expiration,
+                                     uint32_t flags)
+{
+  memcached_return_t rc;
+  LIBMEMCACHED_MEMCACHED_REPLACE_START();
+  rc= memcached_send(ptr, key, key_length,
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, REPLACE_OP);
+  LIBMEMCACHED_MEMCACHED_REPLACE_END();
+  return rc;
+}
+
+memcached_return_t memcached_prepend(memcached_st *ptr,
+                                     const char *key, size_t key_length,
+                                     const char *value, size_t value_length,
+                                     time_t expiration,
+                                     uint32_t flags)
+{
+  memcached_return_t rc;
+  rc= memcached_send(ptr, key, key_length,
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, PREPEND_OP);
+  return rc;
+}
+
+memcached_return_t memcached_append(memcached_st *ptr,
+                                    const char *key, size_t key_length,
+                                    const char *value, size_t value_length,
+                                    time_t expiration,
+                                    uint32_t flags)
+{
+  memcached_return_t rc;
+  rc= memcached_send(ptr, key, key_length,
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, APPEND_OP);
+  return rc;
+}
+
+memcached_return_t memcached_cas(memcached_st *ptr,
+                                 const char *key, size_t key_length,
+                                 const char *value, size_t value_length,
+                                 time_t expiration,
+                                 uint32_t flags,
+                                 uint64_t cas)
+{
+  memcached_return_t rc;
+  rc= memcached_send(ptr, key, key_length,
+                     key, key_length, value, value_length,
+                     expiration, flags, cas, CAS_OP);
+  return rc;
+}
+
+memcached_return_t memcached_set_by_key(memcached_st *ptr,
+                                        const char *group_key,
+                                        size_t group_key_length,
+                                        const char *key, size_t key_length,
+                                        const char *value, size_t value_length,
+                                        time_t expiration,
+                                        uint32_t flags)
+{
+  memcached_return_t rc;
+  LIBMEMCACHED_MEMCACHED_SET_START();
+  rc= memcached_send(ptr, group_key, group_key_length,
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, SET_OP);
+  LIBMEMCACHED_MEMCACHED_SET_END();
+  return rc;
+}
+
+memcached_return_t memcached_add_by_key(memcached_st *ptr,
+                                        const char *group_key, size_t group_key_length,
+                                        const char *key, size_t key_length,
+                                        const char *value, size_t value_length,
+                                        time_t expiration,
+                                        uint32_t flags)
+{
+  memcached_return_t rc;
+  LIBMEMCACHED_MEMCACHED_ADD_START();
+  rc= memcached_send(ptr, group_key, group_key_length,
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, ADD_OP);
+  LIBMEMCACHED_MEMCACHED_ADD_END();
+  return rc;
+}
+
+memcached_return_t memcached_replace_by_key(memcached_st *ptr,
+                                            const char *group_key, size_t group_key_length,
+                                            const char *key, size_t key_length,
+                                            const char *value, size_t value_length,
+                                            time_t expiration,
+                                            uint32_t flags)
+{
+  memcached_return_t rc;
+  LIBMEMCACHED_MEMCACHED_REPLACE_START();
+  rc= memcached_send(ptr, group_key, group_key_length,
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, REPLACE_OP);
+  LIBMEMCACHED_MEMCACHED_REPLACE_END();
+  return rc;
+}
+
+memcached_return_t memcached_prepend_by_key(memcached_st *ptr,
+                                            const char *group_key, size_t group_key_length,
+                                            const char *key, size_t key_length,
+                                            const char *value, size_t value_length,
+                                            time_t expiration,
+                                            uint32_t flags)
+{
+  return memcached_send(ptr, group_key, group_key_length,
+                        key, key_length, value, value_length,
+                        expiration, flags, 0, PREPEND_OP);
+}
+
+memcached_return_t memcached_append_by_key(memcached_st *ptr,
+                                           const char *group_key, size_t group_key_length,
+                                           const char *key, size_t key_length,
+                                           const char *value, size_t value_length,
+                                           time_t expiration,
+                                           uint32_t flags)
+{
+  return memcached_send(ptr, group_key, group_key_length,
+                        key, key_length, value, value_length,
+                        expiration, flags, 0, APPEND_OP);
+}
+
+memcached_return_t memcached_cas_by_key(memcached_st *ptr,
+                                        const char *group_key, size_t group_key_length,
+                                        const char *key, size_t key_length,
+                                        const char *value, size_t value_length,
+                                        time_t expiration,
+                                        uint32_t flags,
+                                        uint64_t cas)
+{
+  return  memcached_send(ptr, group_key, group_key_length,
+                         key, key_length, value, value_length,
+                         expiration, flags, cas, CAS_OP);
+}
+
diff --git a/src/libmemcached/strerror.cc b/src/libmemcached/strerror.cc
new file mode 100644 (file)
index 0000000..c5615ca
--- /dev/null
@@ -0,0 +1,198 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+const char *memcached_strerror(const memcached_st *, memcached_return_t rc)
+{
+  switch (rc)
+  {
+  case MEMCACHED_SUCCESS:
+    return "SUCCESS";
+
+  case MEMCACHED_FAILURE:
+    return "FAILURE";
+
+  case MEMCACHED_HOST_LOOKUP_FAILURE: // getaddrinfo only
+    return "getaddrinfo() or getnameinfo() HOSTNAME LOOKUP FAILURE";
+
+  case MEMCACHED_CONNECTION_FAILURE:
+    return "CONNECTION FAILURE";
+
+  case MEMCACHED_CONNECTION_BIND_FAILURE: // DEPRECATED, see MEMCACHED_HOST_LOOKUP_FAILURE
+    return "CONNECTION BIND FAILURE";
+
+  case MEMCACHED_READ_FAILURE:
+    return "READ FAILURE";
+
+  case MEMCACHED_UNKNOWN_READ_FAILURE:
+    return "UNKNOWN READ FAILURE";
+
+  case MEMCACHED_PROTOCOL_ERROR:
+    return "PROTOCOL ERROR";
+
+  case MEMCACHED_CLIENT_ERROR:
+    return "CLIENT ERROR";
+
+  case MEMCACHED_SERVER_ERROR:
+    return "SERVER ERROR";
+
+  case MEMCACHED_WRITE_FAILURE:
+    return "WRITE FAILURE";
+
+  case MEMCACHED_ERROR:
+    return "ERROR was returned by server";
+
+  case MEMCACHED_DATA_EXISTS:
+    return "CONNECTION DATA EXISTS";
+
+  case MEMCACHED_DATA_DOES_NOT_EXIST:
+    return "CONNECTION DATA DOES NOT EXIST";
+
+  case MEMCACHED_NOTSTORED:
+    return "NOT STORED";
+
+  case MEMCACHED_STORED:
+    return "STORED";
+
+  case MEMCACHED_NOTFOUND:
+    return "NOT FOUND";
+
+  case MEMCACHED_MEMORY_ALLOCATION_FAILURE:
+    return "MEMORY ALLOCATION FAILURE";
+
+  case MEMCACHED_PARTIAL_READ:
+    return "PARTIAL READ";
+
+  case MEMCACHED_SOME_ERRORS:
+    return "SOME ERRORS WERE REPORTED";
+
+  case MEMCACHED_NO_SERVERS:
+    return "NO SERVERS DEFINED";
+
+  case MEMCACHED_END:
+    return "SERVER END";
+
+  case MEMCACHED_DELETED:
+    return "SERVER DELETE";
+
+  case MEMCACHED_VALUE:
+    return "SERVER VALUE";
+
+  case MEMCACHED_STAT:
+    return "STAT VALUE";
+
+  case MEMCACHED_ITEM:
+    return "ITEM VALUE";
+
+  case MEMCACHED_ERRNO:
+    return "SYSTEM ERROR";
+
+  case MEMCACHED_FAIL_UNIX_SOCKET:
+    return "COULD NOT OPEN UNIX SOCKET";
+
+  case MEMCACHED_NOT_SUPPORTED:
+    return "ACTION NOT SUPPORTED";
+
+  case MEMCACHED_FETCH_NOTFINISHED:
+    return "FETCH WAS NOT COMPLETED";
+
+  case MEMCACHED_NO_KEY_PROVIDED:
+    return "A KEY LENGTH OF ZERO WAS PROVIDED";
+
+  case MEMCACHED_BUFFERED:
+    return "ACTION QUEUED";
+
+  case MEMCACHED_TIMEOUT:
+    return "A TIMEOUT OCCURRED";
+
+  case MEMCACHED_BAD_KEY_PROVIDED:
+    return "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE";
+
+  case MEMCACHED_INVALID_HOST_PROTOCOL:
+    return "THE HOST TRANSPORT PROTOCOL DOES NOT MATCH THAT OF THE CLIENT";
+
+  case MEMCACHED_SERVER_MARKED_DEAD:
+    return "SERVER IS MARKED DEAD";
+
+  case MEMCACHED_UNKNOWN_STAT_KEY:
+    return "ENCOUNTERED AN UNKNOWN STAT KEY";
+
+  case MEMCACHED_E2BIG:
+    return "ITEM TOO BIG";
+
+  case MEMCACHED_INVALID_ARGUMENTS:
+     return "INVALID ARGUMENTS";
+
+  case MEMCACHED_KEY_TOO_BIG:
+     return "KEY RETURNED FROM SERVER WAS TOO LARGE";
+
+  case MEMCACHED_AUTH_PROBLEM:
+    return "FAILED TO SEND AUTHENTICATION TO SERVER";
+
+  case MEMCACHED_AUTH_FAILURE:
+    return "AUTHENTICATION FAILURE";
+
+  case MEMCACHED_AUTH_CONTINUE:
+    return "CONTINUE AUTHENTICATION";
+
+  case MEMCACHED_PARSE_ERROR:
+    return "ERROR OCCURED WHILE PARSING";
+
+  case MEMCACHED_PARSE_USER_ERROR:
+    return "USER INITIATED ERROR OCCURED WHILE PARSING";
+
+  case MEMCACHED_DEPRECATED:
+    return "DEPRECATED";
+
+  case MEMCACHED_IN_PROGRESS:
+    return "OPERATION IN PROCESS";
+
+  case MEMCACHED_SERVER_TEMPORARILY_DISABLED:
+    return "SERVER HAS FAILED AND IS DISABLED UNTIL TIMED RETRY";
+
+  case MEMCACHED_SERVER_MEMORY_ALLOCATION_FAILURE:
+    return "SERVER FAILED TO ALLOCATE OBJECT";
+
+  case MEMCACHED_UNIX_SOCKET_PATH_TOO_BIG:
+    return "UNIX SOCKET PATH TOO LARGE";
+
+  default:
+  case MEMCACHED_MAXIMUM_RETURN:
+    return "INVALID memcached_return_t";
+  }
+}
diff --git a/src/libmemcached/string.cc b/src/libmemcached/string.cc
new file mode 100644 (file)
index 0000000..b821aca
--- /dev/null
@@ -0,0 +1,330 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libmemcached/common.h>
+
+inline static memcached_return_t _string_check(memcached_string_st *string, size_t need)
+{
+  if (need && need > (size_t)(string->current_size - (size_t)(string->end - string->string)))
+  {
+    size_t current_offset= (size_t) (string->end - string->string);
+
+    /* This is the block multiplier. To keep it larger and surive division errors we must round it up */
+    size_t adjust= (need - (size_t)(string->current_size - (size_t)(string->end - string->string))) / MEMCACHED_BLOCK_SIZE;
+    adjust++;
+
+    size_t new_size= sizeof(char) * (size_t)((adjust * MEMCACHED_BLOCK_SIZE) + string->current_size);
+    /* Test for overflow */
+    if (new_size < need)
+    {
+      char error_message[1024];
+      int error_message_length= snprintf(error_message, sizeof(error_message),"Needed %ld, got %ld", (long)need, (long)new_size);
+      return memcached_set_error(*string->root, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, error_message, error_message_length);
+    }
+
+    char *new_value= libmemcached_xrealloc(string->root, string->string, new_size, char);
+
+    if (new_value == NULL)
+    {
+      return memcached_set_error(*string->root, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+    }
+
+    string->string= new_value;
+    string->end= string->string + current_offset;
+
+    string->current_size+= (MEMCACHED_BLOCK_SIZE * adjust);
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+static inline void _init_string(memcached_string_st *self)
+{
+  self->current_size= 0;
+  self->end= self->string= NULL;
+}
+
+memcached_string_st *memcached_string_create(Memcached *memc, memcached_string_st *self, size_t initial_size)
+{
+  WATCHPOINT_ASSERT(memc);
+
+  /* Saving malloc calls :) */
+  if (self)
+  {
+    WATCHPOINT_ASSERT(self->options.is_initialized == false);
+
+    memcached_set_allocated(self, false);
+  }
+  else
+  {
+    self= libmemcached_xmalloc(memc, memcached_string_st);
+
+    if (self == NULL)
+    {
+      return NULL;
+    }
+
+    memcached_set_allocated(self, true);
+  }
+  self->root= memc;
+
+  _init_string(self);
+
+  if (memcached_failed(_string_check(self, initial_size)))
+  {
+    if (memcached_is_allocated(self))
+    {
+      libmemcached_free(memc, self);
+    }
+
+    return NULL;
+  }
+
+  memcached_set_initialized(self, true);
+
+  WATCHPOINT_ASSERT(self->string == self->end);
+
+  return self;
+}
+
+static memcached_return_t memcached_string_append_null(memcached_string_st& string)
+{
+  if (memcached_failed(_string_check(&string, 1)))
+  {
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+  }
+
+  *string.end= 0;
+
+  return MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t memcached_string_append_null(memcached_string_st *string)
+{
+  if (memcached_failed(_string_check(string, 1)))
+  {
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+  }
+
+  *string->end= 0;
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_string_append_character(memcached_string_st *string,
+                                                     char character)
+{
+  if (memcached_failed(_string_check(string, 1)))
+  {
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+  }
+
+  *string->end= character;
+  string->end++;
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_string_append(memcached_string_st *string,
+                                           const char *value, size_t length)
+{
+  if (memcached_failed(_string_check(string, length)))
+  {
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+  }
+
+  WATCHPOINT_ASSERT(length <= string->current_size);
+  WATCHPOINT_ASSERT(string->string);
+  WATCHPOINT_ASSERT(string->end >= string->string);
+
+  memcpy(string->end, value, length);
+  string->end+= length;
+
+  return MEMCACHED_SUCCESS;
+}
+
+char *memcached_string_c_copy(memcached_string_st *string)
+{
+  if (memcached_string_length(string) == 0)
+  {
+    return NULL;
+  }
+
+  char *c_ptr= static_cast<char *>(libmemcached_malloc(string->root, (memcached_string_length(string)+1) * sizeof(char)));
+
+  if (c_ptr == NULL)
+  {
+    return NULL;
+  }
+
+  memcpy(c_ptr, memcached_string_value(string), memcached_string_length(string));
+  c_ptr[memcached_string_length(string)]= 0;
+
+  return c_ptr;
+}
+
+bool memcached_string_set(memcached_string_st& string, const char* value, size_t length)
+{
+  memcached_string_reset(&string);
+  if (memcached_success(memcached_string_append(&string, value, length)))
+  {
+    memcached_string_append_null(string);
+    return true;
+  }
+
+  return false;
+}
+
+void memcached_string_reset(memcached_string_st *string)
+{
+  string->end= string->string;
+}
+
+void memcached_string_free(memcached_string_st& ptr)
+{
+  memcached_string_free(&ptr);
+}
+
+void memcached_string_free(memcached_string_st *ptr)
+{
+  if (ptr == NULL)
+  {
+    return;
+  }
+
+  if (ptr->string)
+  {
+    libmemcached_free(ptr->root, ptr->string);
+  }
+
+  if (memcached_is_allocated(ptr))
+  {
+    libmemcached_free(ptr->root, ptr);
+  }
+  else
+  {
+    ptr->options.is_initialized= false;
+  }
+}
+
+memcached_return_t memcached_string_check(memcached_string_st *string, size_t need)
+{
+  return _string_check(string, need);
+}
+
+bool memcached_string_resize(memcached_string_st& string, const size_t need)
+{
+  return memcached_success(_string_check(&string, need));
+}
+
+size_t memcached_string_length(const memcached_string_st *self)
+{
+  return size_t(self->end -self->string);
+}
+
+size_t memcached_string_length(const memcached_string_st& self)
+{
+  return size_t(self.end -self.string);
+}
+
+size_t memcached_string_size(const memcached_string_st *self)
+{
+  return self->current_size;
+}
+
+const char *memcached_string_value(const memcached_string_st *self)
+{
+  return self->string;
+}
+
+const char *memcached_string_value(const memcached_string_st& self)
+{
+  return self.string;
+}
+
+char *memcached_string_take_value(memcached_string_st *self)
+{
+  char* value= NULL;
+
+  assert_msg(self, "Invalid memcached_string_st");
+  if (self)
+  {
+    if (memcached_string_length(self))
+    {
+      // If we fail at adding the null, we copy and move on
+      if (memcached_failed(memcached_string_append_null(self)))
+      {
+        return NULL;
+      }
+
+      value= self->string;
+      _init_string(self);
+    }
+  }
+
+  return value;
+}
+
+char *memcached_string_value_mutable(const memcached_string_st *self)
+{
+  return self->string;
+}
+
+char *memcached_string_c_str(memcached_string_st& self)
+{
+  return self.string;
+}
+
+void memcached_string_set_length(memcached_string_st *self, size_t length)
+{
+  self->end= self->string +length;
+}
+
+void memcached_string_set_length(memcached_string_st& self, const size_t length)
+{
+  assert(self.current_size >= length);
+  size_t set_length= length;
+  if (self.current_size > length)
+  {
+    if (memcached_failed(_string_check(&self, length)))
+    {
+      set_length= self.current_size;
+    }
+  }
+  self.end= self.string +set_length;
+}
diff --git a/src/libmemcached/string.hpp b/src/libmemcached/string.hpp
new file mode 100644 (file)
index 0000000..e2978cc
--- /dev/null
@@ -0,0 +1,94 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  libmcachedd client library.
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include "util/string.hpp"
+
+#define memcached_literal_param util_literal_param
+#define memcached_literal_param_size util_literal_param_size
+#define memcached_string_make_from_cstr util_string_make_from_cstr
+#define memcached_array_length util_array_length
+
+/**
+  Strings are always under our control so we make some assumptions
+  about them.
+
+  1) is_initialized is always valid.
+  2) A string once intialized will always be, until free where we
+     unset this flag.
+  3) A string always has a root.
+*/
+
+memcached_string_st *memcached_string_create(memcached_st *ptr,
+                                             memcached_string_st *string,
+                                             size_t initial_size);
+
+memcached_return_t memcached_string_check(memcached_string_st *string, size_t need);
+
+char *memcached_string_c_copy(memcached_string_st *string);
+
+memcached_return_t memcached_string_append_character(memcached_string_st *string,
+                                                     char character);
+
+memcached_return_t memcached_string_append(memcached_string_st *string,
+                                           const char *value, size_t length);
+
+void memcached_string_reset(memcached_string_st *string);
+
+void memcached_string_free(memcached_string_st *string);
+void memcached_string_free(memcached_string_st&);
+
+size_t memcached_string_length(const memcached_string_st *self);
+size_t memcached_string_length(const memcached_string_st&);
+
+size_t memcached_string_size(const memcached_string_st *self);
+
+const char *memcached_string_value(const memcached_string_st *self);
+const char *memcached_string_value(const memcached_string_st&);
+
+char *memcached_string_take_value(memcached_string_st *self);
+
+char *memcached_string_value_mutable(const memcached_string_st *self);
+
+bool memcached_string_set(memcached_string_st&, const char*, size_t);
+
+void memcached_string_set_length(memcached_string_st *self, size_t length);
+void memcached_string_set_length(memcached_string_st&, const size_t length);
+
+bool memcached_string_resize(memcached_string_st&, const size_t);
+char *memcached_string_c_str(memcached_string_st&);
diff --git a/src/libmemcached/touch.cc b/src/libmemcached/touch.cc
new file mode 100644 (file)
index 0000000..9e9cbd6
--- /dev/null
@@ -0,0 +1,155 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+static memcached_return_t ascii_touch(memcached_instance_st* instance,
+                                      const char *key, size_t key_length,
+                                      time_t expiration)
+{
+  char expiration_buffer[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH +1];
+  int expiration_buffer_length= snprintf(expiration_buffer, sizeof(expiration_buffer), " %llu", (unsigned long long)expiration);
+  if (size_t(expiration_buffer_length) >= sizeof(expiration_buffer)+1 or expiration_buffer_length < 0)
+  {
+    return memcached_set_error(*instance, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                               memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
+  }
+
+  libmemcached_io_vector_st vector[]=
+  {
+    { NULL, 0 },
+    { memcached_literal_param("touch ") },
+    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+    { key, key_length },
+    { expiration_buffer, size_t(expiration_buffer_length) },
+    { memcached_literal_param("\r\n") }
+  };
+
+  memcached_return_t rc;
+  if (memcached_failed(rc= memcached_vdo(instance, vector, 6, true)))
+  {
+    return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+  }
+
+  return rc;
+}
+
+static memcached_return_t binary_touch(memcached_instance_st* instance,
+                                       const char *key, size_t key_length,
+                                       time_t expiration)
+{
+  protocol_binary_request_touch request= {}; //{.bytes= {0}};
+
+  initialize_binary_request(instance, request.message.header);
+
+  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_TOUCH;
+  request.message.header.request.extlen= 4;
+  request.message.header.request.keylen= htons((uint16_t)(key_length +memcached_array_size(instance->root->_namespace)));
+  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+  request.message.header.request.bodylen= htonl((uint32_t)(key_length +memcached_array_size(instance->root->_namespace) +request.message.header.request.extlen));
+  request.message.body.expiration= htonl((uint32_t) expiration);
+
+  libmemcached_io_vector_st vector[]=
+  {
+    { NULL, 0 },
+    { request.bytes, sizeof(request.bytes) },
+    { memcached_array_string(instance->root->_namespace), memcached_array_size(instance->root->_namespace) },
+    { key, key_length }
+  };
+
+  memcached_return_t rc;
+  if (memcached_failed(rc= memcached_vdo(instance, vector, 4, true)))
+  {
+    return memcached_set_error(*instance, MEMCACHED_WRITE_FAILURE, MEMCACHED_AT);
+  }
+
+  return rc;
+}
+
+memcached_return_t memcached_touch(memcached_st *ptr,
+                                   const char *key, size_t key_length,
+                                   time_t expiration)
+{
+  return memcached_touch_by_key(ptr, key, key_length, key, key_length, expiration);
+}
+
+memcached_return_t memcached_touch_by_key(memcached_st *shell,
+                                          const char *group_key, size_t group_key_length,
+                                          const char *key, size_t key_length,
+                                          time_t expiration)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  LIBMEMCACHED_MEMCACHED_TOUCH_START();
+
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(ptr, true)))
+  {
+    return rc;
+  }
+
+  if (memcached_failed(rc= memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
+  {
+    return memcached_set_error(*ptr, rc, MEMCACHED_AT);
+  }
+
+  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+  memcached_instance_st* instance= memcached_instance_fetch(ptr, server_key);
+
+  if (ptr->flags.binary_protocol)
+  {
+    rc= binary_touch(instance, key, key_length, expiration);
+  }
+  else
+  {
+    rc= ascii_touch(instance, key, key_length, expiration);
+  }
+
+  if (memcached_failed(rc))
+  {
+    return memcached_set_error(*instance, rc, MEMCACHED_AT, memcached_literal_param("Error occcured while writing touch command to server"));
+  }
+
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+  rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
+
+  if (rc == MEMCACHED_SUCCESS or rc == MEMCACHED_NOTFOUND)
+  {
+    return rc;
+  }
+
+  return memcached_set_error(*instance, rc, MEMCACHED_AT, memcached_literal_param("Error occcured while reading response"));
+}
diff --git a/src/libmemcached/udp.cc b/src/libmemcached/udp.cc
new file mode 100644 (file)
index 0000000..5d21f9f
--- /dev/null
@@ -0,0 +1,77 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+/*
+ * The udp request id consists of two seperate sections
+ *   1) The thread id
+ *   2) The message number
+ * The thread id should only be set when the memcached_st struct is created
+ * and should not be changed.
+ *
+ * The message num is incremented for each new message we send, this function
+ * extracts the message number from message_id, increments it and then
+ * writes the new value back into the header
+ */
+void increment_udp_message_id(memcached_instance_st* ptr)
+{
+  struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
+  uint16_t cur_req= get_udp_datagram_request_id(header);
+  int msg_num= get_msg_num_from_request_id(cur_req);
+  int thread_id= get_thread_id_from_request_id(cur_req);
+
+  if (((++msg_num) & UDP_REQUEST_ID_THREAD_MASK) != 0)
+    msg_num= 0;
+
+  header->request_id= htons((uint16_t) (thread_id | msg_num));
+}
+
+bool memcached_io_init_udp_header(memcached_instance_st* ptr, const uint16_t thread_id)
+{
+  if (thread_id > UDP_REQUEST_ID_MAX_THREAD_ID)
+  {
+    return MEMCACHED_FAILURE;
+  }
+
+  struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
+  header->request_id= htons(uint16_t((generate_udp_request_thread_id(thread_id))));
+  header->num_datagrams= htons(1);
+  header->sequence_number= htons(0);
+
+  return MEMCACHED_SUCCESS;
+}
diff --git a/src/libmemcached/udp.hpp b/src/libmemcached/udp.hpp
new file mode 100644 (file)
index 0000000..7442c59
--- /dev/null
@@ -0,0 +1,59 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define MAX_UDP_DATAGRAM_LENGTH 1400
+#define UDP_DATAGRAM_HEADER_LENGTH 8
+#define UDP_REQUEST_ID_MSG_SIG_DIGITS 10
+#define UDP_REQUEST_ID_THREAD_MASK 0xFFFF << UDP_REQUEST_ID_MSG_SIG_DIGITS
+#define get_udp_datagram_request_id(A) ntohs((A)->request_id)
+#define get_udp_datagram_seq_num(A) ntohs((A)->sequence_number)
+#define get_udp_datagram_num_datagrams(A) ntohs((A)->num_datagrams)
+#define get_msg_num_from_request_id(A) ( (A) & (~(UDP_REQUEST_ID_THREAD_MASK)) )
+#define get_thread_id_from_request_id(A) ( (A) & (UDP_REQUEST_ID_THREAD_MASK) ) >> UDP_REQUEST_ID_MSG_SIG_DIGITS
+#define generate_udp_request_thread_id(A) (A) << UDP_REQUEST_ID_MSG_SIG_DIGITS
+#define UDP_REQUEST_ID_MAX_THREAD_ID get_thread_id_from_request_id(0xFFFF)
+
+struct udp_datagram_header_st
+{
+  uint16_t request_id;
+  uint16_t sequence_number;
+  uint16_t num_datagrams;
+  uint16_t reserved;
+};
+
+bool memcached_io_init_udp_header(memcached_instance_st*, const uint16_t thread_id);
+void increment_udp_message_id(memcached_instance_st*);
diff --git a/src/libmemcached/util.h b/src/libmemcached/util.h
new file mode 100644 (file)
index 0000000..03ed6da
--- /dev/null
@@ -0,0 +1,40 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libmemcachedutil-1.0/util.h>
+
diff --git a/src/libmemcached/util/Makefile.am b/src/libmemcached/util/Makefile.am
new file mode 100644 (file)
index 0000000..bbb94dd
--- /dev/null
@@ -0,0 +1,11 @@
+EXTRA_DIST= libmemcachedutil.ver
+
+lib_LTLIBRARIES=
+
+if BUILD_LIBMEMCACHEDUTIL
+lib_LTLIBRARIES+= libmemcachedutil.la
+endif
+
+libmemcachedutil_la_SOURCES= memcached_pool.c
+libmemcachedutil_la_LDFLAGS= -version-info $(MEMCACHEDUTIL_LIBRARY_VERSION) $(LD_UTIL_VERSION_SCRIPT)
+libmemcachedutil_la_LIBADD= ${top_builddir}/libmemcached/libmemcached.la
diff --git a/src/libmemcached/verbosity.cc b/src/libmemcached/verbosity.cc
new file mode 100644 (file)
index 0000000..43d7374
--- /dev/null
@@ -0,0 +1,104 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+struct context_st
+{
+  size_t length;
+  const char *buffer;
+};
+
+static memcached_return_t _set_verbosity(const Memcached *,
+                                         const memcached_instance_st * server,
+                                         void *context)
+{
+ libmemcached_io_vector_st *vector= (libmemcached_io_vector_st *)context;
+
+  Memcached local_memc;
+  Memcached *memc_ptr= memcached_create(&local_memc);
+
+  memcached_return_t rc= memcached_server_add(memc_ptr, memcached_server_name(server), memcached_server_port(server));
+
+  if (rc == MEMCACHED_SUCCESS)
+  {
+    memcached_instance_st* instance= memcached_instance_fetch(memc_ptr, 0);
+
+    rc= memcached_vdo(instance, vector, 2, true);
+
+    if (rc == MEMCACHED_SUCCESS)
+    {
+      char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+      rc= memcached_response(instance, buffer, sizeof(buffer), NULL);
+    }
+  }
+
+  memcached_free(memc_ptr);
+
+  return rc;
+}
+
+memcached_return_t memcached_verbosity(memcached_st *shell, uint32_t verbosity)
+{
+  Memcached* ptr= memcached2Memcached(shell);
+  memcached_return_t rc;
+  if (memcached_failed(rc= initialize_query(ptr, false)))
+  {
+    return rc;
+  }
+
+  memcached_server_fn callbacks[1];
+
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+
+  int send_length= snprintf(buffer, sizeof(buffer), "verbosity %u\r\n", verbosity);
+  if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE or send_length < 0)
+  {
+    return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT, 
+                               memcached_literal_param("snprintf(MEMCACHED_DEFAULT_COMMAND_SIZE)"));
+  }
+
+  libmemcached_io_vector_st vector[]=
+  {
+    { NULL, 0 },
+    { buffer, size_t(send_length) },
+  };
+
+  callbacks[0]= _set_verbosity;
+
+  return memcached_server_cursor(ptr, callbacks, vector, 1);
+}
diff --git a/src/libmemcached/version.cc b/src/libmemcached/version.cc
new file mode 100644 (file)
index 0000000..53d24c1
--- /dev/null
@@ -0,0 +1,250 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+#include <libmemcached/common.h>
+
+const char * memcached_lib_version(void) 
+{
+  return LIBMEMCACHED_VERSION_STRING;
+}
+
+static inline memcached_return_t memcached_version_textual(Memcached *memc)
+{
+  libmemcached_io_vector_st vector[]=
+  {
+    { memcached_literal_param("version\r\n") },
+  };
+
+  uint32_t success= 0;
+  bool errors_happened= false;
+  for (uint32_t x= 0; x < memcached_server_count(memc); x++)
+  {
+    memcached_instance_st* instance= memcached_instance_fetch(memc, x);
+
+    // Optimization, we only fetch version once.
+    if (instance->major_version != UINT8_MAX)
+    {
+      continue;
+    }
+
+    memcached_return_t rrc;
+    if (memcached_failed(rrc= memcached_vdo(instance, vector, 1, true)))
+    {
+      errors_happened= true;
+      (void)memcached_set_error(*instance, rrc, MEMCACHED_AT);
+      continue;
+    }
+    success++;
+  }
+
+  if (success)
+  {
+    // Collect the returned items
+    memcached_instance_st* instance;
+    memcached_return_t readable_error;
+    while ((instance= memcached_io_get_readable_server(memc, readable_error)))
+    {
+      memcached_return_t rrc= memcached_response(instance, NULL);
+      if (memcached_failed(rrc))
+      {
+        errors_happened= true;
+      }
+    }
+  }
+
+  return errors_happened ? MEMCACHED_SOME_ERRORS : MEMCACHED_SUCCESS;
+}
+
+static inline memcached_return_t memcached_version_binary(Memcached *memc)
+{
+  protocol_binary_request_version request= {};
+
+  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
+  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+
+  libmemcached_io_vector_st vector[]=
+  {
+    { request.bytes, sizeof(request.bytes) }
+  };
+
+  uint32_t success= 0;
+  bool errors_happened= false;
+  for (uint32_t x= 0; x < memcached_server_count(memc); x++) 
+  {
+    memcached_instance_st* instance= memcached_instance_fetch(memc, x);
+
+    initialize_binary_request(instance, request.message.header);
+
+    if (instance->major_version != UINT8_MAX)
+    {
+      continue;
+    }
+
+    memcached_return_t rrc= memcached_vdo(instance, vector, 1, true);
+    if (memcached_failed(rrc))
+    {
+      errors_happened= true;
+      continue;
+    }
+
+    success++;
+  }
+
+  if (success)
+  {
+    // Collect the returned items
+    memcached_instance_st* instance;
+    memcached_return_t readable_error;
+    while ((instance= memcached_io_get_readable_server(memc, readable_error)))
+    {
+      char buffer[32];
+      memcached_return_t rrc= memcached_response(instance, buffer, sizeof(buffer), NULL);
+      if (memcached_failed(rrc))
+      {
+        errors_happened= true;
+      }
+    }
+  }
+
+  return errors_happened ? MEMCACHED_SOME_ERRORS : MEMCACHED_SUCCESS;
+}
+
+static inline void version_ascii_instance(memcached_instance_st* instance)
+{
+  if (instance->major_version != UINT8_MAX)
+  {
+    libmemcached_io_vector_st vector[]=
+    {
+      { memcached_literal_param("version\r\n") },
+    };
+
+    (void)memcached_vdo(instance, vector, 1, false);
+  }
+}
+
+static inline void version_binary_instance(memcached_instance_st* instance)
+{
+  if (instance->major_version != UINT8_MAX)
+  {
+    protocol_binary_request_version request= {};
+
+    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
+    request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+
+    libmemcached_io_vector_st vector[]=
+    {
+      { request.bytes, sizeof(request.bytes) }
+    };
+
+    initialize_binary_request(instance, request.message.header);
+
+    (void)memcached_vdo(instance, vector, 1, false);
+  }
+}
+
+void memcached_version_instance(memcached_instance_st* instance)
+{
+  if (instance)
+  {
+    if (memcached_has_root(instance))
+    {
+      if (memcached_is_fetching_version(instance->root))
+      {
+        if (memcached_is_udp(instance->root) == false)
+        {
+
+          if (memcached_is_binary(instance->root))
+          {
+            version_binary_instance(instance);
+            return;
+          }
+
+          version_ascii_instance(instance);      
+        }
+      }
+    }
+  }
+}
+
+int8_t memcached_version_instance_cmp(memcached_instance_st *instance,
+    uint8_t maj, uint8_t min, uint8_t mic)
+{
+  if (!instance || memcached_server_major_version(instance) == UINT8_MAX) {
+    return INT8_MIN;
+  } else {
+    uint32_t sv, cv;
+
+    sv = memcached_server_micro_version(instance)
+        |memcached_server_minor_version(instance) << 8
+        |memcached_server_major_version(instance) << 16
+        ;
+    cv = mic
+        |min << 8
+        |maj << 16
+        ;
+    if (sv < cv) {
+      return -1;
+    }
+    return sv != cv;
+  }
+}
+
+memcached_return_t memcached_version(memcached_st *shell)
+{
+  Memcached* memc= memcached2Memcached(shell);
+  if (memc)
+  {
+    memcached_return_t rc;
+    if (memcached_failed(rc= initialize_query(memc, true)))
+    {
+      return rc;
+    }
+
+    if (memcached_is_udp(memc))
+    {
+      return MEMCACHED_NOT_SUPPORTED;
+    }
+
+    if (memcached_is_binary(memc))
+    {
+      return memcached_version_binary(memc);
+    }
+
+    return memcached_version_textual(memc);      
+  }
+
+  return MEMCACHED_INVALID_ARGUMENTS;
+}
diff --git a/src/libmemcached/version.hpp b/src/libmemcached/version.hpp
new file mode 100644 (file)
index 0000000..0c16743
--- /dev/null
@@ -0,0 +1,46 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  LibMemcached
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/ All
+ *  rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+  Common include file for libmemached
+*/
+
+#pragma once
+
+void memcached_version_instance(memcached_instance_st*);
+int8_t memcached_version_instance_cmp(memcached_instance_st*,
+    uint8_t maj, uint8_t min, uint8_t mic);
diff --git a/src/libmemcached/virtual_bucket.c b/src/libmemcached/virtual_bucket.c
new file mode 100644 (file)
index 0000000..951881b
--- /dev/null
@@ -0,0 +1,120 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+struct bucket_t {
+  uint32_t master;
+  uint32_t forward;
+};
+
+struct memcached_virtual_bucket_t {
+  bool has_forward;
+  uint32_t size;
+  uint32_t replicas;
+  struct bucket_t buckets[];
+};
+
+memcached_return_t memcached_virtual_bucket_create(memcached_st *self,
+                                                   const uint32_t *host_map,
+                                                   const uint32_t *forward_map,
+                                                   const uint32_t buckets,
+                                                   const uint32_t replicas)
+{
+  if (self == NULL || host_map == NULL || buckets == 0U)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  memcached_virtual_bucket_free(self);
+
+  struct memcached_virtual_bucket_t *virtual_bucket= (struct memcached_virtual_bucket_t *)malloc(sizeof(struct memcached_virtual_bucket_t) + sizeof(struct bucket_t) *buckets);
+  
+  if (virtual_bucket == NULL)
+  {
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+  }
+
+
+  virtual_bucket->size= buckets;
+  virtual_bucket->replicas= replicas;
+  self->virtual_bucket= virtual_bucket;
+
+  uint32_t x= 0;
+  for (; x < buckets; x++)
+  {
+    virtual_bucket->buckets[x].master= host_map[x];
+    if (forward_map)
+    {
+      virtual_bucket->buckets[x].forward= forward_map[x];
+    }
+    else
+    {
+      virtual_bucket->buckets[x].forward= 0;
+    }
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+void memcached_virtual_bucket_free(memcached_st *self)
+{
+  if (self)
+  {
+    if (self->virtual_bucket)
+    {
+      free(self->virtual_bucket);
+      self->virtual_bucket= NULL;
+    }
+  }
+}
+
+uint32_t memcached_virtual_bucket_get(const memcached_st *self, uint32_t digest)
+{
+  if (self)
+  {
+    if (self->virtual_bucket)
+    {
+      uint32_t result= (uint32_t) (digest & (self->virtual_bucket->size -1));
+      return self->virtual_bucket->buckets[result].master;
+    }
+
+    return (uint32_t) (digest & (self->number_of_hosts -1));
+  }
+
+  return 0;
+}
diff --git a/src/libmemcached/virtual_bucket.h b/src/libmemcached/virtual_bucket.h
new file mode 100644 (file)
index 0000000..9a63c38
--- /dev/null
@@ -0,0 +1,56 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+memcached_return_t memcached_virtual_bucket_create(memcached_st *self,
+                                                   const uint32_t *host_map,
+                                                   const uint32_t *forward_map,
+                                                   const uint32_t buckets,
+                                                   const uint32_t replicas);
+
+uint32_t memcached_virtual_bucket_get(const memcached_st *self, uint32_t digest);
+
+void memcached_virtual_bucket_free(memcached_st *self);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/libmemcached/watchpoint.h b/src/libmemcached/watchpoint.h
new file mode 100644 (file)
index 0000000..822101e
--- /dev/null
@@ -0,0 +1,51 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#define WATCHPOINT
+#define WATCHPOINT_ERROR(A)
+#define WATCHPOINT_IFERROR(__memcached_return_t) (void)(__memcached_return_t)
+#define WATCHPOINT_STRING(A)
+#define WATCHPOINT_NUMBER(A)
+#define WATCHPOINT_LABELED_NUMBER(A,B)
+#define WATCHPOINT_IF_LABELED_NUMBER(A,B,C)
+#define WATCHPOINT_ERRNO(A)
+#define WATCHPOINT_ASSERT_PRINT(A,B,C)
+#define WATCHPOINT_ASSERT(A) (void)(A)
+#define WATCHPOINT_ASSERT_INITIALIZED(A)
+#define WATCHPOINT_SET(A)
diff --git a/src/libmemcached/windows.hpp b/src/libmemcached/windows.hpp
new file mode 100644 (file)
index 0000000..40564b1
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Libmemcached library
+ *
+ * Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ *     * The names of its contributors may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+# include <cerrno>
+#else
+# include <errno.h>
+#endif
+
+#ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+#endif
+
+#ifndef _WIN32_WINNT
+# define _WIN32_WINNT 0x0501
+#endif
+
+#ifdef __MINGW32__
+# if(_WIN32_WINNT >= 0x0501)
+# else
+#  undef _WIN32_WINNT
+#  define _WIN32_WINNT 0x0501
+# endif /* _WIN32_WINNT >= 0x0501 */
+#endif /* __MINGW32__ */
+
+#if defined(HAVE_WINSOCK2_H) && HAVE_WINSOCK2_H
+# include <winsock2.h>
+#endif
+
+#if defined(HAVE_WS2TCPIP_H) && HAVE_WS2TCPIP_H
+# include <ws2tcpip.h>
+#endif
+
+#if defined(HAVE_IO_H) && HAVE_IO_H
+# include <io.h>
+#endif
+
+struct sockaddr_un
+{
+  short int sun_family;
+  char sun_path[108];
+};
+
+static inline int translate_windows_error()
+{
+  int local_errno= WSAGetLastError();
+
+  switch(local_errno) {
+  case WSAEINVAL:
+    local_errno= EINPROGRESS;
+    break;
+  case WSAEALREADY:
+  case WSAEWOULDBLOCK:
+    local_errno= EAGAIN;
+    break;
+
+  case WSAECONNREFUSED:
+    local_errno= ECONNREFUSED;
+    break;
+
+  case WSAENETUNREACH:
+    local_errno= ENETUNREACH;
+    break;
+
+  case WSAETIMEDOUT:
+    local_errno= ETIMEDOUT;
+    break;
+
+  case WSAECONNRESET:
+    local_errno= ECONNRESET;
+    break;
+
+  case WSAEADDRINUSE:
+    local_errno= EADDRINUSE;
+    break;
+
+  case WSAEOPNOTSUPP:
+    local_errno= EOPNOTSUPP;
+    break;
+
+  case WSAENOPROTOOPT:
+    local_errno= ENOPROTOOPT;
+    break;
+
+  default:
+    break;
+  }
+
+  return local_errno;
+}
diff --git a/src/libmemcachedprotocol/ascii_handler.c b/src/libmemcachedprotocol/ascii_handler.c
new file mode 100644 (file)
index 0000000..449b650
--- /dev/null
@@ -0,0 +1,1161 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcachedprotocol/common.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+
+static void print_ascii_command(memcached_protocol_client_st *client)
+{
+  if (client->is_verbose)
+  {
+    switch (client->ascii_command)
+    {
+    case SET_CMD:
+      fprintf(stderr, "%s:%d SET_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case ADD_CMD:
+      fprintf(stderr, "%s:%d ADD_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case REPLACE_CMD:
+      fprintf(stderr, "%s:%d REPLACE_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case CAS_CMD:
+      fprintf(stderr, "%s:%d CAS_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case APPEND_CMD:
+      fprintf(stderr, "%s:%d APPEND_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case PREPEND_CMD:
+      fprintf(stderr, "%s:%d PREPEND_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case DELETE_CMD:
+      fprintf(stderr, "%s:%d DELETE_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case INCR_CMD: /* FALLTHROUGH */
+      fprintf(stderr, "%s:%d INCR_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case DECR_CMD:
+      fprintf(stderr, "%s:%d DECR_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case STATS_CMD:
+      fprintf(stderr, "%s:%d STATS_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case FLUSH_ALL_CMD:
+      fprintf(stderr, "%s:%d FLUSH_ALL_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case VERSION_CMD:
+      fprintf(stderr, "%s:%d VERSION_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case QUIT_CMD:
+      fprintf(stderr, "%s:%d QUIT_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case VERBOSITY_CMD:
+      fprintf(stderr, "%s:%d VERBOSITY_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case GET_CMD:
+      fprintf(stderr, "%s:%d GET_CMD\n", __FILE__, __LINE__);
+      break;
+
+    case GETS_CMD:
+      fprintf(stderr, "%s:%d GETS_CMD\n", __FILE__, __LINE__);
+      break;
+
+    default:
+    case UNKNOWN_CMD:
+      fprintf(stderr, "%s:%d UNKNOWN_CMD\n", __FILE__, __LINE__);
+      break;
+
+    }
+  }
+}
+
+/**
+ * Try to parse a key from the string.
+ * @pointer start pointer to a pointer to the string (IN and OUT)
+ * @return length of the string of -1 if this was an illegal key (invalid
+ *         characters or invalid length)
+ * @todo add length!
+ */
+static uint16_t parse_ascii_key(char **start)
+{
+  uint16_t len= 0;
+  char *c= *start;
+  /* Strip leading whitespaces */
+  while (isspace(*c))
+  {
+    ++c;
+  }
+
+  *start= c;
+
+  while (*c != '\0' && !isspace(*c) && !iscntrl(*c))
+  {
+    ++c;
+    ++len;
+  }
+
+
+  if (len == 0 || len > 240 || (*c != '\0' && *c != '\r' && iscntrl(*c)))
+  {
+    return 0;
+  }
+
+  return len;
+}
+
+/**
+ * Spool a zero-terminated string
+ * @param client destination
+ * @param text the text to spool
+ * @return status of the spool operation
+ */
+static protocol_binary_response_status raw_response_handler(memcached_protocol_client_st *client, const char *text)
+{
+  if (client->is_verbose)
+  {
+    fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, text);
+  }
+
+  if (client->root->drain(client) == false)
+  {
+    return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
+  }
+
+  assert(client->output != NULL);
+#if 0
+  if (client->output == NULL)
+  {
+    /* I can write directly to the socket.... */
+    do
+    {
+      size_t num_bytes= len -offset;
+      ssize_t nw= client->root->send(client,
+                                     client->sock,
+                                     ptr + offset,
+                                     num_bytes);
+      if (nw == -1)
+      {
+        if (get_socket_errno() == EWOULDBLOCK)
+        {
+          break;
+        }
+        else if (get_socket_errno() != EINTR)
+        {
+          client->error= errno;
+          return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
+        }
+      }
+      else
+      {
+        offset += (size_t)nw;
+      }
+    } while (offset < len);
+  }
+#endif
+
+  return client->root->spool(client, text, strlen(text));
+}
+
+/**
+ * Send a "CLIENT_ERROR" message back to the client with the correct
+ * format of the command being sent
+ * @param client the client to send the message to
+ */
+static void send_command_usage(memcached_protocol_client_st *client)
+{
+  const char *errmsg[]= {
+    [GET_CMD]= "CLIENT_ERROR: Syntax error: get <key>*\r\n",
+    [GETS_CMD]= "CLIENT_ERROR: Syntax error: gets <key>*\r\n",
+    [SET_CMD]= "CLIENT_ERROR: Syntax error: set <key> <flags> <exptime> <bytes> [noreply]\r\n",
+    [ADD_CMD]= "CLIENT_ERROR: Syntax error: add <key> <flags> <exptime> <bytes> [noreply]\r\n",
+    [REPLACE_CMD]= "CLIENT_ERROR: Syntax error: replace <key> <flags> <exptime> <bytes> [noreply]\r\n",
+    [CAS_CMD]= "CLIENT_ERROR: Syntax error: cas <key> <flags> <exptime> <bytes> <casid> [noreply]\r\n",
+    [APPEND_CMD]= "CLIENT_ERROR: Syntax error: append <key> <flags> <exptime> <bytes> [noreply]\r\n",
+    [PREPEND_CMD]= "CLIENT_ERROR: Syntax error: prepend <key> <flags> <exptime> <bytes> [noreply]\r\n",
+    [DELETE_CMD]= "CLIENT_ERROR: Syntax error: delete_object <key> [noreply]\r\n",
+    [INCR_CMD]= "CLIENT_ERROR: Syntax error: incr <key> <value> [noreply]\r\n",
+    [DECR_CMD]= "CLIENT_ERROR: Syntax error: decr <key> <value> [noreply]\r\n",
+    [STATS_CMD]= "CLIENT_ERROR: Syntax error: stats [key]\r\n",
+    [FLUSH_ALL_CMD]= "CLIENT_ERROR: Syntax error: flush_all [timeout] [noreply]\r\n",
+    [VERSION_CMD]= "CLIENT_ERROR: Syntax error: version\r\n",
+    [QUIT_CMD]="CLIENT_ERROR: Syntax error: quit\r\n",
+
+    [VERBOSITY_CMD]= "CLIENT_ERROR: Syntax error: verbosity <num>\r\n",
+    [UNKNOWN_CMD]= "CLIENT_ERROR: Unknown command\r\n",
+  };
+
+  client->mute = false;
+  raw_response_handler(client, errmsg[client->ascii_command]);
+}
+
+/**
+ * Callback for the VERSION responses
+ * @param cookie client identifier
+ * @param text the length of the body
+ * @param textlen the length of the body
+ */
+static protocol_binary_response_status ascii_version_response_handler(const void *cookie,
+                                                                      const void *text,
+                                                                      uint32_t textlen)
+{
+  memcached_protocol_client_st *client= (memcached_protocol_client_st*)cookie;
+  raw_response_handler(client, "VERSION ");
+  client->root->spool(client, text, textlen);
+  raw_response_handler(client, "\r\n");
+  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Callback for the GET/GETQ/GETK and GETKQ responses
+ * @param cookie client identifier
+ * @param key the key for the item
+ * @param keylen the length of the key
+ * @param body the length of the body
+ * @param bodylen the length of the body
+ * @param flags the flags for the item
+ * @param cas the CAS id for the item
+ */
+static protocol_binary_response_status
+ascii_get_response_handler(const void *cookie,
+                           const void *key,
+                           uint16_t keylen,
+                           const void *body,
+                           uint32_t bodylen,
+                           uint32_t flags,
+                           uint64_t cas)
+{
+  memcached_protocol_client_st *client= (void*)cookie;
+  char buffer[300];
+  strcpy(buffer, "VALUE ");
+  const char *source= key;
+  char *dest= buffer + 6;
+
+  for (int x= 0; x < keylen; ++x)
+  {
+    if (*source != '\0' && !isspace(*source) && !iscntrl(*source))
+    {
+      *dest= *source;
+    }
+    else
+    {
+      return PROTOCOL_BINARY_RESPONSE_EINVAL; /* key constraints in ascii */
+    }
+
+    ++dest;
+    ++source;
+  }
+
+  size_t used= (size_t)(dest - buffer);
+
+  if (client->ascii_command == GETS_CMD)
+  {
+    snprintf(dest, sizeof(buffer) - used, " %u %u %" PRIu64 "\r\n", flags,
+             bodylen, cas);
+  }
+  else
+  {
+    snprintf(dest, sizeof(buffer) - used, " %u %u\r\n", flags, bodylen);
+  }
+
+  client->root->spool(client, buffer, strlen(buffer));
+  client->root->spool(client, body, bodylen);
+  client->root->spool(client, "\r\n", 2);
+
+  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Callback for the STAT responses
+ * @param cookie client identifier
+ * @param key the key for the item
+ * @param keylen the length of the key
+ * @param body the length of the body
+ * @param bodylen the length of the body
+ */
+static protocol_binary_response_status ascii_stat_response_handler(const void *cookie,
+                                                                   const void *key,
+                                                                   uint16_t keylen,
+                                                                   const void *body,
+                                                                   uint32_t bodylen)
+{
+
+  memcached_protocol_client_st *client= (void*)cookie;
+
+  if (key != NULL)
+  {
+    raw_response_handler(client, "STAT ");
+    client->root->spool(client, key, keylen);
+    raw_response_handler(client, " ");
+    client->root->spool(client, body, bodylen);
+    raw_response_handler(client, "\r\n");
+  }
+  else
+  {
+    raw_response_handler(client, "END\r\n");
+  }
+
+  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Process a get or a gets request.
+ * @param client the client handle
+ * @param buffer the complete get(s) command
+ * @param end the last character in the command
+ */
+static void ascii_process_gets(memcached_protocol_client_st *client,
+                               char *buffer, char *end)
+{
+  char *key= buffer;
+
+  /* Skip command */
+  key += (client->ascii_command == GETS_CMD) ? 5 : 4;
+
+  int num_keys= 0;
+  while (key < end)
+  {
+    uint16_t nkey= parse_ascii_key(&key);
+    if (nkey == 0) /* Invalid key... stop processing this line */
+    {
+      break;
+    }
+
+    (void)client->root->callback->interface.v1.get(client, key, nkey,
+                                                   ascii_get_response_handler);
+    key += nkey;
+    ++num_keys;
+  }
+
+  if (num_keys == 0)
+  {
+    send_command_usage(client);
+  }
+  else
+  {
+    client->root->spool(client, "END\r\n", 5);
+  }
+}
+
+/**
+ * Try to split up the command line "asdf asdf asdf asdf\n" into an
+ * argument vector for easier parsing.
+ * @param start the first character in the command line
+ * @param end the last character in the command line ("\n")
+ * @param vec the vector to insert the pointers into
+ * @size the number of elements in the vector
+ * @return the number of tokens in the vector
+ */
+static int ascii_tokenize_command(char *str, char *end, char **vec, int size)
+{
+  int elem= 0;
+
+  while (str < end)
+  {
+    /* Skip leading blanks */
+    while (str < end && isspace(*str))
+    {
+      ++str;
+    }
+
+    if (str == end)
+    {
+      return elem;
+    }
+
+    vec[elem++]= str;
+    /* find the next non-blank field */
+    while (str < end && !isspace(*str))
+    {
+      ++str;
+    }
+
+    /* zero-terminate it for easier parsing later on */
+    *str= '\0';
+    ++str;
+
+    /* Is the vector full? */
+    if (elem == size)
+    {
+      break;
+    }
+  }
+
+  return elem;
+}
+
+/**
+ * If we for some reasons needs to push the line back to read more
+ * data we have to reverse the tokenization. Just do the brain-dead replace
+ * of all '\0' to ' ' and set the last character to '\n'. We could have used
+ * the vector we created, but then we would have to search for all of the
+ * spaces we ignored...
+ * @param start pointer to the first character in the buffer to recover
+ * @param end pointer to the last character in the buffer to recover
+ */
+static void recover_tokenize_command(char *start, char *end)
+{
+  while (start < end)
+  {
+    if (*start == '\0')
+      *start= ' ';
+    ++start;
+  }
+
+  *end= '\n';
+}
+
+/**
+ * Convert the textual command into a comcode
+ */
+static enum ascii_cmd ascii_to_cmd(char *start, size_t length)
+{
+  struct {
+    const char *cmd;
+    size_t len;
+    enum ascii_cmd cc;
+  } commands[]= {
+    { .cmd= "get", .len= 3, .cc= GET_CMD },
+    { .cmd= "gets", .len= 4, .cc= GETS_CMD },
+    { .cmd= "set", .len= 3, .cc= SET_CMD },
+    { .cmd= "add", .len= 3, .cc= ADD_CMD },
+    { .cmd= "replace", .len= 7, .cc= REPLACE_CMD },
+    { .cmd= "cas", .len= 3, .cc= CAS_CMD },
+    { .cmd= "append", .len= 6, .cc= APPEND_CMD },
+    { .cmd= "prepend", .len= 7, .cc= PREPEND_CMD },
+    { .cmd= "delete_object", .len= 6, .cc= DELETE_CMD },
+    { .cmd= "incr", .len= 4, .cc= INCR_CMD },
+    { .cmd= "decr", .len= 4, .cc= DECR_CMD },
+    { .cmd= "stats", .len= 5, .cc= STATS_CMD },
+    { .cmd= "flush_all", .len= 9, .cc= FLUSH_ALL_CMD },
+    { .cmd= "version", .len= 7, .cc= VERSION_CMD },
+    { .cmd= "quit", .len= 4, .cc= QUIT_CMD },
+    { .cmd= "verbosity", .len= 9, .cc= VERBOSITY_CMD },
+    { .cmd= NULL, .len= 0, .cc= UNKNOWN_CMD }};
+
+  int x= 0;
+  while (commands[x].len > 0) {
+    if (length >= commands[x].len)
+    {
+      if (strncmp(start, commands[x].cmd, commands[x].len) == 0)
+      {
+        /* Potential hit */
+        if (length == commands[x].len || isspace(*(start + commands[x].len)))
+        {
+          return commands[x].cc;
+        }
+      }
+    }
+    ++x;
+  }
+
+  return UNKNOWN_CMD;
+}
+
+/**
+ * Perform a delete_object operation.
+ *
+ * @param client client requesting the deletion
+ * @param tokens the command as a vector
+ * @param ntokens the number of items in the vector
+ */
+static void process_delete(memcached_protocol_client_st *client,
+                           char **tokens, int ntokens)
+{
+  char *key= tokens[1];
+  uint16_t nkey;
+
+  if (ntokens != 2 || (nkey= parse_ascii_key(&key)) == 0)
+  {
+    send_command_usage(client);
+    return;
+  }
+
+  if (client->root->callback->interface.v1.delete_object == NULL)
+  {
+    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
+    return;
+  }
+
+  protocol_binary_response_status rval= client->root->callback->interface.v1.delete_object(client, key, nkey, 0);
+
+  if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
+  {
+    raw_response_handler(client, "DELETED\r\n");
+  }
+  else if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT)
+  {
+    raw_response_handler(client, "NOT_FOUND\r\n");
+  }
+  else
+  {
+    char msg[80];
+    snprintf(msg, sizeof(msg), "SERVER_ERROR: delete_object failed %u\r\n",(uint32_t)rval);
+    raw_response_handler(client, msg);
+  }
+}
+
+static void process_arithmetic(memcached_protocol_client_st *client,
+                               char **tokens, int ntokens)
+{
+  char *key= tokens[1];
+  uint16_t nkey;
+
+  if (ntokens != 3 || (nkey= parse_ascii_key(&key)) == 0)
+  {
+    send_command_usage(client);
+    return;
+  }
+
+  uint64_t cas;
+  uint64_t result;
+  errno= 0;
+  uint64_t delta= strtoull(tokens[2], NULL, 10);
+  if (errno != 0)
+  {
+    return; // Error
+  }
+
+  protocol_binary_response_status rval;
+  if (client->ascii_command == INCR_CMD)
+  {
+    if (client->root->callback->interface.v1.increment == NULL)
+    {
+      raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
+      return;
+    }
+    rval= client->root->callback->interface.v1.increment(client,
+                                                         key, nkey,
+                                                         delta, 0,
+                                                         0,
+                                                         &result,
+                                                         &cas);
+  }
+  else
+  {
+    if (client->root->callback->interface.v1.decrement == NULL)
+    {
+      raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
+      return;
+    }
+    rval= client->root->callback->interface.v1.decrement(client,
+                                                         key, nkey,
+                                                         delta, 0,
+                                                         0,
+                                                         &result,
+                                                         &cas);
+  }
+
+  if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
+  {
+    char buffer[80];
+    snprintf(buffer, sizeof(buffer), "%"PRIu64"\r\n", result);
+    raw_response_handler(client, buffer);
+  }
+  else
+  {
+    raw_response_handler(client, "NOT_FOUND\r\n");
+  }
+}
+
+/**
+ * Process the stats command (with or without a key specified)
+ * @param key pointer to the first character after "stats"
+ * @param end pointer to the "\n"
+ */
+static void process_stats(memcached_protocol_client_st *client,
+                          char *key, char *end)
+{
+  if (client->root->callback->interface.v1.stat == NULL)
+  {
+    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
+    return;
+  }
+
+  while (isspace(*key))
+  {
+    key++;
+  }
+
+  uint16_t nkey= (uint16_t)(end - key);
+  (void)client->root->callback->interface.v1.stat(client, key, nkey,
+                                                  ascii_stat_response_handler);
+}
+
+static void process_version(memcached_protocol_client_st *client,
+                            char **tokens, int ntokens)
+{
+  (void)tokens;
+  if (ntokens != 1)
+  {
+    send_command_usage(client);
+    return;
+  }
+
+  if (client->root->callback->interface.v1.version == NULL)
+  {
+    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
+    return;
+  }
+
+ client->root->callback->interface.v1.version(client,
+                                              ascii_version_response_handler);
+}
+
+static void process_flush(memcached_protocol_client_st *client,
+                          char **tokens, int ntokens)
+{
+  if (ntokens > 2)
+  {
+    send_command_usage(client);
+    return;
+  }
+
+  if (client->root->callback->interface.v1.flush_object == NULL)
+  {
+    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
+    return;
+  }
+
+  uint32_t timeout= 0;
+  if (ntokens == 2)
+  {
+    errno= 0;
+    timeout= (uint32_t)strtoul(tokens[1], NULL, 10);
+    if (errno != 0)
+    {
+      return; // Error
+    }
+  }
+
+  protocol_binary_response_status rval;
+  rval= client->root->callback->interface.v1.flush_object(client, timeout);
+  if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
+    raw_response_handler(client, "OK\r\n");
+  else
+    raw_response_handler(client, "SERVER_ERROR: internal error\r\n");
+}
+
+/**
+ * Process one of the storage commands
+ * @param client the client performing the operation
+ * @param tokens the command tokens
+ * @param ntokens the number of tokens
+ * @param start pointer to the first character in the line
+ * @param end pointer to the pointer where the last character of this
+ *            command is (IN and OUT)
+ * @param length the number of bytes available
+ * @return -1 if an error occurs (and we should just terminate the connection
+ *            because we are out of sync)
+ *         0 storage command completed, continue processing
+ *         1 We need more data, so just go ahead and wait for more!
+ */
+static inline int process_storage_command(memcached_protocol_client_st *client,
+                                          char **tokens, int ntokens, char *start,
+                                          char **end, ssize_t length)
+{
+  (void)ntokens; /* already checked */
+  char *key= tokens[1];
+  uint16_t nkey= parse_ascii_key(&key);
+  if (nkey == 0)
+  {
+    /* return error */
+    raw_response_handler(client, "CLIENT_ERROR: bad key\r\n");
+    return -1;
+  }
+
+  errno= 0;
+  uint32_t flags= (uint32_t)strtoul(tokens[2], NULL, 10);
+  if (errno != 0)
+  {
+    /* return error */
+    raw_response_handler(client, "CLIENT_ERROR: bad key\r\n");
+    return -1;
+  }
+
+  uint32_t timeout= (uint32_t)strtoul(tokens[3], NULL, 10);
+  if (errno != 0)
+  {
+    /* return error */
+    raw_response_handler(client, "CLIENT_ERROR: bad key\r\n");
+    return -1;
+  }
+
+  unsigned long nbytes= strtoul(tokens[4], NULL, 10);
+  if (errno != 0)
+  {
+    /* return error */
+    raw_response_handler(client, "CLIENT_ERROR: bad key\r\n");
+    return -1;
+  }
+
+  /* Do we have all data? */
+  unsigned long need= nbytes + (unsigned long)((*end - start) + 1) + 2; /* \n\r\n */
+  if ((ssize_t)need > length)
+  {
+    /* Keep on reading */
+    recover_tokenize_command(start, *end);
+    return 1;
+  }
+
+  void *data= (*end) + 1;
+  uint64_t cas= 0;
+  uint64_t result_cas;
+  protocol_binary_response_status rval;
+  switch (client->ascii_command)
+  {
+  case SET_CMD:
+    rval= client->root->callback->interface.v1.set(client, key,
+                                                   (uint16_t)nkey,
+                                                   data,
+                                                   (uint32_t)nbytes,
+                                                   flags,
+                                                   timeout, cas,
+                                                   &result_cas);
+    break;
+  case ADD_CMD:
+    rval= client->root->callback->interface.v1.add(client, key,
+                                                   (uint16_t)nkey,
+                                                   data,
+                                                   (uint32_t)nbytes,
+                                                   flags,
+                                                   timeout, &result_cas);
+    break;
+  case CAS_CMD:
+    errno= 0;
+    cas= strtoull(tokens[5], NULL, 10);
+    if (errno != 0)
+    {
+      /* return error */
+      raw_response_handler(client, "CLIENT_ERROR: bad key\r\n");
+      return -1;
+    }
+    /* FALLTHROUGH */
+  case REPLACE_CMD:
+    rval= client->root->callback->interface.v1.replace(client, key,
+                                                       (uint16_t)nkey,
+                                                       data,
+                                                       (uint32_t)nbytes,
+                                                       flags,
+                                                       timeout, cas,
+                                                       &result_cas);
+    break;
+  case APPEND_CMD:
+    rval= client->root->callback->interface.v1.append(client, key,
+                                                      (uint16_t)nkey,
+                                                      data,
+                                                      (uint32_t)nbytes,
+                                                      cas,
+                                                      &result_cas);
+    break;
+  case PREPEND_CMD:
+    rval= client->root->callback->interface.v1.prepend(client, key,
+                                                       (uint16_t)nkey,
+                                                       data,
+                                                       (uint32_t)nbytes,
+                                                       cas,
+                                                       &result_cas);
+    break;
+
+    /* gcc complains if I don't put all of the enums in here.. */
+  case GET_CMD:
+  case GETS_CMD:
+  case DELETE_CMD:
+  case DECR_CMD:
+  case INCR_CMD:
+  case STATS_CMD:
+  case FLUSH_ALL_CMD:
+  case VERSION_CMD:
+  case QUIT_CMD:
+  case VERBOSITY_CMD:
+  case UNKNOWN_CMD:
+  default:
+    abort(); /* impossible */
+  }
+
+  if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS)
+  {
+    raw_response_handler(client, "STORED\r\n");
+  }
+  else
+  {
+    if (client->ascii_command == CAS_CMD)
+    {
+      if (rval == PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS)
+      {
+        raw_response_handler(client, "EXISTS\r\n");
+      }
+      else if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT)
+      {
+        raw_response_handler(client, "NOT_FOUND\r\n");
+      }
+      else
+      {
+        raw_response_handler(client, "NOT_STORED\r\n");
+      }
+    }
+    else
+    {
+      raw_response_handler(client, "NOT_STORED\r\n");
+    }
+  }
+
+  *end += nbytes + 2;
+
+  return 0;
+}
+
+static int process_cas_command(memcached_protocol_client_st *client,
+                                char **tokens, int ntokens, char *start,
+                                char **end, ssize_t length)
+{
+  if (ntokens != 6)
+  {
+    send_command_usage(client);
+    return false;
+  }
+
+  if (client->root->callback->interface.v1.replace == NULL)
+  {
+    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
+    return false;
+  }
+
+  return process_storage_command(client, tokens, ntokens, start, end, length);
+}
+
+static int process_set_command(memcached_protocol_client_st *client,
+                                char **tokens, int ntokens, char *start,
+                                char **end, ssize_t length)
+{
+  if (ntokens != 5)
+  {
+    send_command_usage(client);
+    return false;
+  }
+
+  if (client->root->callback->interface.v1.set == NULL)
+  {
+    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
+    return false;
+  }
+
+  return process_storage_command(client, tokens, ntokens, start, end, length);
+}
+
+static int process_add_command(memcached_protocol_client_st *client,
+                                char **tokens, int ntokens, char *start,
+                                char **end, ssize_t length)
+{
+  if (ntokens != 5)
+  {
+    send_command_usage(client);
+    return false;
+  }
+
+  if (client->root->callback->interface.v1.add == NULL)
+  {
+    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
+    return false;
+  }
+
+  return process_storage_command(client, tokens, ntokens, start, end, length);
+}
+
+static int process_replace_command(memcached_protocol_client_st *client,
+                                    char **tokens, int ntokens, char *start,
+                                    char **end, ssize_t length)
+{
+  if (ntokens != 5)
+  {
+    send_command_usage(client);
+    return false;
+  }
+
+  if (client->root->callback->interface.v1.replace == NULL)
+  {
+    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
+    return false;
+  }
+
+  return process_storage_command(client, tokens, ntokens, start, end, length);
+}
+
+static int process_append_command(memcached_protocol_client_st *client,
+                                   char **tokens, int ntokens, char *start,
+                                   char **end, ssize_t length)
+{
+  if (ntokens != 5)
+  {
+    send_command_usage(client);
+    return false;
+  }
+
+  if (client->root->callback->interface.v1.append == NULL)
+  {
+    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
+    return false;
+  }
+
+  return process_storage_command(client, tokens, ntokens, start, end, length);
+}
+
+static int process_prepend_command(memcached_protocol_client_st *client,
+                                    char **tokens, int ntokens, char *start,
+                                    char **end, ssize_t length)
+{
+  if (ntokens != 5)
+  {
+    send_command_usage(client);
+    return false;
+  }
+
+  if (client->root->callback->interface.v1.prepend == NULL)
+  {
+    raw_response_handler(client, "SERVER_ERROR: callback not implemented\r\n");
+    return false;
+  }
+
+  return process_storage_command(client, tokens, ntokens, start, end, length);
+}
+
+/**
+ * The ASCII protocol support is just one giant big hack. Instead of adding
+ * a optimal ascii support, I just convert the ASCII commands to the binary
+ * protocol and calls back into the command handlers for the binary protocol ;)
+ */
+memcached_protocol_event_t memcached_ascii_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr)
+{
+  char *ptr= (char*)client->root->input_buffer;
+  *endptr= ptr;
+
+  do {
+    /* Do we have \n (indicating the command preamble)*/
+    char *end= memchr(ptr, '\n', (size_t)*length);
+    if (end == NULL)
+    {
+      *endptr= ptr;
+      return MEMCACHED_PROTOCOL_READ_EVENT;
+    }
+
+    client->ascii_command= ascii_to_cmd(ptr, (size_t)(*length));
+
+    /* we got all data available, execute the callback! */
+    if (client->root->callback->pre_execute != NULL)
+    {
+      client->root->callback->pre_execute(client, NULL);
+    }
+
+
+    /* A multiget lists all of the keys, and I don't want to have an
+     * avector of let's say 512 pointers to tokenize all of them, so let's
+     * just handle them immediately
+     */
+    if (client->ascii_command == GET_CMD ||
+        client->ascii_command == GETS_CMD)
+    {
+      if (client->root->callback->interface.v1.get != NULL)
+      {
+        ascii_process_gets(client, ptr, end);
+      }
+      else
+      {
+        raw_response_handler(client, "SERVER_ERROR: Command not implemented\n");
+      }
+    }
+    else
+    {
+      /* None of the defined commands takes 10 parameters, so lets just use
+       * that as a maximum limit.
+     */
+      char *tokens[10];
+      int ntokens= ascii_tokenize_command(ptr, end, tokens, 10);
+
+      if (ntokens < 10)
+      {
+        client->mute= strcmp(tokens[ntokens - 1], "noreply") == 0;
+        if (client->mute)
+        {
+          --ntokens; /* processed noreply token*/
+        }
+      }
+
+      int error= 0;
+
+      print_ascii_command(client);
+      switch (client->ascii_command)
+      {
+      case SET_CMD:
+        error= process_set_command(client, tokens, ntokens, ptr, &end, *length);
+        break;
+
+      case ADD_CMD:
+        error= process_add_command(client, tokens, ntokens, ptr, &end, *length);
+        break;
+
+      case REPLACE_CMD:
+        error= process_replace_command(client, tokens, ntokens, ptr, &end, *length);
+        break;
+
+      case CAS_CMD:
+        error= process_cas_command(client, tokens, ntokens, ptr, &end, *length);
+        break;
+
+      case APPEND_CMD:
+        error= process_append_command(client, tokens, ntokens, ptr, &end, *length);
+        break;
+
+      case PREPEND_CMD:
+        error= process_prepend_command(client, tokens, ntokens, ptr, &end, *length);
+        break;
+
+      case DELETE_CMD:
+        process_delete(client, tokens, ntokens);
+        break;
+
+      case INCR_CMD: /* FALLTHROUGH */
+      case DECR_CMD:
+        process_arithmetic(client, tokens, ntokens);
+        break;
+
+      case STATS_CMD:
+        if (client->mute)
+        {
+          send_command_usage(client);
+        }
+        else
+        {
+          recover_tokenize_command(ptr, end);
+          process_stats(client, ptr + 6, end);
+        }
+        break;
+
+      case FLUSH_ALL_CMD:
+        process_flush(client, tokens, ntokens);
+        break;
+
+      case VERSION_CMD:
+        if (client->mute)
+        {
+          send_command_usage(client);
+        }
+        else
+        {
+          process_version(client, tokens, ntokens);
+        }
+        break;
+
+      case QUIT_CMD:
+        if (ntokens != 1 || client->mute)
+        {
+          send_command_usage(client);
+        }
+        else
+        {
+          if (client->root->callback->interface.v1.quit != NULL)
+          {
+            client->root->callback->interface.v1.quit(client);
+          }
+
+          return MEMCACHED_PROTOCOL_ERROR_EVENT;
+        }
+        break;
+
+      case VERBOSITY_CMD:
+        if (ntokens != 2)
+        {
+          send_command_usage(client);
+        }
+        else
+        {
+          raw_response_handler(client, "OK\r\n");
+        }
+        break;
+
+      case UNKNOWN_CMD:
+        send_command_usage(client);
+        break;
+
+      case GET_CMD:
+      case GETS_CMD:
+      default:
+        /* Should already be handled */
+        abort();
+      }
+
+      if (error == -1)
+      {
+        return MEMCACHED_PROTOCOL_ERROR_EVENT;
+      }
+      else if (error == 1)
+      {
+        return MEMCACHED_PROTOCOL_READ_EVENT;
+      }
+    }
+
+    if (client->root->callback->post_execute != NULL)
+    {
+      client->root->callback->post_execute(client, NULL);
+    }
+
+    /* Move past \n */
+    ++end;
+    *length -= end - ptr;
+    ptr= end;
+  } while (*length > 0);
+
+  *endptr= ptr;
+  return MEMCACHED_PROTOCOL_READ_EVENT;
+}
diff --git a/src/libmemcachedprotocol/ascii_handler.h b/src/libmemcachedprotocol/ascii_handler.h
new file mode 100644 (file)
index 0000000..02f8831
--- /dev/null
@@ -0,0 +1,40 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+LIBMEMCACHED_LOCAL
+memcached_protocol_event_t memcached_ascii_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr);
diff --git a/src/libmemcachedprotocol/binary_handler.c b/src/libmemcachedprotocol/binary_handler.c
new file mode 100644 (file)
index 0000000..d720424
--- /dev/null
@@ -0,0 +1,1198 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <libmemcachedprotocol/common.h>
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+
+/*
+** **********************************************************************
+** INTERNAL INTERFACE
+** **********************************************************************
+*/
+
+/**
+ * Send a preformatted packet back to the client. If the connection is in
+ * pedantic mode, it will validate the packet and refuse to send it if it
+ * breaks the specification.
+ *
+ * @param cookie client identification
+ * @param request the original request packet
+ * @param response the packet to send
+ * @return The status of the operation
+ */
+static protocol_binary_response_status raw_response_handler(const void *cookie,
+                                                            protocol_binary_request_header *request,
+                                                            protocol_binary_response_header *response)
+{
+  memcached_protocol_client_st *client= (void*)cookie;
+
+  if (client->root->pedantic &&
+      !memcached_binary_protocol_pedantic_check_response(request, response))
+  {
+    return PROTOCOL_BINARY_RESPONSE_EINVAL;
+  }
+
+  if (client->root->drain(client) == false)
+  {
+    return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
+  }
+
+  size_t len= sizeof(protocol_binary_response_header) + htonl(response->response.bodylen);
+  size_t offset= 0;
+  char *ptr= (void*)response;
+
+  if (client->output == NULL)
+  {
+    /* I can write directly to the socket.... */
+    do
+    {
+      size_t num_bytes= len - offset;
+      ssize_t nw= client->root->send(client,
+                                     client->sock,
+                                     ptr + offset,
+                                     num_bytes);
+      if (nw == -1)
+      {
+        if (get_socket_errno() == EWOULDBLOCK)
+        {
+          break;
+        }
+        else if (get_socket_errno() != EINTR)
+        {
+          client->error= errno;
+          return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
+        }
+      }
+      else
+      {
+        offset += (size_t)nw;
+      }
+    } while (offset < len);
+  }
+
+  return client->root->spool(client, ptr, len - offset);
+}
+
+static void print_cmd(protocol_binary_command cmd)
+{
+  switch (cmd)
+  {
+  case PROTOCOL_BINARY_CMD_GET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GET\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_SET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SET\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_ADD: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_ADD\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_REPLACE: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_REPLACE\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_DELETE: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_DELETE\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_INCREMENT: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_INCREMENT\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_DECREMENT: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_DECREMENT\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_QUIT: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_QUIT\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_FLUSH: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_FLUSH\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_GETQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GETQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_NOOP: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_NOOP\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_VERSION: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_VERSION\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_GETK: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GETK\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_GETKQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GETKQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_APPEND: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_APPEND\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_PREPEND: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_PREPEND\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_STAT: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_STAT\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_SETQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SETQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_ADDQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_ADDQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_REPLACEQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_REPLACEQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_DELETEQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_DELETEQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_INCREMENTQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_INCREMENTQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_DECREMENTQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_DECREMENTQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_QUITQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_QUITQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_FLUSHQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_FLUSHQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_APPENDQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_APPENDQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_PREPENDQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_PREPENDQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_VERBOSITY: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_VERBOSITY\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_TOUCH: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TOUCH\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_GAT: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GAT\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_GATQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GATQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SASL_LIST_MECHS\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_SASL_AUTH: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SASL_AUTH\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_SASL_STEP: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SASL_STEP\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_RGET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RGET\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_RSET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RSET\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_RSETQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RSETQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_RAPPEND: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RAPPEND\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_RAPPENDQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RAPPENDQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_RPREPEND: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RPREPEND\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_RPREPENDQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RPREPENDQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_RDELETE: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RDELETE\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_RDELETEQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RDELETEQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_RINCR: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RINCR\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_RINCRQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RINCRQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_RDECR: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RDECR\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_RDECRQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_RDECRQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_SET_VBUCKET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SET_VBUCKET\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_GET_VBUCKET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GET_VBUCKET\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_DEL_VBUCKET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_DEL_VBUCKET\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_TAP_CONNECT: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_CONNECT\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_TAP_MUTATION: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_MUTATION\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_TAP_DELETE: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_DELETE\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_TAP_FLUSH: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_FLUSH\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_TAP_OPAQUE: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_OPAQUE\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_TAP_VBUCKET_SET: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_VBUCKET_SET\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_START: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_START\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_END: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_TAP_CHECKPOINT_END\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_LAST_RESERVED: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_LAST_RESERVED\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_GATK: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GATK\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_GATKQ: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_GATKQ\n", __FILE__, __LINE__); return;
+  case PROTOCOL_BINARY_CMD_SCRUB: fprintf(stderr, "%s:%d PROTOCOL_BINARY_CMD_SCRUB\n", __FILE__, __LINE__); return;
+  default:
+                                  abort();
+  }
+}
+
+/*
+ * Version 0 of the interface is really low level and protocol specific,
+ * while the version 1 of the interface is more API focused. We need a
+ * way to translate between the command codes on the wire and the
+ * application level interface in V1, so let's just use the V0 of the
+ * interface as a map instead of creating a huuuge switch :-)
+ */
+
+/**
+ * Callback for the GET/GETQ/GETK and GETKQ responses
+ * @param cookie client identifier
+ * @param key the key for the item
+ * @param keylen the length of the key
+ * @param body the length of the body
+ * @param bodylen the length of the body
+ * @param flags the flags for the item
+ * @param cas the CAS id for the item
+ */
+static protocol_binary_response_status get_response_handler(const void *cookie,
+                                                            const void *key,
+                                                            uint16_t keylen,
+                                                            const void *body,
+                                                            uint32_t bodylen,
+                                                            uint32_t flags,
+                                                            uint64_t cas)
+{
+  memcached_protocol_client_st *client= (void*)cookie;
+  uint8_t opcode= client->current_command->request.opcode;
+
+  if (opcode == PROTOCOL_BINARY_CMD_GET || opcode == PROTOCOL_BINARY_CMD_GETQ)
+  {
+    keylen= 0;
+  }
+
+  protocol_binary_response_get response= {
+    .message.header.response= {
+      .magic= PROTOCOL_BINARY_RES,
+      .opcode= opcode,
+      .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+      .opaque= client->current_command->request.opaque,
+      .cas= memcached_htonll(cas),
+      .keylen= htons(keylen),
+      .extlen= 4,
+      .bodylen= htonl(bodylen + keylen + 4),
+    },
+  };
+
+  response.message.body.flags= htonl(flags);
+
+  protocol_binary_response_status rval;
+  const protocol_binary_response_status success= PROTOCOL_BINARY_RESPONSE_SUCCESS;
+  if ((rval= client->root->spool(client, response.bytes, sizeof(response.bytes))) != success ||
+      (rval= client->root->spool(client, key, keylen)) != success ||
+      (rval= client->root->spool(client, body, bodylen)) != success)
+  {
+    return rval;
+  }
+
+  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Callback for the STAT responses
+ * @param cookie client identifier
+ * @param key the key for the item
+ * @param keylen the length of the key
+ * @param body the length of the body
+ * @param bodylen the length of the body
+ */
+static protocol_binary_response_status stat_response_handler(const void *cookie,
+                                                             const void *key,
+                                                             uint16_t keylen,
+                                                             const void *body,
+                                                             uint32_t bodylen)
+{
+
+  memcached_protocol_client_st *client= (void*)cookie;
+
+  protocol_binary_response_no_extras response= {
+    .message.header.response= {
+      .magic= PROTOCOL_BINARY_RES,
+      .opcode= client->current_command->request.opcode,
+      .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+      .opaque= client->current_command->request.opaque,
+      .keylen= htons(keylen),
+      .bodylen= htonl(bodylen + keylen),
+      .cas= 0
+    },
+  };
+
+  protocol_binary_response_status rval;
+  const protocol_binary_response_status success= PROTOCOL_BINARY_RESPONSE_SUCCESS;
+  if ((rval= client->root->spool(client, response.bytes, sizeof(response.bytes))) != success ||
+      (rval= client->root->spool(client, key, keylen)) != success ||
+      (rval= client->root->spool(client, body, bodylen)) != success)
+  {
+    return rval;
+  }
+
+  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Callback for the VERSION responses
+ * @param cookie client identifier
+ * @param text the length of the body
+ * @param textlen the length of the body
+ */
+static protocol_binary_response_status version_response_handler(const void *cookie,
+                                                                const void *text,
+                                                                uint32_t textlen)
+{
+
+  memcached_protocol_client_st *client= (void*)cookie;
+
+  protocol_binary_response_no_extras response= {
+    .message.header.response= {
+      .magic= PROTOCOL_BINARY_RES,
+      .opcode= client->current_command->request.opcode,
+      .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+      .opaque= client->current_command->request.opaque,
+      .bodylen= htonl(textlen),
+      .cas= 0
+    },
+  };
+
+  protocol_binary_response_status rval;
+  const protocol_binary_response_status success= PROTOCOL_BINARY_RESPONSE_SUCCESS;
+  if ((rval= client->root->spool(client, response.bytes, sizeof(response.bytes))) != success ||
+      (rval= client->root->spool(client, text, textlen)) != success)
+  {
+    return rval;
+  }
+
+  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Callback for ADD and ADDQ
+ * @param cookie the calling client
+ * @param header the add/addq command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+add_command_handler(const void *cookie,
+                    protocol_binary_request_header *header,
+                    memcached_binary_protocol_raw_response_handler response_handler)
+{
+  protocol_binary_response_status rval;
+
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.add != NULL)
+  {
+    uint16_t keylen= ntohs(header->request.keylen);
+    uint32_t datalen= ntohl(header->request.bodylen) - keylen - 8;
+    protocol_binary_request_add *request= (void*)header;
+    uint32_t flags= ntohl(request->message.body.flags);
+    uint32_t timeout= ntohl(request->message.body.expiration);
+    char *key= ((char*)header) + sizeof(*header) + 8;
+    char *data= key + keylen;
+    uint64_t cas;
+
+    rval= client->root->callback->interface.v1.add(cookie, key, keylen,
+                                                   data, datalen, flags,
+                                                   timeout, &cas);
+
+    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+        header->request.opcode == PROTOCOL_BINARY_CMD_ADD)
+    {
+      /* Send a positive request */
+      protocol_binary_response_no_extras response= {
+        .message= {
+          .header.response= {
+            .magic= PROTOCOL_BINARY_RES,
+            .opcode= PROTOCOL_BINARY_CMD_ADD,
+            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+            .opaque= header->request.opaque,
+            .cas= memcached_ntohll(cas)
+          }
+        }
+      };
+      rval= response_handler(cookie, header, (void*)&response);
+    }
+  }
+  else
+  {
+    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+  }
+
+  return rval;
+}
+
+/**
+ * Callback for DECREMENT and DECREMENTQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+decrement_command_handler(const void *cookie,
+                          protocol_binary_request_header *header,
+                          memcached_binary_protocol_raw_response_handler response_handler)
+{
+  (void)response_handler;
+  protocol_binary_response_status rval;
+
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.decrement != NULL)
+  {
+    uint16_t keylen= ntohs(header->request.keylen);
+    protocol_binary_request_decr *request= (void*)header;
+    uint64_t init= memcached_ntohll(request->message.body.initial);
+    uint64_t delta= memcached_ntohll(request->message.body.delta);
+    uint32_t timeout= ntohl(request->message.body.expiration);
+    void *key= request->bytes + sizeof(request->bytes);
+    uint64_t result;
+    uint64_t cas;
+
+    rval= client->root->callback->interface.v1.decrement(cookie, key, keylen,
+                                                         delta, init, timeout,
+                                                         &result, &cas);
+    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+        header->request.opcode == PROTOCOL_BINARY_CMD_DECREMENT)
+    {
+      /* Send a positive request */
+      protocol_binary_response_decr response= {
+        .message= {
+          .header.response= {
+            .magic= PROTOCOL_BINARY_RES,
+            .opcode= PROTOCOL_BINARY_CMD_DECREMENT,
+            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+            .opaque= header->request.opaque,
+            .cas= memcached_ntohll(cas),
+            .bodylen= htonl(8)
+          },
+          .body.value= memcached_htonll(result)
+        }
+      };
+      rval= response_handler(cookie, header, (void*)&response);
+    }
+  }
+  else
+  {
+    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+  }
+
+  return rval;
+}
+
+/**
+ * Callback for DELETE and DELETEQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status delete_command_handler(const void *cookie,
+                                                              protocol_binary_request_header *header,
+                                                              memcached_binary_protocol_raw_response_handler response_handler)
+{
+  (void)response_handler;
+  protocol_binary_response_status rval;
+
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.delete_object != NULL)
+  {
+    uint16_t keylen= ntohs(header->request.keylen);
+    void *key= (header +1);
+    uint64_t cas= memcached_ntohll(header->request.cas);
+    rval= client->root->callback->interface.v1.delete_object(cookie, key, keylen, cas);
+    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+        header->request.opcode == PROTOCOL_BINARY_CMD_DELETE)
+    {
+      /* Send a positive request */
+      protocol_binary_response_no_extras response= {
+        .message= {
+          .header.response= {
+            .magic= PROTOCOL_BINARY_RES,
+            .opcode= PROTOCOL_BINARY_CMD_DELETE,
+            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+            .opaque= header->request.opaque,
+          }
+        }
+      };
+      rval= response_handler(cookie, header, (void*)&response);
+    }
+  }
+  else
+  {
+    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+  }
+
+  return rval;
+}
+
+/**
+ * Callback for FLUSH and FLUSHQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+flush_command_handler(const void *cookie,
+                      protocol_binary_request_header *header,
+                      memcached_binary_protocol_raw_response_handler response_handler)
+{
+  (void)response_handler;
+  protocol_binary_response_status rval;
+
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.flush_object != NULL)
+  {
+    protocol_binary_request_flush *flush_object= (void*)header;
+    uint32_t timeout= 0;
+    if (htonl(header->request.bodylen) == 4)
+    {
+      timeout= ntohl(flush_object->message.body.expiration);
+    }
+
+    rval= client->root->callback->interface.v1.flush_object(cookie, timeout);
+    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+        header->request.opcode == PROTOCOL_BINARY_CMD_FLUSH)
+    {
+      /* Send a positive request */
+      protocol_binary_response_no_extras response= {
+        .message= {
+          .header.response= {
+            .magic= PROTOCOL_BINARY_RES,
+            .opcode= PROTOCOL_BINARY_CMD_FLUSH,
+            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+            .opaque= header->request.opaque,
+          }
+        }
+      };
+      rval= response_handler(cookie, header, (void*)&response);
+    }
+  }
+  else
+  {
+    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+  }
+
+  return rval;
+}
+
+/**
+ * Callback for GET, GETK, GETQ, GETKQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+get_command_handler(const void *cookie,
+                    protocol_binary_request_header *header,
+                    memcached_binary_protocol_raw_response_handler response_handler)
+{
+  (void)response_handler;
+  protocol_binary_response_status rval;
+
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.get != NULL)
+  {
+    uint16_t keylen= ntohs(header->request.keylen);
+    void *key= (header + 1);
+    rval= client->root->callback->interface.v1.get(cookie, key, keylen,
+                                                   get_response_handler);
+
+    if (rval == PROTOCOL_BINARY_RESPONSE_KEY_ENOENT &&
+        (header->request.opcode == PROTOCOL_BINARY_CMD_GETQ ||
+         header->request.opcode == PROTOCOL_BINARY_CMD_GETKQ))
+    {
+      /* Quiet commands shouldn't respond on cache misses */
+      rval= PROTOCOL_BINARY_RESPONSE_SUCCESS;
+    }
+  }
+  else
+  {
+    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+  }
+
+  return rval;
+}
+
+/**
+ * Callback for INCREMENT and INCREMENTQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+increment_command_handler(const void *cookie,
+                          protocol_binary_request_header *header,
+                          memcached_binary_protocol_raw_response_handler response_handler)
+{
+  (void)response_handler;
+  protocol_binary_response_status rval;
+
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.increment != NULL)
+  {
+    uint16_t keylen= ntohs(header->request.keylen);
+    protocol_binary_request_incr *request= (void*)header;
+    uint64_t init= memcached_ntohll(request->message.body.initial);
+    uint64_t delta= memcached_ntohll(request->message.body.delta);
+    uint32_t timeout= ntohl(request->message.body.expiration);
+    void *key= request->bytes + sizeof(request->bytes);
+    uint64_t cas;
+    uint64_t result;
+
+    rval= client->root->callback->interface.v1.increment(cookie, key, keylen,
+                                                         delta, init, timeout,
+                                                         &result, &cas);
+    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+        header->request.opcode == PROTOCOL_BINARY_CMD_INCREMENT)
+    {
+      /* Send a positive request */
+      protocol_binary_response_incr response= {
+        .message= {
+          .header.response= {
+            .magic= PROTOCOL_BINARY_RES,
+            .opcode= PROTOCOL_BINARY_CMD_INCREMENT,
+            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+            .opaque= header->request.opaque,
+            .cas= memcached_ntohll(cas),
+            .bodylen= htonl(8)
+          },
+          .body.value= memcached_htonll(result)
+        }
+      };
+
+      rval= response_handler(cookie, header, (void*)&response);
+    }
+  }
+  else
+  {
+    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+  }
+
+  return rval;
+}
+
+/**
+ * Callback for noop. Inform the v1 interface about the noop packet, and
+ * create and send a packet back to the client
+ *
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler the response handler
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+noop_command_handler(const void *cookie,
+                     protocol_binary_request_header *header,
+                     memcached_binary_protocol_raw_response_handler response_handler)
+{
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.noop != NULL)
+  {
+    client->root->callback->interface.v1.noop(cookie);
+  }
+
+  protocol_binary_response_no_extras response= {
+    .message= {
+      .header.response= {
+        .magic= PROTOCOL_BINARY_RES,
+        .opcode= PROTOCOL_BINARY_CMD_NOOP,
+        .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+        .opaque= header->request.opaque,
+      }
+    }
+  };
+
+  return response_handler(cookie, header, (void*)&response);
+}
+
+/**
+ * Callback for APPEND and APPENDQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+append_command_handler(const void *cookie,
+                       protocol_binary_request_header *header,
+                       memcached_binary_protocol_raw_response_handler response_handler)
+{
+  (void)response_handler;
+  protocol_binary_response_status rval;
+
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.append != NULL)
+  {
+    uint16_t keylen= ntohs(header->request.keylen);
+    uint32_t datalen= ntohl(header->request.bodylen) - keylen;
+    char *key= (void*)(header +1);
+    char *data= key +keylen;
+    uint64_t cas= memcached_ntohll(header->request.cas);
+    uint64_t result_cas;
+
+    rval= client->root->callback->interface.v1.append(cookie, key, keylen,
+                                                      data, datalen, cas,
+                                                      &result_cas);
+    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+        header->request.opcode == PROTOCOL_BINARY_CMD_APPEND)
+    {
+      /* Send a positive request */
+      protocol_binary_response_no_extras response= {
+        .message= {
+          .header.response= {
+            .magic= PROTOCOL_BINARY_RES,
+            .opcode= PROTOCOL_BINARY_CMD_APPEND,
+            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+            .opaque= header->request.opaque,
+            .cas= memcached_ntohll(result_cas),
+          },
+        }
+      };
+      rval= response_handler(cookie, header, (void*)&response);
+    }
+  }
+  else
+  {
+    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+  }
+
+  return rval;
+}
+
+/**
+ * Callback for PREPEND and PREPENDQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+prepend_command_handler(const void *cookie,
+                        protocol_binary_request_header *header,
+                        memcached_binary_protocol_raw_response_handler response_handler)
+{
+  (void)response_handler;
+  protocol_binary_response_status rval;
+
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.prepend != NULL)
+  {
+    uint16_t keylen= ntohs(header->request.keylen);
+    uint32_t datalen= ntohl(header->request.bodylen) - keylen;
+    char *key= (char*)(header + 1);
+    char *data= key + keylen;
+    uint64_t cas= memcached_ntohll(header->request.cas);
+    uint64_t result_cas;
+    rval= client->root->callback->interface.v1.prepend(cookie, key, keylen,
+                                                       data, datalen, cas,
+                                                       &result_cas);
+    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+        header->request.opcode == PROTOCOL_BINARY_CMD_PREPEND)
+    {
+      /* Send a positive request */
+      protocol_binary_response_no_extras response= {
+        .message= {
+          .header.response= {
+            .magic= PROTOCOL_BINARY_RES,
+            .opcode= PROTOCOL_BINARY_CMD_PREPEND,
+            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+            .opaque= header->request.opaque,
+            .cas= memcached_ntohll(result_cas),
+          },
+        }
+      };
+      rval= response_handler(cookie, header, (void*)&response);
+    }
+  }
+  else
+  {
+    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+  }
+
+  return rval;
+}
+
+/**
+ * Callback for QUIT and QUITQ. Notify the client and shut down the connection
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+quit_command_handler(const void *cookie,
+                     protocol_binary_request_header *header,
+                     memcached_binary_protocol_raw_response_handler response_handler)
+{
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.quit != NULL)
+  {
+    client->root->callback->interface.v1.quit(cookie);
+  }
+
+  protocol_binary_response_no_extras response= {
+    .message= {
+      .header.response= {
+        .magic= PROTOCOL_BINARY_RES,
+        .opcode= PROTOCOL_BINARY_CMD_QUIT,
+        .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+        .opaque= header->request.opaque
+      }
+    }
+  };
+
+  if (header->request.opcode == PROTOCOL_BINARY_CMD_QUIT)
+  {
+    response_handler(cookie, header, (void*)&response);
+  }
+
+  /* I need a better way to signal to close the connection */
+  return PROTOCOL_BINARY_RESPONSE_EINTERNAL;
+}
+
+/**
+ * Callback for REPLACE and REPLACEQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+replace_command_handler(const void *cookie,
+                        protocol_binary_request_header *header,
+                        memcached_binary_protocol_raw_response_handler response_handler)
+{
+  (void)response_handler;
+  protocol_binary_response_status rval;
+
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.replace != NULL)
+  {
+    uint16_t keylen= ntohs(header->request.keylen);
+    uint32_t datalen= ntohl(header->request.bodylen) - keylen - 8;
+    protocol_binary_request_replace *request= (void*)header;
+    uint32_t flags= ntohl(request->message.body.flags);
+    uint32_t timeout= ntohl(request->message.body.expiration);
+    char *key= ((char*)header) + sizeof(*header) + 8;
+    char *data= key + keylen;
+    uint64_t cas= memcached_ntohll(header->request.cas);
+    uint64_t result_cas;
+
+    rval= client->root->callback->interface.v1.replace(cookie, key, keylen,
+                                                       data, datalen, flags,
+                                                       timeout, cas,
+                                                       &result_cas);
+    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+        header->request.opcode == PROTOCOL_BINARY_CMD_REPLACE)
+    {
+      /* Send a positive request */
+      protocol_binary_response_no_extras response= {
+        .message= {
+          .header.response= {
+            .magic= PROTOCOL_BINARY_RES,
+            .opcode= PROTOCOL_BINARY_CMD_REPLACE,
+            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+            .opaque= header->request.opaque,
+            .cas= memcached_ntohll(result_cas),
+          },
+        }
+      };
+      rval= response_handler(cookie, header, (void*)&response);
+    }
+  }
+  else
+  {
+    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+  }
+
+  return rval;
+}
+
+/**
+ * Callback for SET and SETQ
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status set_command_handler(const void *cookie,
+                                                           protocol_binary_request_header *header,
+                                                           memcached_binary_protocol_raw_response_handler response_handler)
+{
+  (void)response_handler;
+  protocol_binary_response_status rval;
+
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.set != NULL)
+  {
+    uint16_t keylen= ntohs(header->request.keylen);
+    uint32_t datalen= ntohl(header->request.bodylen) - keylen - 8;
+    protocol_binary_request_replace *request= (void*)header;
+    uint32_t flags= ntohl(request->message.body.flags);
+    uint32_t timeout= ntohl(request->message.body.expiration);
+    char *key= ((char*)header) + sizeof(*header) + 8;
+    char *data= key + keylen;
+    uint64_t cas= memcached_ntohll(header->request.cas);
+    uint64_t result_cas;
+
+
+    rval= client->root->callback->interface.v1.set(cookie, key, keylen,
+                                                   data, datalen, flags,
+                                                   timeout, cas, &result_cas);
+    if (rval == PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+        header->request.opcode == PROTOCOL_BINARY_CMD_SET)
+    {
+      /* Send a positive request */
+      protocol_binary_response_no_extras response= {
+        .message= {
+          .header.response= {
+            .magic= PROTOCOL_BINARY_RES,
+            .opcode= PROTOCOL_BINARY_CMD_SET,
+            .status= htons(PROTOCOL_BINARY_RESPONSE_SUCCESS),
+            .opaque= header->request.opaque,
+            .cas= memcached_ntohll(result_cas),
+          },
+        }
+      };
+      rval= response_handler(cookie, header, (void*)&response);
+    }
+  }
+  else
+  {
+    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+  }
+
+  return rval;
+}
+
+/**
+ * Callback for STAT
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+stat_command_handler(const void *cookie,
+                     protocol_binary_request_header *header,
+                     memcached_binary_protocol_raw_response_handler response_handler)
+{
+  (void)response_handler;
+  protocol_binary_response_status rval;
+
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.stat != NULL)
+  {
+    uint16_t keylen= ntohs(header->request.keylen);
+
+    rval= client->root->callback->interface.v1.stat(cookie,
+                                                    (void*)(header + 1),
+                                                    keylen,
+                                                    stat_response_handler);
+  }
+  else
+  {
+    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+  }
+
+  return rval;
+}
+
+/**
+ * Callback for VERSION
+ * @param cookie the calling client
+ * @param header the command
+ * @param response_handler not used
+ * @return the result of the operation
+ */
+static protocol_binary_response_status
+version_command_handler(const void *cookie,
+                        protocol_binary_request_header *header,
+                        memcached_binary_protocol_raw_response_handler response_handler)
+{
+  (void)response_handler;
+  (void)header;
+  protocol_binary_response_status rval;
+
+  memcached_protocol_client_st *client= (void*)cookie;
+  if (client->root->callback->interface.v1.version != NULL)
+  {
+    rval= client->root->callback->interface.v1.version(cookie,
+                                                       version_response_handler);
+  }
+  else
+  {
+    rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+  }
+
+  return rval;
+}
+
+/**
+ * The map to remap between the com codes and the v1 logical setting
+ */
+static memcached_binary_protocol_command_handler comcode_v0_v1_remap[256]= {
+  [PROTOCOL_BINARY_CMD_ADDQ]= add_command_handler,
+  [PROTOCOL_BINARY_CMD_ADD]= add_command_handler,
+  [PROTOCOL_BINARY_CMD_APPENDQ]= append_command_handler,
+  [PROTOCOL_BINARY_CMD_APPEND]= append_command_handler,
+  [PROTOCOL_BINARY_CMD_DECREMENTQ]= decrement_command_handler,
+  [PROTOCOL_BINARY_CMD_DECREMENT]= decrement_command_handler,
+  [PROTOCOL_BINARY_CMD_DELETEQ]= delete_command_handler,
+  [PROTOCOL_BINARY_CMD_DELETE]= delete_command_handler,
+  [PROTOCOL_BINARY_CMD_FLUSHQ]= flush_command_handler,
+  [PROTOCOL_BINARY_CMD_FLUSH]= flush_command_handler,
+  [PROTOCOL_BINARY_CMD_GETKQ]= get_command_handler,
+  [PROTOCOL_BINARY_CMD_GETK]= get_command_handler,
+  [PROTOCOL_BINARY_CMD_GETQ]= get_command_handler,
+  [PROTOCOL_BINARY_CMD_GET]= get_command_handler,
+  [PROTOCOL_BINARY_CMD_INCREMENTQ]= increment_command_handler,
+  [PROTOCOL_BINARY_CMD_INCREMENT]= increment_command_handler,
+  [PROTOCOL_BINARY_CMD_NOOP]= noop_command_handler,
+  [PROTOCOL_BINARY_CMD_PREPENDQ]= prepend_command_handler,
+  [PROTOCOL_BINARY_CMD_PREPEND]= prepend_command_handler,
+  [PROTOCOL_BINARY_CMD_QUITQ]= quit_command_handler,
+  [PROTOCOL_BINARY_CMD_QUIT]= quit_command_handler,
+  [PROTOCOL_BINARY_CMD_REPLACEQ]= replace_command_handler,
+  [PROTOCOL_BINARY_CMD_REPLACE]= replace_command_handler,
+  [PROTOCOL_BINARY_CMD_SETQ]= set_command_handler,
+  [PROTOCOL_BINARY_CMD_SET]= set_command_handler,
+  [PROTOCOL_BINARY_CMD_STAT]= stat_command_handler,
+  [PROTOCOL_BINARY_CMD_VERSION]= version_command_handler,
+};
+
+/**
+ * Try to execute a command. Fire the pre/post functions and the specialized
+ * handler function if it's set. If not, the unknown probe should be fired
+ * if it's present.
+ * @param client the client connection to operate on
+ * @param header the command to execute
+ * @return true if success or false if a fatal error occured so that the
+ *         connection should be shut down.
+ */
+static protocol_binary_response_status execute_command(memcached_protocol_client_st *client, protocol_binary_request_header *header)
+{
+  if (client->root->pedantic &&
+      memcached_binary_protocol_pedantic_check_request(header))
+  {
+      /* @todo return invalid command packet */
+  }
+
+  /* we got all data available, execute the callback! */
+  if (client->root->callback->pre_execute != NULL)
+  {
+    client->root->callback->pre_execute(client, header);
+  }
+
+  protocol_binary_response_status rval= PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND;
+  uint8_t cc= header->request.opcode;
+
+  if (client->is_verbose)
+  {
+    print_cmd(cc);
+  }
+
+  switch (client->root->callback->interface_version)
+  {
+  case 0:
+    if (client->root->callback->interface.v0.comcode[cc] != NULL)
+    {
+      rval= client->root->callback->interface.v0.comcode[cc](client, header, raw_response_handler);
+    }
+    break;
+
+  case 1:
+    if (comcode_v0_v1_remap[cc] != NULL)
+    {
+      rval= comcode_v0_v1_remap[cc](client, header, raw_response_handler);
+    }
+    break;
+
+  default:
+    /* Unknown interface.
+     * It should be impossible to get here so I'll just call abort
+     * to avoid getting a compiler warning :-)
+     */
+    abort();
+  }
+
+
+  if (rval == PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND &&
+      client->root->callback->unknown != NULL)
+  {
+    rval= client->root->callback->unknown(client, header, raw_response_handler);
+  }
+
+  if (rval != PROTOCOL_BINARY_RESPONSE_SUCCESS &&
+      rval != PROTOCOL_BINARY_RESPONSE_EINTERNAL &&
+      rval != PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED)
+  {
+    protocol_binary_response_no_extras response= {
+      .message= {
+        .header.response= {
+          .magic= PROTOCOL_BINARY_RES,
+          .opcode= cc,
+          .status= htons(rval),
+          .opaque= header->request.opaque,
+        },
+      }
+    };
+    rval= raw_response_handler(client, header, (void*)&response);
+  }
+
+  if (client->root->callback->post_execute != NULL)
+  {
+    client->root->callback->post_execute(client, header);
+  }
+
+  return rval;
+}
+
+/*
+** **********************************************************************
+** "PROTOECTED" INTERFACE
+** **********************************************************************
+*/
+memcached_protocol_event_t memcached_binary_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr)
+{
+  /* try to parse all of the received packets */
+  protocol_binary_request_header *header;
+  header= (void*)client->root->input_buffer;
+  if (header->request.magic != (uint8_t)PROTOCOL_BINARY_REQ)
+  {
+    client->error= EINVAL;
+    return MEMCACHED_PROTOCOL_ERROR_EVENT;
+  }
+  ssize_t len= *length;
+
+  while (len >= (ssize_t)sizeof(*header) &&
+         (len >= (ssize_t)(sizeof(*header) + ntohl(header->request.bodylen))))
+  {
+    /* I have the complete package */
+    client->current_command= header;
+    protocol_binary_response_status rv= execute_command(client, header);
+
+    if (rv == PROTOCOL_BINARY_RESPONSE_EINTERNAL)
+    {
+      *length= len;
+      *endptr= (void*)header;
+      return MEMCACHED_PROTOCOL_ERROR_EVENT;
+    }
+    else if (rv == PROTOCOL_BINARY_RESPONSE_NOT_SUPPORTED)
+    {
+      return MEMCACHED_PROTOCOL_PAUSE_EVENT;
+    }
+
+    ssize_t total= (ssize_t)(sizeof(*header) + ntohl(header->request.bodylen));
+    len -= total;
+    if (len > 0)
+    {
+      intptr_t ptr= (intptr_t)header;
+      ptr += total;
+      if ((ptr % 8) == 0)
+      {
+        header= (void*)ptr;
+      }
+      else
+      {
+        /* Fix alignment */
+        memmove(client->root->input_buffer, (void*)ptr, (size_t)len);
+        header= (void*)client->root->input_buffer;
+      }
+    }
+    *length= len;
+    *endptr= (void*)header;
+  }
+
+  return MEMCACHED_PROTOCOL_READ_EVENT;
+}
+
+/*
+** **********************************************************************
+** PUBLIC INTERFACE
+** **********************************************************************
+*/
+memcached_binary_protocol_callback_st *memcached_binary_protocol_get_callbacks(memcached_protocol_st *instance)
+{
+  return instance->callback;
+}
+
+void memcached_binary_protocol_set_callbacks(memcached_protocol_st *instance, memcached_binary_protocol_callback_st *callback)
+{
+  instance->callback= callback;
+}
+
+memcached_binary_protocol_raw_response_handler memcached_binary_protocol_get_raw_response_handler(const void *cookie)
+{
+  (void)cookie;
+  return raw_response_handler;
+}
+
+void memcached_binary_protocol_set_pedantic(memcached_protocol_st *instance, bool enable)
+{
+  instance->pedantic= enable;
+}
+
+bool memcached_binary_protocol_get_pedantic(memcached_protocol_st *instance)
+{
+  return instance->pedantic;
+}
+
diff --git a/src/libmemcachedprotocol/binary_handler.h b/src/libmemcachedprotocol/binary_handler.h
new file mode 100644 (file)
index 0000000..d5a74e7
--- /dev/null
@@ -0,0 +1,47 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+LIBMEMCACHED_LOCAL
+bool memcached_binary_protocol_pedantic_check_request(const protocol_binary_request_header *request);
+
+LIBMEMCACHED_LOCAL
+bool memcached_binary_protocol_pedantic_check_response(const protocol_binary_request_header *request,
+                                                       const protocol_binary_response_header *response);
+
+LIBMEMCACHED_LOCAL
+memcached_protocol_event_t memcached_binary_protocol_process_data(memcached_protocol_client_st *client, ssize_t *length, void **endptr);
diff --git a/src/libmemcachedprotocol/cache.c b/src/libmemcachedprotocol/cache.c
new file mode 100644 (file)
index 0000000..67c72ea
--- /dev/null
@@ -0,0 +1,189 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+#include "mem_config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+
+#ifndef NDEBUG
+#include <signal.h>
+#endif
+
+#include <libmemcachedprotocol/common.h>
+
+#ifndef NDEBUG
+const uint64_t redzone_pattern = 0xdeadbeefcafebabe;
+int cache_error = 0;
+#endif
+
+const size_t initial_pool_size = 64;
+
+cache_t* cache_create(const char *name, size_t bufsize, size_t align,
+                      cache_constructor_t* constructor,
+                      cache_destructor_t* destructor) {
+    cache_t* ret = calloc(1, sizeof(cache_t));
+    size_t name_length= strlen(name);
+    char* nm= calloc(1, (sizeof(char) * name_length) +1);
+    memcpy(nm, name, name_length);
+    void** ptr = calloc(initial_pool_size, bufsize);
+    if (ret == NULL || nm == NULL || ptr == NULL ||
+        pthread_mutex_init(&ret->mutex, NULL) == -1) {
+        free(ret);
+        free(nm);
+        free(ptr);
+        return NULL;
+    }
+
+    ret->name = nm;
+    ret->ptr = ptr;
+    ret->freetotal = initial_pool_size;
+    ret->constructor = constructor;
+    ret->destructor = destructor;
+
+#ifndef NDEBUG
+    ret->bufsize = bufsize + 2 * sizeof(redzone_pattern);
+#else
+    ret->bufsize = bufsize;
+#endif
+
+    (void)align;
+
+    return ret;
+}
+
+static inline void* get_object(void *ptr) {
+#ifndef NDEBUG
+    uint64_t *pre = ptr;
+    return pre + 1;
+#else
+    return ptr;
+#endif
+}
+
+void cache_destroy(cache_t *cache) {
+    while (cache->freecurr > 0) {
+        void *ptr = cache->ptr[--cache->freecurr];
+        if (cache->destructor) {
+            cache->destructor(get_object(ptr), NULL);
+        }
+        free(ptr);
+    }
+    free(cache->name);
+    free(cache->ptr);
+    pthread_mutex_destroy(&cache->mutex);
+}
+
+void* cache_alloc(cache_t *cache) {
+    void *ret;
+    void *object;
+    pthread_mutex_lock(&cache->mutex);
+    if (cache->freecurr > 0) {
+        ret = cache->ptr[--cache->freecurr];
+        object = get_object(ret);
+    } else {
+        object = ret = malloc(cache->bufsize);
+        if (ret != NULL) {
+            object = get_object(ret);
+
+            if (cache->constructor != NULL &&
+                cache->constructor(object, NULL, 0) != 0) {
+                free(ret);
+                object = NULL;
+            }
+        }
+    }
+    pthread_mutex_unlock(&cache->mutex);
+
+#ifndef NDEBUG
+    if (object != NULL) {
+        /* add a simple form of buffer-check */
+        uint64_t *pre = ret;
+        *pre = redzone_pattern;
+        ret = pre+1;
+        memcpy(((char*)ret) + cache->bufsize - (2 * sizeof(redzone_pattern)),
+               &redzone_pattern, sizeof(redzone_pattern));
+    }
+#endif
+
+    return object;
+}
+
+void cache_free(cache_t *cache, void *ptr) {
+    pthread_mutex_lock(&cache->mutex);
+
+#ifndef NDEBUG
+    /* validate redzone... */
+    if (memcmp(((char*)ptr) + cache->bufsize - (2 * sizeof(redzone_pattern)),
+               &redzone_pattern, sizeof(redzone_pattern)) != 0) {
+        raise(SIGABRT);
+        cache_error = 1;
+        pthread_mutex_unlock(&cache->mutex);
+        return;
+    }
+    uint64_t *pre = ptr;
+    --pre;
+    if (*pre != redzone_pattern) {
+        raise(SIGABRT);
+        cache_error = -1;
+        pthread_mutex_unlock(&cache->mutex);
+        return;
+    }
+    ptr = pre;
+#endif
+    if (cache->freecurr < cache->freetotal) {
+        cache->ptr[cache->freecurr++] = ptr;
+    } else {
+        /* try to enlarge free connections array */
+        size_t newtotal = cache->freetotal * 2;
+        void **new_free = realloc(cache->ptr, sizeof(char *) * newtotal);
+        if (new_free) {
+            cache->freetotal = newtotal;
+            cache->ptr = new_free;
+            cache->ptr[cache->freecurr++] = ptr;
+        } else {
+            if (cache->destructor) {
+                cache->destructor(ptr, NULL);
+            }
+            free(ptr);
+
+        }
+    }
+    pthread_mutex_unlock(&cache->mutex);
+}
+
diff --git a/src/libmemcachedprotocol/cache.h b/src/libmemcachedprotocol/cache.h
new file mode 100644 (file)
index 0000000..6f84fea
--- /dev/null
@@ -0,0 +1,148 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+#pragma once
+
+#include <pthread.h>
+
+#ifdef HAVE_UMEM_H
+# include <umem.h>
+# define cache_t umem_cache_t
+# define cache_alloc(a) umem_cache_alloc(a, UMEM_DEFAULT)
+# define cache_free(a, b) umem_cache_free(a, b)
+# define cache_create(a,b,c,d,e) umem_cache_create((char*)a, b, c, d, e, NULL, NULL, NULL, 0)
+# define cache_destroy(a) umem_cache_destroy(a);
+#else
+# ifndef NDEBUG
+/* may be used for debug purposes */
+extern int cache_error;
+# endif
+
+/**
+ * Constructor used to initialize allocated objects
+ *
+ * @param obj pointer to the object to initialized.
+ * @param notused1 This parameter is currently not used.
+ * @param notused2 This parameter is currently not used.
+ * @return you should return 0, but currently this is not checked
+ */
+typedef int cache_constructor_t(void* obj, void* notused1, int notused2);
+/**
+ * Destructor used to clean up allocated objects before they are
+ * returned to the operating system.
+ *
+ * @param obj pointer to the object to initialized.
+ * @param notused1 This parameter is currently not used.
+ * @param notused2 This parameter is currently not used.
+ * @return you should return 0, but currently this is not checked
+ */
+typedef void cache_destructor_t(void* obj, void* notused);
+
+/**
+ * Definition of the structure to keep track of the internal details of
+ * the cache allocator. Touching any of these variables results in
+ * undefined behavior.
+ */
+typedef struct {
+    /** Mutex to protect access to the structure */
+    pthread_mutex_t mutex;
+    /** Name of the cache objects in this cache (provided by the caller) */
+    char *name;
+    /** List of pointers to available buffers in this cache */
+    void **ptr;
+    /** The size of each element in this cache */
+    size_t bufsize;
+    /** The capacity of the list of elements */
+    size_t freetotal;
+    /** The current number of free elements */
+    size_t freecurr;
+    /** The constructor to be called each time we allocate more memory */
+    cache_constructor_t* constructor;
+    /** The destructor to be called each time before we release memory */
+    cache_destructor_t* destructor;
+} cache_t;
+
+/**
+ * Create an object cache.
+ *
+ * The object cache will let you allocate objects of the same size. It is fully
+ * MT safe, so you may allocate objects from multiple threads without having to
+ * do any syncrhonization in the application code.
+ *
+ * @param name the name of the object cache. This name may be used for debug purposes
+ *             and may help you track down what kind of object you have problems with
+ *             (buffer overruns, leakage etc)
+ * @param bufsize the size of each object in the cache
+ * @param align the alignment requirements of the objects in the cache.
+ * @param constructor the function to be called to initialize memory when we need
+ *                    to allocate more memory from the os.
+ * @param destructor the function to be called before we release the memory back
+ *                   to the os.
+ * @return a handle to an object cache if successful, NULL otherwise.
+ */
+cache_t* cache_create(const char* name, size_t bufsize, size_t align,
+                      cache_constructor_t* constructor,
+                      cache_destructor_t* destructor);
+/**
+ * Destroy an object cache.
+ *
+ * Destroy and invalidate an object cache. You should return all buffers allocated
+ * with cache_alloc by using cache_free before calling this function. Not doing
+ * so results in undefined behavior (the buffers may or may not be invalidated)
+ *
+ * @param handle the handle to the object cache to destroy.
+ */
+void cache_destroy(cache_t* handle);
+/**
+ * Allocate an object from the cache.
+ *
+ * @param handle the handle to the object cache to allocate from
+ * @return a pointer to an initialized object from the cache, or NULL if
+ *         the allocation cannot be satisfied.
+ */
+void* cache_alloc(cache_t* handle);
+/**
+ * Return an object back to the cache.
+ *
+ * The caller should return the object in an initialized state so that
+ * the object may be returned in an expected state from cache_alloc.
+ *
+ * @param handle handle to the object cache to return the object to
+ * @param ptr pointer to the object to return.
+ */
+void cache_free(cache_t* handle, void* ptr);
+#endif //  HAVE_UMEM_H
diff --git a/src/libmemcachedprotocol/common.h b/src/libmemcachedprotocol/common.h
new file mode 100644 (file)
index 0000000..a4ddc2c
--- /dev/null
@@ -0,0 +1,162 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include "mem_config.h"
+#include <assert.h>
+
+#include <libmemcachedprotocol-0.0/handler.h>
+#include <libmemcachedprotocol/cache.h>
+#include <libmemcached/byteorder.h>
+#include <libmemcached/socket.hpp>
+
+/*
+ * I don't really need the following two functions as function pointers
+ * in the instance handle, but I don't want to put them in the global
+ * namespace for those linking statically (personally I don't like that,
+ * but some people still do). If it ever shows up as a performance thing
+ * I'll look into optimizing this ;-)
+ */
+typedef bool (*drain_func)(memcached_protocol_client_st *client);
+typedef protocol_binary_response_status (*spool_func)(memcached_protocol_client_st *client,
+                                                      const void *data,
+                                                      size_t length);
+
+/**
+ * Definition of the per instance structure.
+ */
+struct memcached_protocol_st {
+  memcached_binary_protocol_callback_st *callback;
+  memcached_protocol_recv_func recv;
+  memcached_protocol_send_func send;
+
+  /*
+   * I really don't need these as funciton pointers, but I don't want
+   * to clutter the namespace if someone links statically.
+   */
+  drain_func drain;
+  spool_func spool;
+
+  /*
+   * To avoid keeping a buffer in each client all the time I have a
+   * bigger buffer in the instance that I read to initially, and then
+   * I try to parse and execute as much from the buffer. If I wasn't able
+   * to process all data I'll keep that in a per-connection buffer until
+   * the next time I can read from the socket.
+   */
+  uint8_t *input_buffer;
+  size_t input_buffer_size;
+
+  bool pedantic;
+  /* @todo use multiple sized buffers */
+  cache_t *buffer_cache;
+};
+
+struct chunk_st {
+  /* Pointer to the data */
+  char *data;
+  /* The offset to the first byte into the buffer that is used */
+  size_t offset;
+  /* The offset into the buffer for the first free byte */
+  size_t nbytes;
+  /* The number of bytes in the buffer */
+  size_t size;
+  /* Pointer to the next buffer in the chain */
+  struct chunk_st *next;
+};
+
+#define CHUNK_BUFFERSIZE 2048
+
+typedef memcached_protocol_event_t (*process_data)(struct memcached_protocol_client_st *client, ssize_t *length, void **endptr);
+
+enum ascii_cmd {
+  GET_CMD,
+  GETS_CMD,
+  SET_CMD,
+  ADD_CMD,
+  REPLACE_CMD,
+  CAS_CMD,
+  APPEND_CMD,
+  PREPEND_CMD,
+  DELETE_CMD,
+  INCR_CMD,
+  DECR_CMD,
+  STATS_CMD,
+  FLUSH_ALL_CMD,
+  VERSION_CMD,
+  QUIT_CMD,
+  VERBOSITY_CMD,
+  UNKNOWN_CMD
+};
+
+struct memcached_protocol_client_st {
+  bool is_verbose;
+  memcached_protocol_st *root;
+  memcached_socket_t sock;
+  int error;
+
+  /* Linked list of data to send */
+  struct chunk_st *output;
+  struct chunk_st *output_tail;
+
+  /*
+   * While we process input data, this is where we spool incomplete commands
+   * if we need to receive more data....
+   * @todo use the buffercace
+   */
+  uint8_t *input_buffer;
+  size_t input_buffer_size;
+  size_t input_buffer_offset;
+
+  /* The callback to the protocol handler to use (ascii or binary) */
+  process_data work;
+
+  /*
+   * Should the spool data discard the data to send or not? (aka noreply in
+   * the ascii protocol..
+   */
+  bool mute;
+
+  /* Members used by the binary protocol */
+  protocol_binary_request_header *current_command;
+
+  /* Members used by the ascii protocol */
+  enum ascii_cmd ascii_command;
+};
+
+#include "ascii_handler.h"
+#include "binary_handler.h"
diff --git a/src/libmemcachedprotocol/handler.c b/src/libmemcachedprotocol/handler.c
new file mode 100644 (file)
index 0000000..afd7086
--- /dev/null
@@ -0,0 +1,441 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+#include <libmemcachedprotocol/common.h>
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <string.h>
+#include <strings.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+/*
+** **********************************************************************
+** INTERNAL INTERFACE
+** **********************************************************************
+*/
+
+/**
+ * The default function to receive data from the client. This function
+ * just wraps the recv function to receive from a socket.
+ * See man -s3socket recv for more information.
+ *
+ * @param cookie cookie indentifying a client, not used
+ * @param sock socket to read from
+ * @param buf the destination buffer
+ * @param nbytes the number of bytes to read
+ * @return the number of bytes transferred of -1 upon error
+ */
+static ssize_t default_recv(const void *cookie,
+                            memcached_socket_t sock,
+                            void *buf,
+                            size_t nbytes)
+{
+  (void)cookie;
+  return recv(sock, buf, nbytes, 0);
+}
+
+/**
+ * The default function to send data to the server. This function
+ * just wraps the send function to send through a socket.
+ * See man -s3socket send for more information.
+ *
+ * @param cookie cookie indentifying a client, not used
+ * @param sock socket to send to
+ * @param buf the source buffer
+ * @param nbytes the number of bytes to send
+ * @return the number of bytes transferred of -1 upon error
+ */
+static ssize_t default_send(const void *cookie,
+                            memcached_socket_t fd,
+                            const void *buf,
+                            size_t nbytes)
+{
+  (void)cookie;
+  return send(fd, buf, nbytes, MSG_NOSIGNAL);
+}
+
+/**
+ * Try to drain the output buffers without blocking
+ *
+ * @param client the client to drain
+ * @return false if an error occured (connection should be shut down)
+ *         true otherwise (please note that there may be more data to
+ *              left in the buffer to send)
+ */
+static bool drain_output(struct memcached_protocol_client_st *client)
+{
+  if (client->is_verbose)
+  {
+    fprintf(stderr, "%s:%d %s mute:%d output:%s length:%d\n", __FILE__, __LINE__, __func__, (int)client->mute,
+            client->output ? "yes" : "no",
+            client->output ? (int)(client->output->nbytes - client->output->offset) : 0);
+  }
+
+  /* Do we have pending data to send? */
+  while (client->output != NULL)
+  {
+    ssize_t len= client->root->send(client,
+                            client->sock,
+                            client->output->data + client->output->offset,
+                            client->output->nbytes - client->output->offset);
+
+    if (len == -1)
+    {
+      if (get_socket_errno() == EWOULDBLOCK)
+      {
+        return true;
+      }
+      else if (get_socket_errno() != EINTR)
+      {
+        client->error= get_socket_errno();
+        return false;
+      }
+    }
+    else
+    {
+      client->output->offset += (size_t)len;
+      if (client->output->offset == client->output->nbytes)
+      {
+        /* This was the complete buffer */
+        struct chunk_st *old= client->output;
+        client->output= client->output->next;
+        if (client->output == NULL)
+        {
+          client->output_tail= NULL;
+        }
+        cache_free(client->root->buffer_cache, old);
+      }
+    }
+  }
+
+  return true;
+}
+
+/**
+ * Allocate an output buffer and chain it into the output list
+ *
+ * @param client the client that needs the buffer
+ * @return pointer to the new chunk if the allocation succeeds, NULL otherwise
+ */
+static struct chunk_st *allocate_output_chunk(struct memcached_protocol_client_st *client)
+{
+  struct chunk_st *ret= cache_alloc(client->root->buffer_cache);
+
+  if (ret == NULL)
+  {
+    return NULL;
+  }
+
+  ret->offset= ret->nbytes= 0;
+  ret->next= NULL;
+  ret->size= CHUNK_BUFFERSIZE;
+  ret->data= (void*)(ret + 1);
+  if (client->output == NULL)
+  {
+    client->output= client->output_tail= ret;
+  }
+  else
+  {
+    client->output_tail->next= ret;
+    client->output_tail= ret;
+  }
+
+  return ret;
+}
+
+/**
+ * Spool data into the send-buffer for a client.
+ *
+ * @param client the client to spool the data for
+ * @param data the data to spool
+ * @param length the number of bytes of data to spool
+ * @return PROTOCOL_BINARY_RESPONSE_SUCCESS if success,
+ *         PROTOCOL_BINARY_RESPONSE_ENOMEM if we failed to allocate memory
+ */
+static protocol_binary_response_status spool_output(struct memcached_protocol_client_st *client,
+                                                    const void *data,
+                                                    size_t length)
+{
+  if (client->is_verbose)
+  {
+    fprintf(stderr, "%s:%d %s mute:%d length:%d\n", __FILE__, __LINE__, __func__, (int)client->mute, (int)length);
+  }
+
+  if (client->mute)
+  {
+    return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+  }
+
+  size_t offset= 0;
+
+  struct chunk_st *chunk= client->output;
+  while (offset < length)
+  {
+    if (chunk == NULL || (chunk->size - chunk->nbytes) == 0)
+    {
+      if ((chunk= allocate_output_chunk(client)) == NULL)
+      {
+        return PROTOCOL_BINARY_RESPONSE_ENOMEM;
+      }
+    }
+
+    size_t bulk= length - offset;
+    if (bulk > chunk->size - chunk->nbytes)
+    {
+      bulk= chunk->size - chunk->nbytes;
+    }
+
+    memcpy(chunk->data + chunk->nbytes, data, bulk);
+    chunk->nbytes += bulk;
+    offset += bulk;
+  }
+
+  return PROTOCOL_BINARY_RESPONSE_SUCCESS;
+}
+
+/**
+ * Try to determine the protocol used on this connection.
+ * If the first byte contains the magic byte PROTOCOL_BINARY_REQ we should
+ * be using the binary protocol on the connection. I implemented the support
+ * for the ASCII protocol by wrapping into the simple interface (aka v1),
+ * so the implementors needs to provide an implementation of that interface
+ *
+ */
+static memcached_protocol_event_t determine_protocol(struct memcached_protocol_client_st *client, ssize_t *length, void **endptr)
+{
+  if (*client->root->input_buffer == (uint8_t)PROTOCOL_BINARY_REQ)
+  {
+    if (client->is_verbose)
+    {
+      fprintf(stderr, "%s:%d PROTOCOL: memcached_binary_protocol_process_data\n", __FILE__, __LINE__);
+    }
+    client->work= memcached_binary_protocol_process_data;
+  }
+  else if (client->root->callback->interface_version == 1)
+  {
+    if (client->is_verbose)
+    {
+      fprintf(stderr, "%s:%d PROTOCOL: memcached_ascii_protocol_process_data\n", __FILE__, __LINE__);
+    }
+
+    /*
+     * The ASCII protocol can only be used if the implementors provide
+     * an implementation for the version 1 of the interface..
+     *
+     * @todo I should allow the implementors to provide an implementation
+     *       for version 0 and 1 at the same time and set the preferred
+     *       interface to use...
+     */
+    client->work= memcached_ascii_protocol_process_data;
+  }
+  else
+  {
+    if (client->is_verbose)
+    {
+      fprintf(stderr, "%s:%d PROTOCOL: Unsupported protocol\n", __FILE__, __LINE__);
+    }
+
+    /* Let's just output a warning the way it is supposed to look like
+     * in the ASCII protocol...
+     */
+    const char *err= "CLIENT_ERROR: Unsupported protocol\r\n";
+    client->root->spool(client, err, strlen(err));
+    client->root->drain(client);
+
+    return MEMCACHED_PROTOCOL_ERROR_EVENT; /* Unsupported protocol */
+  }
+
+  return client->work(client, length, endptr);
+}
+
+/*
+** **********************************************************************
+** * PUBLIC INTERFACE
+** * See protocol_handler.h for function description
+** **********************************************************************
+*/
+struct memcached_protocol_st *memcached_protocol_create_instance(void)
+{
+  struct memcached_protocol_st *ret= calloc(1, sizeof(*ret));
+  if (ret != NULL)
+  {
+    ret->recv= default_recv;
+    ret->send= default_send;
+    ret->drain= drain_output;
+    ret->spool= spool_output;
+    ret->input_buffer_size= 1 * 1024 * 1024;
+    ret->input_buffer= malloc(ret->input_buffer_size);
+    if (ret->input_buffer == NULL)
+    {
+      free(ret);
+      ret= NULL;
+
+      return NULL;
+    }
+
+    ret->buffer_cache= cache_create("protocol_handler",
+                                     CHUNK_BUFFERSIZE + sizeof(struct chunk_st),
+                                     0, NULL, NULL);
+    if (ret->buffer_cache == NULL)
+    {
+      free(ret->input_buffer);
+      free(ret);
+      ret= NULL;
+    }
+  }
+
+  return ret;
+}
+
+void memcached_protocol_destroy_instance(struct memcached_protocol_st *instance)
+{
+  cache_destroy(instance->buffer_cache);
+  free(instance->input_buffer);
+  free(instance);
+}
+
+struct memcached_protocol_client_st *memcached_protocol_create_client(struct memcached_protocol_st *instance, memcached_socket_t sock)
+{
+  struct memcached_protocol_client_st *ret= calloc(1, sizeof(memcached_protocol_client_st));
+  if (ret != NULL)
+  {
+    ret->root= instance;
+    ret->sock= sock;
+    ret->work= determine_protocol;
+  }
+
+  return ret;
+}
+
+void memcached_protocol_client_destroy(struct memcached_protocol_client_st *client)
+{
+  free(client);
+}
+
+void memcached_protocol_client_set_verbose(struct memcached_protocol_client_st *client, bool arg)
+{
+  if (client)
+  {
+    client->is_verbose= arg;
+  }
+}
+
+memcached_protocol_event_t memcached_protocol_client_work(struct memcached_protocol_client_st *client)
+{
+  /* Try to send data and read from the socket */
+  bool more_data= true;
+  do
+  {
+    ssize_t len= client->root->recv(client,
+                                    client->sock,
+                                    client->root->input_buffer + client->input_buffer_offset,
+                                    client->root->input_buffer_size - client->input_buffer_offset);
+
+    if (len > 0)
+    {
+      /* Do we have the complete packet? */
+      if (client->input_buffer_offset > 0)
+      {
+        memcpy(client->root->input_buffer, client->input_buffer,
+               client->input_buffer_offset);
+        len += (ssize_t)client->input_buffer_offset;
+
+        /* @todo use buffer-cache! */
+        free(client->input_buffer);
+        client->input_buffer_offset= 0;
+      }
+
+      void *endptr;
+      memcached_protocol_event_t events= client->work(client, &len, &endptr);
+      if (events == MEMCACHED_PROTOCOL_ERROR_EVENT)
+      {
+        return MEMCACHED_PROTOCOL_ERROR_EVENT;
+      }
+
+      if (len > 0)
+      {
+        /* save the data for later on */
+        /* @todo use buffer-cache */
+        client->input_buffer= malloc((size_t)len);
+        if (client->input_buffer == NULL)
+        {
+          client->error= ENOMEM;
+          return MEMCACHED_PROTOCOL_ERROR_EVENT;
+        }
+        memcpy(client->input_buffer, endptr, (size_t)len);
+        client->input_buffer_offset= (size_t)len;
+        more_data= false;
+      }
+    }
+    else if (len == 0)
+    {
+      /* Connection closed */
+      drain_output(client);
+      return MEMCACHED_PROTOCOL_ERROR_EVENT;
+    }
+    else
+    {
+      if (get_socket_errno() != EWOULDBLOCK)
+      {
+        client->error= get_socket_errno();
+        /* mark this client as terminated! */
+        return MEMCACHED_PROTOCOL_ERROR_EVENT;
+      }
+      more_data= false;
+    }
+  } while (more_data);
+
+  if (!drain_output(client))
+  {
+    return MEMCACHED_PROTOCOL_ERROR_EVENT;
+  }
+
+  memcached_protocol_event_t ret= MEMCACHED_PROTOCOL_READ_EVENT;
+  if (client->output)
+  {
+    ret|= MEMCACHED_PROTOCOL_READ_EVENT;
+  }
+
+  return ret;
+}
diff --git a/src/libmemcachedprotocol/pedantic.c b/src/libmemcachedprotocol/pedantic.c
new file mode 100644 (file)
index 0000000..54a2add
--- /dev/null
@@ -0,0 +1,237 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+#include <libmemcachedprotocol/common.h>
+
+#include <sys/types.h>
+
+#define ensure(a) if (!(a)) { return false; }
+
+bool memcached_binary_protocol_pedantic_check_request(const protocol_binary_request_header *request)
+{
+  ensure(request->request.magic == PROTOCOL_BINARY_REQ);
+  ensure(request->request.datatype == PROTOCOL_BINARY_RAW_BYTES);
+
+  ensure(request->bytes[6] == 0);
+  ensure(request->bytes[7] == 0);
+
+  uint8_t opcode= request->request.opcode;
+  uint16_t keylen= ntohs(request->request.keylen);
+  uint8_t extlen= request->request.extlen;
+  uint32_t bodylen= ntohl(request->request.bodylen);
+
+  ensure(bodylen >= (keylen + extlen));
+
+  switch (opcode) {
+  case PROTOCOL_BINARY_CMD_GET:
+  case PROTOCOL_BINARY_CMD_GETK:
+  case PROTOCOL_BINARY_CMD_GETKQ:
+  case PROTOCOL_BINARY_CMD_GETQ:
+    ensure(extlen == 0);
+    ensure(keylen > 0);
+    ensure(keylen == bodylen);
+    ensure(request->request.cas == 0);
+    break;
+
+  case PROTOCOL_BINARY_CMD_ADD:
+  case PROTOCOL_BINARY_CMD_ADDQ:
+    /* it makes no sense to run add with a cas value */
+    ensure(request->request.cas == 0);
+    /* FALLTHROUGH */
+  case PROTOCOL_BINARY_CMD_SET:
+  case PROTOCOL_BINARY_CMD_SETQ:
+  case PROTOCOL_BINARY_CMD_REPLACE:
+  case PROTOCOL_BINARY_CMD_REPLACEQ:
+    ensure(keylen > 0);
+    ensure(extlen == 8);
+    break;
+
+  case PROTOCOL_BINARY_CMD_DELETE:
+  case PROTOCOL_BINARY_CMD_DELETEQ:
+    ensure(extlen == 0);
+    ensure(keylen > 0);
+    ensure(keylen == bodylen);
+    break;
+
+  case PROTOCOL_BINARY_CMD_INCREMENT:
+  case PROTOCOL_BINARY_CMD_INCREMENTQ:
+  case PROTOCOL_BINARY_CMD_DECREMENT:
+  case PROTOCOL_BINARY_CMD_DECREMENTQ:
+    ensure(extlen == 20);
+    ensure(keylen > 0);
+    ensure(keylen + extlen == bodylen);
+    break;
+
+  case PROTOCOL_BINARY_CMD_QUIT:
+  case PROTOCOL_BINARY_CMD_QUITQ:
+  case PROTOCOL_BINARY_CMD_NOOP:
+  case PROTOCOL_BINARY_CMD_VERSION:
+    ensure(extlen == 0);
+    ensure(keylen == 0);
+    ensure(bodylen == 0);
+    break;
+
+  case PROTOCOL_BINARY_CMD_FLUSH:
+  case PROTOCOL_BINARY_CMD_FLUSHQ:
+    ensure(extlen == 0 || extlen == 4);
+    ensure(keylen == 0);
+    ensure(bodylen == extlen);
+    break;
+
+  case PROTOCOL_BINARY_CMD_STAT:
+    ensure(extlen == 0);
+    /* May have key, but not value */
+    ensure(keylen == bodylen);
+    break;
+
+  case PROTOCOL_BINARY_CMD_APPEND:
+  case PROTOCOL_BINARY_CMD_APPENDQ:
+  case PROTOCOL_BINARY_CMD_PREPEND:
+  case PROTOCOL_BINARY_CMD_PREPENDQ:
+    ensure(extlen == 0);
+    ensure(keylen > 0);
+    break;
+  default:
+    /* Unknown command */
+    ;
+  }
+
+  return true;
+}
+
+bool memcached_binary_protocol_pedantic_check_response(const protocol_binary_request_header *request,
+                                                       const protocol_binary_response_header *response)
+{
+  ensure(response->response.magic == PROTOCOL_BINARY_RES);
+  ensure(response->response.datatype == PROTOCOL_BINARY_RAW_BYTES);
+  ensure(response->response.opaque == request->request.opaque);
+
+  uint16_t status= ntohs(response->response.status);
+  uint8_t opcode= response->response.opcode;
+
+  if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS)
+  {
+    switch (opcode) {
+    case PROTOCOL_BINARY_CMD_ADDQ:
+    case PROTOCOL_BINARY_CMD_APPENDQ:
+    case PROTOCOL_BINARY_CMD_DECREMENTQ:
+    case PROTOCOL_BINARY_CMD_DELETEQ:
+    case PROTOCOL_BINARY_CMD_FLUSHQ:
+    case PROTOCOL_BINARY_CMD_INCREMENTQ:
+    case PROTOCOL_BINARY_CMD_PREPENDQ:
+    case PROTOCOL_BINARY_CMD_QUITQ:
+    case PROTOCOL_BINARY_CMD_REPLACEQ:
+    case PROTOCOL_BINARY_CMD_SETQ:
+      /* Quiet command shouldn't return on success */
+      return false;
+    default:
+      break;
+    }
+
+    switch (opcode) {
+    case PROTOCOL_BINARY_CMD_ADD:
+    case PROTOCOL_BINARY_CMD_REPLACE:
+    case PROTOCOL_BINARY_CMD_SET:
+    case PROTOCOL_BINARY_CMD_APPEND:
+    case PROTOCOL_BINARY_CMD_PREPEND:
+      ensure(response->response.keylen == 0);
+      ensure(response->response.extlen == 0);
+      ensure(response->response.bodylen == 0);
+      ensure(response->response.cas != 0);
+      break;
+    case PROTOCOL_BINARY_CMD_FLUSH:
+    case PROTOCOL_BINARY_CMD_NOOP:
+    case PROTOCOL_BINARY_CMD_QUIT:
+    case PROTOCOL_BINARY_CMD_DELETE:
+      ensure(response->response.keylen == 0);
+      ensure(response->response.extlen == 0);
+      ensure(response->response.bodylen == 0);
+      ensure(response->response.cas == 0);
+      break;
+
+    case PROTOCOL_BINARY_CMD_DECREMENT:
+    case PROTOCOL_BINARY_CMD_INCREMENT:
+      ensure(response->response.keylen == 0);
+      ensure(response->response.extlen == 0);
+      ensure(ntohl(response->response.bodylen) == 8);
+      ensure(response->response.cas != 0);
+      break;
+
+    case PROTOCOL_BINARY_CMD_STAT:
+      ensure(response->response.extlen == 0);
+      /* key and value exists in all packets except in the terminating */
+      ensure(response->response.cas == 0);
+      break;
+
+    case PROTOCOL_BINARY_CMD_VERSION:
+      ensure(response->response.keylen == 0);
+      ensure(response->response.extlen == 0);
+      ensure(response->response.bodylen != 0);
+      ensure(response->response.cas == 0);
+      break;
+
+    case PROTOCOL_BINARY_CMD_GET:
+    case PROTOCOL_BINARY_CMD_GETQ:
+      ensure(response->response.keylen == 0);
+      ensure(response->response.extlen == 4);
+      ensure(response->response.cas != 0);
+      break;
+
+    case PROTOCOL_BINARY_CMD_GETK:
+    case PROTOCOL_BINARY_CMD_GETKQ:
+      ensure(response->response.keylen != 0);
+      ensure(response->response.extlen == 4);
+      ensure(response->response.cas != 0);
+      break;
+
+    default:
+      /* Undefined command code */
+      break;
+    }
+  }
+  else
+  {
+    ensure(response->response.cas == 0);
+    ensure(response->response.extlen == 0);
+    if (opcode != PROTOCOL_BINARY_CMD_GETK)
+    {
+      ensure(response->response.keylen == 0);
+    }
+  }
+
+  return true;
+}
diff --git a/src/libmemcachedutil/CMakeLists.txt b/src/libmemcachedutil/CMakeLists.txt
new file mode 100644 (file)
index 0000000..f09b2a2
--- /dev/null
@@ -0,0 +1,19 @@
+
+add_library(libmemcachedutil SHARED
+        ../libmemcached/backtrace.cc
+        flush.cc
+        pid.cc
+        ping.cc
+        pool.cc
+        version.cc
+        )
+add_library(memcachedutil ALIAS libmemcachedutil)
+set_target_properties(libmemcachedutil PROPERTIES LIBRARY_OUTPUT_NAME memcachedutil)
+target_compile_definitions(libmemcachedutil PRIVATE -DBUILDING_LIBMEMCACHED)
+target_link_libraries(libmemcachedutil libmemcached Threads::Threads)
+
+set_target_properties(libmemcachedutil PROPERTIES SOVERSION ${LIBMEMCACHEDUTIL_SO_VERSION})
+install(TARGETS libmemcachedutil EXPORT libmemcachedutil
+        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
+export(EXPORT libmemcachedutil)
+install(EXPORT libmemcachedutil DESTINATION ${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/cmake)
diff --git a/src/libmemcachedutil/common.h b/src/libmemcachedutil/common.h
new file mode 100644 (file)
index 0000000..5e39354
--- /dev/null
@@ -0,0 +1,49 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached Utility library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Summary: connects to a host, and then flushes it (memcached_flush(3)).
+ *
+ */
+
+#pragma once
+
+#include "mem_config.h"
+
+#include <cstddef>
+#include <cstdlib>
+#include <cstdio>
+
+#include "libmemcachedutil-1.0/util.h"
+#include "libmemcached/assert.hpp"
+#include "libmemcached/backtrace.hpp"
diff --git a/src/libmemcachedutil/flush.cc b/src/libmemcachedutil/flush.cc
new file mode 100644 (file)
index 0000000..6a99603
--- /dev/null
@@ -0,0 +1,60 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Summary: connects to a host, and then flushes it (memcached_flush(3)).
+ *
+ */
+
+#include <libmemcachedutil/common.h>
+
+
+bool libmemcached_util_flush(const char *hostname, in_port_t port, memcached_return_t *ret)
+{
+  memcached_st *memc_ptr= memcached_create(NULL);
+
+  memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
+  if (memcached_success(rc))
+  {
+    rc= memcached_flush(memc_ptr, 0);
+  }
+
+  memcached_free(memc_ptr);
+
+  if (ret)
+  {
+    *ret= rc;
+  }
+
+  return memcached_success(rc);
+}
diff --git a/src/libmemcachedutil/pid.cc b/src/libmemcachedutil/pid.cc
new file mode 100644 (file)
index 0000000..3465611
--- /dev/null
@@ -0,0 +1,161 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Summary: connects to a host, and determines what its pid is
+ *
+ */
+
+#include <libmemcachedutil/common.h>
+
+
+// Never look at the stat object directly.
+
+
+pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_return_t *ret)
+{
+  pid_t pid= -1;
+
+  memcached_return_t unused;
+  if (ret == NULL)
+  {
+    ret= &unused;
+  }
+
+  memcached_st *memc_ptr= memcached_create(NULL);
+  if (memc_ptr == NULL)
+  {
+    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return -1;
+  }
+
+  memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
+  if (memcached_success(rc))
+  {
+    memcached_stat_st *stat= memcached_stat(memc_ptr, NULL, &rc);
+    if (memcached_success(rc) and stat and stat->pid != -1)
+    {
+      pid= stat->pid;
+    }
+    else if (memcached_success(rc))
+    {
+      rc= MEMCACHED_UNKNOWN_STAT_KEY; // Something went wrong if this happens
+    }
+    else if (rc == MEMCACHED_SOME_ERRORS) // Generic answer, we will now find the specific reason (if one exists)
+    {
+      const memcached_instance_st * instance= memcached_server_instance_by_position(memc_ptr, 0);
+
+      assert_msg(instance and memcached_server_error(instance), " ");
+      if (instance and memcached_server_error(instance))
+      {
+        rc= memcached_server_error_return(instance);
+      }
+    }
+
+    memcached_stat_free(memc_ptr, stat);
+  }
+  memcached_free(memc_ptr);
+
+  *ret= rc;
+
+  return pid;
+}
+
+pid_t libmemcached_util_getpid2(const char *hostname, in_port_t port, const char *username, const char *password,  memcached_return_t *ret)
+{
+  if (username == NULL)
+  {
+    return libmemcached_util_getpid(hostname, port, ret);
+  }
+
+  pid_t pid= -1;
+
+  memcached_return_t unused;
+  if (not ret)
+    ret= &unused;
+
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    *ret= MEMCACHED_NOT_SUPPORTED;
+    return pid;
+  }
+
+  memcached_st *memc_ptr= memcached_create(NULL);
+  if (not memc_ptr)
+  {
+    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return -1;
+  }
+
+  if (memcached_failed(*ret= memcached_set_sasl_auth_data(memc_ptr, username, password)))
+  {
+    memcached_free(memc_ptr);
+    return false;
+  }
+
+
+  memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
+  if (memcached_success(rc))
+  {
+    memcached_stat_st *stat= memcached_stat(memc_ptr, NULL, &rc);
+    if (memcached_success(rc) and stat and stat->pid != -1)
+    {
+      pid= stat->pid;
+    }
+    else if (memcached_success(rc))
+    {
+      rc= MEMCACHED_UNKNOWN_STAT_KEY; // Something went wrong if this happens
+    }
+    else if (rc == MEMCACHED_SOME_ERRORS) // Generic answer, we will now find the specific reason (if one exists)
+    {
+      const memcached_instance_st * instance=
+        memcached_server_instance_by_position(memc_ptr, 0);
+
+#if 0
+      assert_msg(instance and instance->error_messages, " ");
+#endif
+      if (instance and memcached_server_error(instance))
+      {
+        rc= memcached_server_error_return(instance);
+      }
+    }
+
+    memcached_stat_free(memc_ptr, stat);
+  }
+  memcached_free(memc_ptr);
+
+  *ret= rc;
+
+  return pid;
+}
diff --git a/src/libmemcachedutil/ping.cc b/src/libmemcachedutil/ping.cc
new file mode 100644 (file)
index 0000000..a867c56
--- /dev/null
@@ -0,0 +1,136 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Summary: connects to a host, and makes sure it is alive.
+ *
+ */
+
+#include <libmemcachedutil/common.h>
+
+bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret)
+{
+  memcached_return_t unused;
+  if (ret == NULL)
+  {
+    ret= &unused;
+  }
+
+  memcached_st *memc_ptr= memcached_create(NULL);
+  if (memc_ptr == NULL)
+  {
+    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return false;
+  }
+
+  if (memcached_success((*ret= memcached_behavior_set(memc_ptr, MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT, 400000))))
+  {
+    memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
+    if (memcached_success(rc))
+    {
+      rc= memcached_version(memc_ptr);
+    }
+
+    if (memcached_failed(rc) and rc == MEMCACHED_SOME_ERRORS)
+    {
+      const memcached_instance_st * instance=
+        memcached_server_instance_by_position(memc_ptr, 0);
+
+      assert_msg(instance and memcached_server_error(instance), " ");
+      if (instance and memcached_server_error(instance))
+      {
+        rc= memcached_server_error_return(instance);
+      }
+    }
+
+    *ret= rc;
+  }
+  memcached_free(memc_ptr);
+
+  return memcached_success(*ret);
+}
+
+bool libmemcached_util_ping2(const char *hostname, in_port_t port, const char *username, const char *password,  memcached_return_t *ret)
+{
+  if (username == NULL)
+  {
+    return libmemcached_util_ping(hostname, port, ret);
+  }
+
+  memcached_return_t unused;
+  if (not ret)
+    ret= &unused;
+
+  if (LIBMEMCACHED_WITH_SASL_SUPPORT == 0)
+  {
+    *ret= MEMCACHED_NOT_SUPPORTED;
+    return false;
+  }
+
+  memcached_st *memc_ptr= memcached_create(NULL);
+  if (not memc_ptr)
+  {
+    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return false;
+  }
+
+  if (memcached_failed(*ret= memcached_set_sasl_auth_data(memc_ptr, username, password)))
+  {
+    memcached_free(memc_ptr);
+    return false;
+  }
+
+  memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
+  if (memcached_success(rc))
+  {
+    rc= memcached_version(memc_ptr);
+  }
+
+  if (memcached_failed(rc) and rc == MEMCACHED_SOME_ERRORS)
+  {
+    const memcached_instance_st * instance=
+      memcached_server_instance_by_position(memc_ptr, 0);
+
+    assert_msg(instance and memcached_server_error(instance), " ");
+    if (instance and memcached_server_error(instance))
+    {
+      rc= memcached_server_error_return(instance);
+    }
+  }
+  memcached_free(memc_ptr);
+
+  *ret= rc;
+
+  return memcached_success(rc);
+}
diff --git a/src/libmemcachedutil/pool.cc b/src/libmemcachedutil/pool.cc
new file mode 100644 (file)
index 0000000..8d76024
--- /dev/null
@@ -0,0 +1,523 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libmemcachedutil/common.h>
+
+#include <cassert>
+#include <cerrno>
+#include <pthread.h>
+#include <memory>
+
+struct memcached_pool_st
+{
+  pthread_mutex_t mutex;
+  pthread_cond_t cond;
+  memcached_st *master;
+  memcached_st **server_pool;
+  int firstfree;
+  const uint32_t size;
+  uint32_t current_size;
+  bool _owns_master;
+  struct timespec _timeout;
+
+  memcached_pool_st(memcached_st *master_arg, size_t max_arg) :
+    master(master_arg),
+    server_pool(NULL),
+    firstfree(-1),
+    size(uint32_t(max_arg)),
+    current_size(0),
+    _owns_master(false)
+  {
+    pthread_mutex_init(&mutex, NULL);
+    pthread_cond_init(&cond, NULL);
+    _timeout.tv_sec= 5;
+    _timeout.tv_nsec= 0;
+  }
+
+  const struct timespec& timeout() const
+  {
+    return _timeout;
+  }
+
+  bool release(memcached_st*, memcached_return_t& rc);
+
+  memcached_st *fetch(memcached_return_t& rc);
+  memcached_st *fetch(const struct timespec&, memcached_return_t& rc);
+
+  bool init(uint32_t initial);
+
+  ~memcached_pool_st()
+  {
+    for (int x= 0; x <= firstfree; ++x)
+    {
+      memcached_free(server_pool[x]);
+      server_pool[x]= NULL;
+    }
+
+    int error;
+    if ((error= pthread_mutex_destroy(&mutex)) != 0)
+    {
+      assert_vmsg(error != 0, "pthread_mutex_destroy() %s(%d)", strerror(error), error);
+    }
+
+    if ((error= pthread_cond_destroy(&cond)) != 0)
+    {
+      assert_vmsg(error != 0, "pthread_cond_destroy() %s", strerror(error));
+    }
+
+    delete [] server_pool;
+    if (_owns_master)
+    {
+      memcached_free(master);
+    }
+  }
+
+  void increment_version()
+  {
+    ++master->configure.version;
+  }
+
+  bool compare_version(const memcached_st *arg) const
+  {
+    return (arg->configure.version == version());
+  }
+
+  int32_t version() const
+  {
+    return master->configure.version;
+  }
+};
+
+
+/**
+ * Grow the connection pool by creating a connection structure and clone the
+ * original memcached handle.
+ */
+static bool grow_pool(memcached_pool_st* pool)
+{
+  assert(pool);
+
+  memcached_st *obj;
+  if (not (obj= memcached_clone(NULL, pool->master)))
+  {
+    return false;
+  }
+
+  pool->server_pool[++pool->firstfree]= obj;
+  pool->current_size++;
+  obj->configure.version= pool->version();
+
+  return true;
+}
+
+bool memcached_pool_st::init(uint32_t initial)
+{
+  server_pool= new (std::nothrow) memcached_st *[size];
+  if (server_pool == NULL)
+  {
+    return false;
+  }
+
+  /*
+    Try to create the initial size of the pool. An allocation failure at
+    this time is not fatal..
+  */
+  for (unsigned int x= 0; x < initial; ++x)
+  {
+    if (grow_pool(this) == false)
+    {
+      break;
+    }
+  }
+
+  return true;
+}
+
+
+static inline memcached_pool_st *_pool_create(memcached_st* master, uint32_t initial, uint32_t max)
+{
+  if (initial == 0 or max == 0 or (initial > max))
+  {
+    return NULL;
+  }
+
+  memcached_pool_st *object= new (std::nothrow) memcached_pool_st(master, max);
+  if (object == NULL)
+  {
+    return NULL;
+  }
+
+  /*
+    Try to create the initial size of the pool. An allocation failure at
+    this time is not fatal..
+  */
+  if (not object->init(initial))
+  {
+    delete object;
+    return NULL;
+  }
+
+  return object;
+}
+
+memcached_pool_st *memcached_pool_create(memcached_st* master, uint32_t initial, uint32_t max)
+{
+  return _pool_create(master, initial, max);
+}
+
+memcached_pool_st * memcached_pool(const char *option_string, size_t option_string_length)
+{
+  memcached_st *memc= memcached(option_string, option_string_length);
+
+  if (memc == NULL)
+  {
+    return NULL;
+  }
+
+  memcached_pool_st *self= memcached_pool_create(memc, memc->configure.initial_pool_size, memc->configure.max_pool_size);
+  if (self == NULL)
+  {
+    memcached_free(memc);
+    return NULL;
+  }
+
+  self->_owns_master= true;
+
+  return self;
+}
+
+memcached_st*  memcached_pool_destroy(memcached_pool_st* pool)
+{
+  if (pool == NULL)
+  {
+    return NULL;
+  }
+
+  // Legacy that we return the original structure
+  memcached_st *ret= NULL;
+  if (pool->_owns_master)
+  { }
+  else
+  {
+    ret= pool->master;
+  }
+
+  delete pool;
+
+  return ret;
+}
+
+memcached_st* memcached_pool_st::fetch(memcached_return_t& rc)
+{
+  static struct timespec relative_time= { 0, 0 };
+  return fetch(relative_time, rc);
+}
+
+memcached_st* memcached_pool_st::fetch(const struct timespec& relative_time, memcached_return_t& rc)
+{
+  rc= MEMCACHED_SUCCESS;
+
+  int error;
+  if ((error= pthread_mutex_lock(&mutex)) != 0)
+  {
+    rc= MEMCACHED_IN_PROGRESS;
+    return NULL;
+  }
+
+  memcached_st *ret= NULL;
+  do
+  {
+    if (firstfree > -1)
+    {
+      ret= server_pool[firstfree--];
+    }
+    else if (current_size == size)
+    {
+      if (relative_time.tv_sec == 0 and relative_time.tv_nsec == 0)
+      {
+        error= pthread_mutex_unlock(&mutex);
+        rc= MEMCACHED_NOTFOUND;
+
+        return NULL;
+      }
+
+      struct timespec time_to_wait= {0, 0};
+      time_to_wait.tv_sec= time(NULL) +relative_time.tv_sec;
+      time_to_wait.tv_nsec= relative_time.tv_nsec;
+
+      int thread_ret;
+      if ((thread_ret= pthread_cond_timedwait(&cond, &mutex, &time_to_wait)) != 0)
+      {
+        int unlock_error;
+        if ((unlock_error= pthread_mutex_unlock(&mutex)) != 0)
+        {
+          assert_vmsg(error != 0, "pthread_mutex_unlock() %s", strerror(error));
+        }
+
+        if (thread_ret == ETIMEDOUT)
+        {
+          rc= MEMCACHED_TIMEOUT;
+        }
+        else
+        {
+          errno= thread_ret;
+          rc= MEMCACHED_ERRNO;
+        }
+
+        return NULL;
+      }
+    }
+    else if (grow_pool(this) == false)
+    {
+      int unlock_error;
+      if ((unlock_error= pthread_mutex_unlock(&mutex)) != 0)
+      {
+        assert_vmsg(error != 0, "pthread_mutex_unlock() %s", strerror(error));
+      }
+
+      return NULL;
+    }
+  } while (ret == NULL);
+
+  if ((error= pthread_mutex_unlock(&mutex)) != 0)
+  {
+    assert_vmsg(error != 0, "pthread_mutex_unlock() %s", strerror(error));
+  }
+
+  return ret;
+}
+
+bool memcached_pool_st::release(memcached_st *released, memcached_return_t& rc)
+{
+  rc= MEMCACHED_SUCCESS;
+  if (released == NULL)
+  {
+    rc= MEMCACHED_INVALID_ARGUMENTS;
+    return false;
+  }
+
+  int error;
+  if ((error= pthread_mutex_lock(&mutex)))
+  {
+    rc= MEMCACHED_IN_PROGRESS;
+    return false;
+  }
+
+  /* 
+    Someone updated the behavior on the object, so we clone a new memcached_st with the new settings. If we fail to clone, we keep the old one around.
+  */
+  if (compare_version(released) == false)
+  {
+    memcached_st *memc;
+    if ((memc= memcached_clone(NULL, master)))
+    {
+      memcached_free(released);
+      released= memc;
+    }
+  }
+
+  server_pool[++firstfree]= released;
+
+  if (firstfree == 0 and current_size == size)
+  {
+    /* we might have people waiting for a connection.. wake them up :-) */
+    if ((error= pthread_cond_broadcast(&cond)) != 0)
+    {
+      assert_vmsg(error != 0, "pthread_cond_broadcast() %s", strerror(error));
+    }
+  }
+
+  if ((error= pthread_mutex_unlock(&mutex)) != 0)
+  {
+  }
+
+  return true;
+}
+
+memcached_st* memcached_pool_fetch(memcached_pool_st* pool, struct timespec* relative_time, memcached_return_t* rc)
+{
+  if (pool == NULL)
+  {
+    return NULL;
+  }
+
+  memcached_return_t unused;
+  if (rc == NULL)
+  {
+    rc= &unused;
+  }
+
+  if (relative_time == NULL)
+  {
+    return pool->fetch(*rc);
+  }
+
+  return pool->fetch(*relative_time, *rc);
+}
+
+memcached_st* memcached_pool_pop(memcached_pool_st* pool,
+                                 bool block,
+                                 memcached_return_t *rc)
+{
+  if (pool == NULL)
+  {
+    return NULL;
+  }
+
+  memcached_return_t unused;
+  if (rc == NULL)
+  {
+    rc= &unused;
+  }
+
+  memcached_st *memc;
+  if (block)
+  {
+    memc= pool->fetch(pool->timeout(), *rc);
+  }
+  else
+  {
+    memc= pool->fetch(*rc);
+  }
+
+  return memc;
+}
+
+memcached_return_t memcached_pool_release(memcached_pool_st* pool, memcached_st *released)
+{
+  if (pool == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  memcached_return_t rc;
+
+  (void) pool->release(released, rc);
+
+  return rc;
+}
+
+memcached_return_t memcached_pool_push(memcached_pool_st* pool, memcached_st *released)
+{
+  return memcached_pool_release(pool, released);
+}
+
+
+memcached_return_t memcached_pool_behavior_set(memcached_pool_st *pool,
+                                               memcached_behavior_t flag,
+                                               uint64_t data)
+{
+  if (pool == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  int error;
+  if ((error= pthread_mutex_lock(&pool->mutex)))
+  {
+    return MEMCACHED_IN_PROGRESS;
+  }
+
+  /* update the master */
+  memcached_return_t rc= memcached_behavior_set(pool->master, flag, data);
+  if (memcached_failed(rc))
+  {
+    if ((error= pthread_mutex_unlock(&pool->mutex)) != 0)
+    {
+      assert_vmsg(error != 0, "pthread_mutex_unlock() %s", strerror(error));
+    }
+    return rc;
+  }
+
+  pool->increment_version();
+  /* update the clones */
+  for (int xx= 0; xx <= pool->firstfree; ++xx)
+  {
+    if (memcached_success(memcached_behavior_set(pool->server_pool[xx], flag, data)))
+    {
+      pool->server_pool[xx]->configure.version= pool->version();
+    }
+    else
+    {
+      memcached_st *memc;
+      if ((memc= memcached_clone(NULL, pool->master)))
+      {
+        memcached_free(pool->server_pool[xx]);
+        pool->server_pool[xx]= memc;
+        /* I'm not sure what to do in this case.. this would happen
+          if we fail to push the server list inside the client..
+          I should add a testcase for this, but I believe the following
+          would work, except that you would add a hole in the pool list..
+          in theory you could end up with an empty pool....
+        */
+      }
+    }
+  }
+
+  if ((error= pthread_mutex_unlock(&pool->mutex)) != 0)
+  {
+    assert_vmsg(error != 0, "pthread_mutex_unlock() %s", strerror(error));
+  }
+
+  return rc;
+}
+
+memcached_return_t memcached_pool_behavior_get(memcached_pool_st *pool,
+                                               memcached_behavior_t flag,
+                                               uint64_t *value)
+{
+  if (pool == NULL)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
+  int error;
+  if ((error= pthread_mutex_lock(&pool->mutex)))
+  {
+    return MEMCACHED_IN_PROGRESS;
+  }
+
+  *value= memcached_behavior_get(pool->master, flag);
+
+  if ((error= pthread_mutex_unlock(&pool->mutex)) != 0)
+  {
+    assert_vmsg(error != 0, "pthread_mutex_unlock() %s", strerror(error));
+  }
+
+  return MEMCACHED_SUCCESS;
+}
diff --git a/src/libmemcachedutil/version.cc b/src/libmemcachedutil/version.cc
new file mode 100644 (file)
index 0000000..75a8f60
--- /dev/null
@@ -0,0 +1,96 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2010 Brian Aker All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <libmemcachedutil/common.h>
+#include <cassert>
+
+struct local_context
+{
+  uint8_t major_version;
+  uint8_t minor_version;
+  uint8_t micro_version;
+
+  bool truth;
+};
+
+static memcached_return_t check_server_version(const memcached_st *,
+                                               const memcached_instance_st * instance,
+                                               void *context)
+{
+  /* Do Nothing */
+  struct local_context *check= (struct local_context *)context;
+
+  if (memcached_server_major_version(instance) != UINT8_MAX) {
+    uint32_t sv, cv;
+
+    sv = memcached_server_micro_version(instance)
+        |memcached_server_minor_version(instance) << 8
+        |memcached_server_major_version(instance) << 16
+        ;
+    cv = check->micro_version
+        |check->minor_version << 8
+        |check->major_version << 16;
+
+    if (sv >= cv) {
+      return MEMCACHED_SUCCESS;
+    }
+  }
+
+  check->truth= false;
+
+  return MEMCACHED_FAILURE;
+}
+
+bool libmemcached_util_version_check(memcached_st *memc,
+                                     uint8_t major_version,
+                                     uint8_t minor_version,
+                                     uint8_t micro_version)
+{
+  if (memcached_failed(memcached_version(memc)))
+  {
+    return false;
+  }
+
+  struct local_context check= { major_version, minor_version, micro_version, true };
+
+  memcached_server_fn callbacks[1];
+  callbacks[0]= check_server_version;
+  memcached_server_cursor(memc, callbacks, (void *)&check,  1);
+
+  return check.truth;
+}
diff --git a/src/libtest/CMakeLists.txt b/src/libtest/CMakeLists.txt
new file mode 100644 (file)
index 0000000..794d7bd
--- /dev/null
@@ -0,0 +1,70 @@
+
+file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/tmp_chroot)
+file(WRITE ${CMAKE_BINARY_DIR}/libtool
+"#!/bin/bash
+shift
+exec $@
+")
+if(UNIX)
+    if(EXISTS ${CMAKE_BINARY_DIR}/libtool)
+        execute_process(COMMAND chmod +x ${CMAKE_BINARY_DIR}/libtool)
+    endif()
+endif()
+
+add_library(libtest STATIC
+        alarm.cc
+        binaries.cc
+        client.cc
+        cmdline.cc
+        collection.cc
+        comparison.cc
+        core.cc
+        cpu.cc
+        dns.cc
+        dream.cc
+        drizzled.cc
+        exception.cc
+        exception/fatal.cc
+        formatter.cc
+        framework.cc
+        gearmand.cc
+        has.cc
+        http.cc
+        is_local.cc
+        killpid.cc
+        libtool.cc
+        main.cc
+        memcached.cc
+        port.cc
+        result.cc
+        runner.cc
+        server.cc
+        server_container.cc
+        signal.cc
+        socket.cc
+        strerror.cc
+        timer.cc
+        tmpfile.cc
+        vchar.cc
+        )
+set_target_properties(libtest PROPERTIES LIBRARY_OUTPUT_NAME test)
+target_compile_definitions(libtest PRIVATE
+        BUILDING_LIBTEST=1
+        LIBTEST_TEMP=\"${CMAKE_BINARY_DIR}/tmp_chroot\"
+
+        DRIZZLED_BINARY=\"drizzled\"
+        GEARMAND_BINARY=\"gearmand\"
+        MEMCACHED_BINARY=\"${MEMCACHED_BINARY}\"
+        HAVE_MEMCACHED_BINARY=1
+        )
+target_link_libraries(libtest PRIVATE Threads::Threads ${CMAKE_DL_LIBS})
+
+add_executable(wait wait.cc dream.cc)
+
+add_executable(core_count core_count.cc cpu.cc)
+
+add_executable(backtrace backtrace_test.cc ../libmemcached/backtrace.cc)
+target_link_libraries(backtrace PRIVATE ${CMAKE_DL_LIBS})
+
+configure_file(yatlcon.h.in yatlcon.h @ONLY)
+configure_file(version.h.in version.h @ONLY)
diff --git a/src/libtest/alarm.cc b/src/libtest/alarm.cc
new file mode 100644 (file)
index 0000000..6193fbb
--- /dev/null
@@ -0,0 +1,102 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include <libtest/common.h>
+
+#include <sys/time.h>
+#include <cstdlib>
+
+namespace libtest {
+
+static const struct timeval default_it_value= { 600, 0 };
+static const struct timeval default_it_interval= { 0, 0 };
+static const struct itimerval defualt_timer= { default_it_interval, default_it_value };
+
+static const struct itimerval cancel_timer= { default_it_interval, default_it_interval };
+
+
+void set_alarm()
+{
+  if (setitimer(ITIMER_VIRTUAL, &defualt_timer, NULL) == -1)
+  {
+    Error << "setitimer() failed";
+  }
+}
+
+void set_alarm(long tv_sec, long tv_usec)
+{
+  // For the moment use any value to YATL_ALARM to cancel alarming.
+  if (getenv("YATL_ALARM"))
+  {
+    errno= 0;
+    tv_sec= strtol(getenv("YATL_ALARM"), (char **) NULL, 10);
+
+    if (errno != 0)
+    {
+      FATAL("Bad value for YATL_ALARM");
+    }
+    else if (tv_sec == 0)
+    {
+      cancel_alarm();
+    }
+  }
+
+#ifdef __APPLE__
+  struct timeval it_value= { time_t(tv_sec), suseconds_t(tv_usec) };
+#else
+  struct timeval it_value= { tv_sec, tv_usec };
+#endif
+
+  struct itimerval timer= { default_it_interval, it_value };
+
+  if (setitimer(ITIMER_VIRTUAL, &timer, NULL) == -1)
+  {
+    Error << "setitimer() failed";
+  }
+}
+
+void cancel_alarm()
+{
+  if (setitimer(ITIMER_VIRTUAL, &cancel_timer, NULL) == -1)
+  {
+    Error << "setitimer() failed";
+  }
+}
+
+} // namespace libtest
+
diff --git a/src/libtest/alarm.h b/src/libtest/alarm.h
new file mode 100644 (file)
index 0000000..f675c58
--- /dev/null
@@ -0,0 +1,46 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+void set_alarm(long tv_sec, long tv_usec);
+void set_alarm();
+void cancel_alarm();
+
+} // namespace libtest
+
diff --git a/src/libtest/backtrace_test.cc b/src/libtest/backtrace_test.cc
new file mode 100644 (file)
index 0000000..d4af451
--- /dev/null
@@ -0,0 +1,123 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <cerrno>
+#include <csignal>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+
+#include "libmemcached/backtrace.hpp"
+
+class Test {
+public:
+  Test()
+  {
+  }
+
+  void call_backtrace()
+  {
+    std::cerr << __func__ << std::endl;
+    custom_backtrace();
+  }
+};
+
+void SIGSEGV_handler(int sig_num, siginfo_t* info, void* ucontext)
+{
+  std::cerr << __func__ << std::endl;
+  (void)sig_num;
+  (void)info;
+  (void)ucontext;
+
+  custom_backtrace();
+}
+
+int raise_SIGSEGV()
+{
+  std::cerr << std::endl << "Calling backtrace()" << std::endl;
+  custom_backtrace();
+  std::cerr << std::endl << "Calling raise()" << std::endl;
+  return raise(SIGSEGV);
+}
+
+int layer4()
+{
+  return raise_SIGSEGV();
+}
+
+int layer3()
+{
+  return layer4();
+}
+
+int layer2()
+{
+  return layer3();
+}
+
+int layer1()
+{
+  return layer2();
+}
+
+int main(int, char **)
+{
+  Test t;
+
+  t.call_backtrace();
+
+  struct sigaction sigact;
+
+  sigact.sa_sigaction= SIGSEGV_handler;
+  sigact.sa_flags= SA_RESTART | SA_SIGINFO;
+
+  if (sigaction(SIGSEGV, &sigact, (struct sigaction *)NULL) != 0)
+  {
+    std::cerr << "error setting signal handler for " << strsignal(SIGSEGV) << "(" <<  SIGSEGV << ")" << std::endl;
+
+    exit(EXIT_FAILURE);
+  }
+
+  int ret= layer1();
+  if (ret)
+  {
+    std::cerr << "raise() " << strerror(errno) << std::endl;
+    exit(EXIT_FAILURE);
+  }
+
+  exit(EXIT_SUCCESS);
+}
diff --git a/src/libtest/binaries.cc b/src/libtest/binaries.cc
new file mode 100644 (file)
index 0000000..9adfb89
--- /dev/null
@@ -0,0 +1,41 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+namespace libtest {
+
+}
diff --git a/src/libtest/binaries.h b/src/libtest/binaries.h
new file mode 100644 (file)
index 0000000..7829f3f
--- /dev/null
@@ -0,0 +1,41 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+} // namespace libtest
diff --git a/src/libtest/blobslap_worker.cc b/src/libtest/blobslap_worker.cc
new file mode 100644 (file)
index 0000000..5100a38
--- /dev/null
@@ -0,0 +1,165 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+#include <libtest/blobslap_worker.h>
+
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+namespace libtest {
+
+class BlobslapWorker : public Server
+{
+private:
+public:
+  BlobslapWorker(in_port_t port_arg) :
+    Server("localhost", port_arg, "benchmark/blobslap_worker", true)
+  { 
+    set_pid_file();
+  }
+
+  pid_t get_pid(bool error_is_ok)
+  {
+    if (pid_file().empty())
+    {
+      Error << "pid_file was empty";
+      return -1;
+    }
+
+    Wait wait(pid_file(), 0);
+
+    if (error_is_ok and not wait.successful())
+    {
+      Error << "Pidfile was not found:" << pid_file();
+      return -1;
+    }
+
+    std::stringstream error_message;
+    pid_t ret= get_pid_from_file(pid_file(), error_message);
+
+    if (error_is_ok and is_pid_valid(ret) == false)
+    {
+      Error << error_message.str();
+    }
+
+    return ret;
+  }
+
+  bool ping()
+  {
+    if (pid_file().empty())
+    {
+      Error << "No pid file available";
+      return false;
+    }
+
+    Wait wait(pid_file(), 0);
+    if (not wait.successful())
+    {
+      Error << "Pidfile was not found:" << pid_file();
+      return false;
+    }
+
+    std::stringstream error_message;
+    pid_t local_pid= get_pid_from_file(pid_file(), error_message);
+    if (is_pid_valid(local_pid) == false)
+    {
+      Error << error_message.str();
+      return false;
+    }
+
+    // Use kill to determine is the process exist
+    if (::kill(local_pid, 0) == 0)
+    {
+      return true;
+    }
+
+    return false;
+  }
+
+  const char *name()
+  {
+    return "blobslap_worker";
+  };
+
+  bool has_port_option() const
+  {
+    return true;
+  }
+
+  bool has_log_file_option() const
+  {
+    return true;
+  }
+
+  bool is_libtool()
+  {
+    return true;
+  }
+
+  bool build();
+};
+
+
+#include <sstream>
+
+bool BlobslapWorker::build()
+{
+  return true;
+}
+
+Server *build_blobslap_worker(in_port_t try_port)
+{
+  return new BlobslapWorker(try_port);
+}
+
+} // namespace libtest
diff --git a/src/libtest/blobslap_worker.h b/src/libtest/blobslap_worker.h
new file mode 100644 (file)
index 0000000..907ae6e
--- /dev/null
@@ -0,0 +1,43 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+Server *build_blobslap_worker(in_port_t try_port);
+
+}
diff --git a/src/libtest/callbacks.h b/src/libtest/callbacks.h
new file mode 100644 (file)
index 0000000..1e617b4
--- /dev/null
@@ -0,0 +1,52 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void* (test_callback_create_fn)(libtest::server_startup_st&, test_return_t&);
+typedef bool test_callback_destroy_fn(void *);
+typedef enum test_return_t (test_callback_fn)(void *);
+typedef enum test_return_t (test_callback_runner_fn)(test_callback_fn*, void *);
+typedef enum test_return_t (test_callback_error_fn)(const test_return_t, void *);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/src/libtest/client.cc b/src/libtest/client.cc
new file mode 100644 (file)
index 0000000..c536e9d
--- /dev/null
@@ -0,0 +1,389 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <string>
+
+#ifdef HAVE_POLL_H
+# include <poll.h>
+#endif
+
+#ifndef HAVE_MSG_NOSIGNAL
+# define MSG_NOSIGNAL 0
+#endif
+
+namespace libtest {
+
+SimpleClient::SimpleClient(const std::string& hostname_, in_port_t port_) :
+  _is_connected(false),
+  _hostname(hostname_),
+  _port(port_),
+  sock_fd(INVALID_SOCKET),
+  requested_message(1)
+  {
+  }
+
+bool SimpleClient::ready(int event_)
+{
+  struct pollfd fds[1];
+  fds[0].fd= sock_fd;
+  fds[0].events= event_;
+  fds[0].revents= 0;
+
+  int timeout= 5000;
+  if (_is_connected == false)
+  {
+    timeout= timeout * 30;
+  }
+
+  int ready_fds= poll(fds, 1, timeout);
+
+  if (ready_fds == -1)
+  {
+    _error= strerror(errno);
+    return false;
+  }
+  else if (ready_fds == 1)
+  {
+    if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL))
+    {
+      int err;
+      socklen_t len= sizeof (err);
+      // We replace errno with err if getsockopt() passes, but err has been
+      // set.
+      if (getsockopt(fds[0].fd, SOL_SOCKET, SO_ERROR, &err, &len) == 0)
+      {
+        // We check the value to see what happened wth the socket.
+        if (err == 0)
+        {
+          _error= "getsockopt() returned no error but poll() indicated one existed";
+          return false;
+        }
+        errno= err;
+      }
+      _error= strerror(errno);
+
+      return false;
+    }
+
+    _is_connected= true;
+    if (fds[0].revents & event_)
+    {
+      return true;
+    }
+  }
+
+  fatal_assert(ready_fds == 0);
+  _error= "TIMEOUT";
+
+  return false;
+}
+
+struct addrinfo* SimpleClient::lookup()
+{
+  struct addrinfo *ai= NULL;
+  struct addrinfo hints;
+  memset(&hints, 0, sizeof(struct addrinfo));
+  hints.ai_socktype= SOCK_STREAM;
+  hints.ai_protocol= IPPROTO_TCP;
+
+  libtest::vchar_t service;
+  service.resize(NI_MAXSERV);
+  (void)snprintf(&service[0], service.size(), "%d", _port);
+
+  int getaddrinfo_error;
+  if ((getaddrinfo_error= getaddrinfo(_hostname.c_str(), &service[0], &hints, &ai)) != 0)
+  {
+    if (getaddrinfo_error != EAI_SYSTEM)
+    {
+      _error= gai_strerror(getaddrinfo_error);
+      return NULL;
+    }
+    else
+    {
+      _error= strerror(getaddrinfo_error);
+      return NULL;
+    }
+  }
+
+  return ai;
+}
+
+SimpleClient::~SimpleClient()
+{
+  close_socket();
+}
+
+void SimpleClient::close_socket()
+{
+  if (sock_fd != INVALID_SOCKET)
+  {
+    close(sock_fd);
+    sock_fd= INVALID_SOCKET;
+  }
+}
+
+bool SimpleClient::instance_connect()
+{
+  _is_connected= false;
+  struct addrinfo *ai;
+  if ((ai= lookup()))
+  {
+    {
+      struct addrinfo* address_info_next= ai;
+
+      while (address_info_next and sock_fd == INVALID_SOCKET)
+      {
+        if ((sock_fd= socket(address_info_next->ai_family, address_info_next->ai_socktype, address_info_next->ai_protocol)) != SOCKET_ERROR)
+        {
+          if (connect(sock_fd, address_info_next->ai_addr, address_info_next->ai_addrlen) == SOCKET_ERROR)
+          {
+            switch (errno)
+            {
+            case EINTR:
+              close_socket();
+              continue;
+
+            case EINPROGRESS: // nonblocking mode - first return
+            case EALREADY: // nonblocking mode - subsequent returns
+              continue; // Jump to while() and continue on
+
+
+            case ECONNREFUSED:
+            default:
+              break;
+            }
+
+            close_socket();
+            _error= strerror(errno);
+          }
+        }
+        else
+        {
+          FATAL(strerror(errno));
+        }
+        address_info_next= address_info_next->ai_next;
+      }
+
+      freeaddrinfo(ai);
+    }
+
+    if (sock_fd == INVALID_SOCKET)
+    {
+      fatal_assert(_error.size());
+    }
+
+    return bool(sock_fd != INVALID_SOCKET);
+  }
+
+  return false;
+}
+
+bool SimpleClient::is_valid()
+{
+  _error.clear();
+  if (sock_fd == INVALID_SOCKET)
+  {
+    return instance_connect();
+  }
+
+  return true;
+}
+
+bool SimpleClient::message(const char* ptr, const size_t len)
+{
+  if (is_valid())
+  {
+    if (ready(POLLOUT))
+    {
+      off_t offset= 0;
+      do
+      {
+        ssize_t nw= send(sock_fd, ptr + offset, len - offset, MSG_NOSIGNAL);
+        if (nw == -1)
+        {
+          if (errno != EINTR)
+          {
+            _error= strerror(errno);
+            return false;
+          }
+        }
+        else
+        {
+          offset += nw;
+        }
+      } while (offset < ssize_t(len));
+
+      return true;
+    }
+  }
+
+  fatal_assert(_error.size());
+
+  return false;
+}
+
+bool SimpleClient::send_message(const std::string& arg)
+{
+  if (message(arg.c_str(), arg.size()) == true)
+  {
+    return message("\r\n", 2);
+  }
+
+  return false;
+}
+
+bool SimpleClient::send_data(const libtest::vchar_t& message_, libtest::vchar_t& response_)
+{
+  requested_message++;
+  if (message(&message_[0], message_.size()))
+  {
+    return response(response_);
+  }
+
+  return false;
+}
+
+bool SimpleClient::send_message(const std::string& message_, std::string& response_)
+{
+  requested_message++;
+  if (send_message(message_))
+  {
+    return response(response_);
+  }
+
+  return false;
+}
+
+bool SimpleClient::response(libtest::vchar_t& response_)
+{
+  response_.clear();
+
+  if (is_valid())
+  {
+    if (ready(POLLIN))
+    {
+      bool more= true;
+      char buffer[2];
+      buffer[1]= 0;
+      do
+      {
+        ssize_t nr= recv(sock_fd, buffer, 1, MSG_NOSIGNAL);
+        if (nr == -1)
+        {
+          if (errno != EINTR)
+          {
+            _error= strerror(errno);
+            return false;
+          }
+        }
+        else if (nr == 0)
+        {
+          close_socket();
+          more= false;
+        }
+        else
+        {
+          response_.reserve(response_.size() + nr +1);
+          fatal_assert(nr == 1);
+          if (buffer[0] == '\n')
+          {
+            more= false;
+          }
+          response_.insert(response_.end(), buffer, buffer +nr);
+        }
+      } while (more);
+
+      return response_.size();
+    }
+  }
+
+  fatal_assert(_error.size());
+  return false;
+}
+
+bool SimpleClient::response(std::string& response_)
+{
+  response_.clear();
+
+  if (is_valid())
+  {
+    if (ready(POLLIN))
+    {
+      bool more= true;
+      char buffer[2];
+      buffer[1]= 0;
+      do
+      {
+        ssize_t nr= recv(sock_fd, buffer, 1, MSG_NOSIGNAL);
+        if (nr == -1)
+        {
+          if (errno != EINTR)
+          {
+            _error= strerror(errno);
+            return false;
+          }
+        }
+        else if (nr == 0)
+        {
+          close_socket();
+          more= false;
+        }
+        else
+        {
+          fatal_assert(nr == 1);
+          if (buffer[0] == '\n')
+          {
+            more= false;
+          }
+          response_.append(buffer);
+        }
+      } while (more);
+
+      return response_.size();
+    }
+  }
+
+  fatal_assert(_error.size());
+  return false;
+}
+
+} // namespace libtest
diff --git a/src/libtest/client.hpp b/src/libtest/client.hpp
new file mode 100644 (file)
index 0000000..979a532
--- /dev/null
@@ -0,0 +1,80 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+class SimpleClient {
+public:
+  SimpleClient(const std::string& hostname_, in_port_t port_);
+  ~SimpleClient();
+
+  bool send_data(const libtest::vchar_t&, libtest::vchar_t&);
+  bool send_message(const std::string&);
+  bool send_message(const std::string&, std::string&);
+  bool response(std::string&);
+  bool response(libtest::vchar_t&);
+
+  bool is_valid();
+
+  const std::string& error() const
+  {
+    return _error;
+  }
+
+  bool is_error() const
+  {
+    return _error.size() ? true : false;
+  }
+
+private: // Methods
+  void close_socket();
+  bool instance_connect();
+  struct addrinfo* lookup();
+  bool message(const char* ptr, const size_t len);
+  bool ready(int event_);
+
+private:
+  bool _is_connected;
+  std::string _hostname;
+  in_port_t _port;
+  int sock_fd;
+  std::string _error;
+  int requested_message;
+};
+
+} // namespace libtest
diff --git a/src/libtest/cmdline.cc b/src/libtest/cmdline.cc
new file mode 100644 (file)
index 0000000..375b00a
--- /dev/null
@@ -0,0 +1,868 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include "libtest/common.h"
+
+using namespace libtest;
+
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+#include <fcntl.h>
+#include <fstream>
+#include <memory>
+#ifdef HAVE_POLL_H
+# include <poll.h>
+#endif
+#ifdef HAVE_SPAWN_H
+# include <spawn.h>
+#endif
+#include <sstream>
+#include <string>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <stdexcept>
+
+#ifndef __USE_GNU
+static char **environ= NULL;
+#endif
+
+#ifndef FD_CLOEXEC
+# define FD_CLOEXEC 0
+#endif
+
+namespace {
+
+  std::string print_argv(libtest::vchar_ptr_t& built_argv)
+  {
+    std::stringstream arg_buffer;
+
+    for (vchar_ptr_t::iterator iter= built_argv.begin();
+         iter != built_argv.end();
+         ++iter)
+    {
+      if (*iter)
+      {
+        arg_buffer << *iter << " ";
+      }
+    }
+
+    return arg_buffer.str();
+  }
+
+#if 0
+  std::string print_argv(char** argv)
+  {
+    std::stringstream arg_buffer;
+
+    for (char** ptr= argv; *ptr; ++ptr)
+    {
+      arg_buffer << *ptr << " ";
+    }
+
+    return arg_buffer.str();
+  }
+#endif
+
+  static Application::error_t int_to_error_t(int arg)
+  {
+    switch (arg)
+    {
+    case 127:
+      return Application::INVALID_POSIX_SPAWN;
+
+    case 0:
+      return Application::SUCCESS;
+
+    case 1:
+      return Application::FAILURE;
+
+    default:
+      return Application::UNKNOWN;
+    }
+  }
+}
+
+namespace libtest {
+
+Application::Application(const std::string& arg, const bool _use_libtool_arg) :
+  _use_libtool(_use_libtool_arg),
+  _use_valgrind(false),
+  _use_gdb(false),
+  _use_ptrcheck(false),
+  _will_fail(false),
+  _argc(0),
+  _exectuble(arg),
+  stdin_fd(STDIN_FILENO),
+  stdout_fd(STDOUT_FILENO),
+  stderr_fd(STDERR_FILENO),
+  _pid(-1),
+  _status(0),
+  _app_exit_state(UNINITIALIZED)
+  { 
+    if (_use_libtool)
+    {
+      if (libtool() == NULL)
+      {
+        FATAL("libtool requested, but no libtool was found");
+      }
+    }
+
+    // Find just the name of the application with no path
+    {
+      size_t found= arg.find_last_of("/\\");
+      if (found)
+      {
+        _exectuble_name= arg.substr(found +1);
+      }
+      else
+      {
+        _exectuble_name= arg;
+      }
+    }
+
+    if (_use_libtool and getenv("PWD"))
+    {
+      _exectuble_with_path+= getenv("PWD");
+      _exectuble_with_path+= "/";
+    }
+    _exectuble_with_path+= _exectuble;
+  }
+
+Application::~Application()
+{
+  murder();
+  delete_argv();
+}
+
+Application::error_t Application::run(const char *args[])
+{
+  stdin_fd.reset();
+  stdout_fd.reset();
+  stderr_fd.reset();
+  _stdout_buffer.clear();
+  _stderr_buffer.clear();
+
+  posix_spawn_file_actions_t file_actions;
+  posix_spawn_file_actions_init(&file_actions);
+
+  stdin_fd.dup_for_spawn(file_actions);
+  stdout_fd.dup_for_spawn(file_actions);
+  stderr_fd.dup_for_spawn(file_actions);
+
+  posix_spawnattr_t spawnattr;
+  posix_spawnattr_init(&spawnattr);
+
+  short flags= 0;
+
+  // Child should not block signals
+  flags |= POSIX_SPAWN_SETSIGMASK;
+
+  sigset_t mask;
+  sigemptyset(&mask);
+
+  fatal_assert(posix_spawnattr_setsigmask(&spawnattr, &mask) == 0);
+
+#if defined(POSIX_SPAWN_USEVFORK) || defined(__linux__)
+  // Use USEVFORK on linux
+  flags |= POSIX_SPAWN_USEVFORK;
+#endif
+
+  flags |= POSIX_SPAWN_SETPGROUP;
+  fatal_assert(posix_spawnattr_setpgroup(&spawnattr, 0) == 0);
+
+  fatal_assert(posix_spawnattr_setflags(&spawnattr, flags) == 0);
+  
+  create_argv(args);
+
+  int spawn_ret;
+  if (_use_gdb)
+  {
+    std::string gdb_run_file= create_tmpfile(_exectuble_name);
+    std::fstream file_stream;
+    file_stream.open(gdb_run_file.c_str(), std::fstream::out | std::fstream::trunc);
+
+    _gdb_filename= create_tmpfile(_exectuble_name);
+    file_stream 
+      << "set logging redirect on" << std::endl
+      << "set logging file " << _gdb_filename << std::endl
+      << "set logging overwrite on" << std::endl
+      << "set logging on" << std::endl
+      << "set environment LIBTEST_IN_GDB=1" << std::endl
+      << "run " << arguments() << std::endl
+      << "thread apply all bt" << std::endl
+      << "quit" << std::endl;
+
+    fatal_assert(file_stream.good());
+    file_stream.close();
+
+    if (_use_libtool)
+    {
+      // libtool --mode=execute gdb -f -x binary
+      char *argv[]= {
+        const_cast<char *>(libtool()),
+        const_cast<char *>("--mode=execute"),
+        const_cast<char *>("gdb"),
+        const_cast<char *>("-batch"),
+        const_cast<char *>("-f"),
+        const_cast<char *>("-x"),
+        const_cast<char *>(gdb_run_file.c_str()), 
+        const_cast<char *>(_exectuble_with_path.c_str()), 
+        0};
+
+      spawn_ret= posix_spawnp(&_pid, libtool(), &file_actions, &spawnattr, argv, environ);
+    }
+    else
+    {
+      // gdb binary
+      char *argv[]= {
+        const_cast<char *>("gdb"),
+        const_cast<char *>("-batch"),
+        const_cast<char *>("-f"),
+        const_cast<char *>("-x"),
+        const_cast<char *>(gdb_run_file.c_str()), 
+        const_cast<char *>(_exectuble_with_path.c_str()), 
+        0};
+      spawn_ret= posix_spawnp(&_pid, "gdb", &file_actions, &spawnattr, argv, environ);
+    }
+  }
+  else
+  {
+    spawn_ret= posix_spawn(&_pid, built_argv[0], &file_actions, &spawnattr, &built_argv[0], environ);
+  }
+
+  posix_spawn_file_actions_destroy(&file_actions);
+  posix_spawnattr_destroy(&spawnattr);
+
+  stdin_fd.close(Application::Pipe::READ);
+  stdout_fd.close(Application::Pipe::WRITE);
+  stderr_fd.close(Application::Pipe::WRITE);
+
+  if (spawn_ret != 0)
+  {
+    if (_will_fail == false)
+    {
+      std::string sb;
+      char buf[1024];
+
+      std::for_each(built_argv.begin(), built_argv.end()-1, [&sb](const char *a) {
+        if (sb.size()) {
+          sb.append(" ");
+        }
+        sb.append(a);
+      });
+      Error << strerror(spawn_ret) << "(" << spawn_ret << "): " << sb << " cwd:" << getcwd(buf, sizeof(buf)-1);
+    }
+    _pid= -1;
+    return Application::INVALID_POSIX_SPAWN;
+  }
+
+  assert(_pid != -1);
+  if (_pid == -1)
+  {
+    return Application::INVALID_POSIX_SPAWN;
+  }
+
+#if 0
+  app_thread_st* _app_thread= new app_thread_st(_pid, _status, built_argv[0], _app_exit_state);
+  int error;
+  if ((error= pthread_create(&_thread, NULL, &app_thread, _app_thread)) != 0)
+  {
+    Error << "pthread_create() died during pthread_create(" << strerror(error) << ")";
+    return Application::FAILURE;
+  }
+#endif
+
+  return Application::SUCCESS;
+}
+
+bool Application::check() const
+{
+  if (_pid > 1 and kill(_pid, 0) == 0)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+void Application::murder()
+{
+  if (check())
+  {
+    int count= 5;
+    while ((count--) > 0 and check())
+    {
+      if (kill(_pid, SIGTERM) == 0)
+      {
+        join();
+      }
+      else
+      {
+        Error << "kill(pid, SIGTERM) failed after kill with error of " << strerror(errno);
+        continue;
+      }
+
+      break;
+    }
+
+    // If for whatever reason it lives, kill it hard
+    if (check())
+    {
+      Error << "using SIGKILL, things will likely go poorly from this point";
+      (void)kill(_pid, SIGKILL);
+    }
+  }
+  slurp();
+}
+
+// false means that no data was returned
+bool Application::slurp()
+{
+  struct pollfd fds[2];
+  fds[0].fd= stdout_fd.fd();
+  fds[0].events= POLLRDNORM;
+  fds[0].revents= 0;
+  fds[1].fd= stderr_fd.fd();
+  fds[1].events= POLLRDNORM;
+  fds[1].revents= 0;
+
+  int active_fd;
+  if ((active_fd= poll(fds, 2, 0)) == -1)
+  {
+    int error;
+    switch ((error= errno))
+    {
+#ifdef __linux
+    case ERESTART:
+#endif
+    case EINTR:
+      break;
+
+    case EFAULT:
+    case ENOMEM:
+      FATAL(strerror(error));
+      break;
+
+    case EINVAL:
+      FATAL("RLIMIT_NOFILE exceeded, or if OSX the timeout value was invalid");
+      break;
+
+    default:
+      FATAL(strerror(error));
+      break;
+    }
+
+    return false;
+  }
+
+  if (active_fd == 0)
+  {
+    return false;
+  }
+
+  bool data_was_read= false;
+  if (fds[0].revents & POLLRDNORM)
+  {
+    if (stdout_fd.read(_stdout_buffer) == true)
+    {
+      data_was_read= true;
+    }
+  }
+
+  if (fds[1].revents & POLLRDNORM)
+  {
+    if (stderr_fd.read(_stderr_buffer) == true)
+    {
+      data_was_read= true;
+    }
+  }
+
+  return data_was_read;
+}
+
+std::pair<std::string, std::string> Application::output()
+{
+  slurp();
+  return {
+      std::string {
+          stdout_result().data(),
+          stdout_result().size()
+      },
+      std::string {
+          stderr_result().data(),
+          stderr_result().size()
+      }
+  };
+
+}
+
+Application::error_t Application::join()
+{
+  pid_t waited_pid= waitpid(_pid, &_status, WUNTRACED);
+  slurp();
+  if (waited_pid == _pid and WIFEXITED(_status) == false)
+  {
+    /*
+      What we are looking for here is how the exit status happened.
+      - 127 means that posix_spawn() itself had an error.
+      - If WEXITSTATUS is positive we need to see if it is a signal that we sent to kill the process. If not something bad happened in the process itself. 
+      - Finally something has happened that we don't currently understand.
+    */
+    if (WEXITSTATUS(_status) == 127)
+    {
+      _app_exit_state= Application::INVALID_POSIX_SPAWN;
+      std::string error_string("posix_spawn() failed pid:");
+      error_string+= _pid;
+      error_string+= " name:";
+      error_string+= print_argv(built_argv);
+      if (stderr_result_length())
+      {
+        error_string+= " stderr: ";
+        error_string+= stderr_c_str();
+      }
+      throw std::logic_error(error_string);
+    }
+    else if (WIFSIGNALED(_status))
+    {
+      if (WTERMSIG(_status) != SIGTERM and WTERMSIG(_status) != SIGHUP)
+      {
+        slurp();
+        _app_exit_state= Application::INVALID_POSIX_SPAWN;
+        std::string error_string(print_argv(built_argv));
+        error_string+= " was killed by signal ";
+        error_string+= strsignal(WTERMSIG(_status));
+
+        if (stdout_result_length())
+        {
+          error_string+= " stdout: ";
+          error_string+= stdout_c_str();
+        }
+
+        if (stderr_result_length())
+        {
+          error_string+= " stderr: ";
+          error_string+= stderr_c_str();
+        }
+
+        throw std::runtime_error(error_string);
+      }
+
+      // If we terminted it on purpose then it counts as a success.
+#if defined(DEBUG)
+      if (DEBUG)
+      {
+        Out << "waitpid() application terminated at request"
+          << " pid:" << _pid 
+          << " name:" << built_argv[0];
+      }
+#endif
+    }
+    else
+    {
+      _app_exit_state= Application::UNKNOWN;
+      Error << "Unknown logic state at exit:" << WEXITSTATUS(_status) 
+        << " pid:" << _pid
+        << " name:" << built_argv[0];
+    }
+  }
+  else if (waited_pid == _pid and WIFEXITED(_status))
+  {
+    _app_exit_state= int_to_error_t(WEXITSTATUS(_status));
+  }
+  else if (waited_pid == -1)
+  {
+    std::string error_string;
+    if (stdout_result_length())
+    {
+      error_string+= " stdout: ";
+      error_string+= stdout_c_str();
+    }
+
+    if (stderr_result_length())
+    {
+      error_string+= " stderr: ";
+      error_string+= stderr_c_str();
+    }
+    Error << "waitpid() returned errno:" << strerror(errno) << " " << error_string;
+    _app_exit_state= Application::UNKNOWN;
+  }
+  else
+  {
+    _app_exit_state= Application::UNKNOWN;
+    throw std::logic_error("waitpid() returned an unknown value");
+  }
+
+  return _app_exit_state;
+}
+
+void Application::add_long_option(const std::string& name, const std::string& option_value)
+{
+  std::string arg(name);
+  arg+= option_value;
+  _options.push_back(std::make_pair(arg, std::string()));
+}
+
+void Application::add_option(const std::string& arg)
+{
+  _options.push_back(std::make_pair(arg, std::string()));
+}
+
+void Application::add_option(const std::string& name, const std::string& value)
+{
+  _options.push_back(std::make_pair(name, value));
+}
+
+Application::Pipe::Pipe(int arg) :
+  _std_fd(arg)
+{
+  _pipe_fd[READ]= -1;
+  _pipe_fd[WRITE]= -1;
+  _open[READ]= false;
+  _open[WRITE]= false;
+}
+
+int Application::Pipe::Pipe::fd()
+{
+  if (_std_fd == STDOUT_FILENO)
+  {
+    return _pipe_fd[READ];
+  }
+  else if (_std_fd == STDERR_FILENO)
+  {
+    return _pipe_fd[READ];
+  }
+
+  return _pipe_fd[WRITE]; // STDIN_FILENO
+}
+
+
+bool Application::Pipe::read(libtest::vchar_t& arg)
+{
+  fatal_assert(_std_fd == STDOUT_FILENO or _std_fd == STDERR_FILENO);
+
+  bool data_was_read= false;
+
+  libtest::vchar_t buffer;
+  buffer.resize(1024);
+  ssize_t read_length;
+  while ((read_length= ::read(_pipe_fd[READ], &buffer[0], buffer.size())))
+  {
+    if (read_length == -1)
+    {
+      switch(errno)
+      {
+      case EAGAIN:
+        break;
+
+      default:
+        Error << strerror(errno);
+        break;
+      }
+
+      break;
+    }
+
+    data_was_read= true;
+    arg.reserve(read_length +1);
+    for (size_t x= 0; x < size_t(read_length); ++x)
+    {
+      arg.push_back(buffer[x]);
+    }
+    // @todo Suck up all errput code here
+  }
+
+  return data_was_read;
+}
+
+void Application::Pipe::nonblock()
+{
+  int flags;
+  do 
+  {
+    flags= fcntl(_pipe_fd[READ], F_GETFL, 0);
+  } while (flags == -1 and (errno == EINTR or errno == EAGAIN));
+
+  if (flags == -1)
+  {
+    Error << "fcntl(F_GETFL) " << strerror(errno);
+    throw strerror(errno);
+  }
+
+  int rval;
+  do
+  {
+    rval= fcntl(_pipe_fd[READ], F_SETFL, flags | O_NONBLOCK);
+  } while (rval == -1 and (errno == EINTR or errno == EAGAIN));
+
+  if (rval == -1)
+  {
+    Error << "fcntl(F_SETFL) " << strerror(errno);
+    throw strerror(errno);
+  }
+}
+
+void Application::Pipe::reset()
+{
+  close(READ);
+  close(WRITE);
+
+#ifdef HAVE_PIPE2
+  if (pipe2(_pipe_fd, O_NONBLOCK|O_CLOEXEC) == -1)
+#endif
+  {
+    if (pipe(_pipe_fd) == -1)
+    {
+      FATAL(strerror(errno));
+    }
+
+    // Since either pipe2() was not found/called we set the pipe directly
+    nonblock();
+    cloexec();
+  }
+  _open[0]= true;
+  _open[1]= true;
+}
+
+void Application::Pipe::cloexec()
+{
+  //if (SOCK_CLOEXEC == 0)
+  {
+    if (FD_CLOEXEC) 
+    {
+      int flags;
+      do 
+      {
+        flags= fcntl(_pipe_fd[WRITE], F_GETFD, 0);
+      } while (flags == -1 and (errno == EINTR or errno == EAGAIN));
+
+      if (flags == -1)
+      {
+        Error << "fcntl(F_GETFD) " << strerror(errno);
+        throw strerror(errno);
+      }
+
+      int rval;
+      do
+      { 
+        rval= fcntl(_pipe_fd[WRITE], F_SETFD, flags | FD_CLOEXEC);
+      } while (rval == -1 && (errno == EINTR or errno == EAGAIN));
+
+      if (rval == -1)
+      {
+        Error << "fcntl(F_SETFD) " << strerror(errno);
+        throw strerror(errno);
+      }
+    }
+  }
+}
+
+Application::Pipe::~Pipe()
+{
+  if (_pipe_fd[0] != -1)
+  {
+    ::close(_pipe_fd[0]);
+  }
+
+  if (_pipe_fd[1] != -1)
+  {
+    ::close(_pipe_fd[1]);
+  }
+}
+
+void Application::Pipe::dup_for_spawn(posix_spawn_file_actions_t& file_actions)
+{
+  int type= STDIN_FILENO == _std_fd ? 0 : 1;
+
+  int ret;
+  if ((ret= posix_spawn_file_actions_adddup2(&file_actions, _pipe_fd[type], _std_fd )) < 0)
+  {
+    FATAL("posix_spawn_file_actions_adddup2(%s)", strerror(ret));
+  }
+
+  if ((ret= posix_spawn_file_actions_addclose(&file_actions, _pipe_fd[type])) < 0)
+  {
+    FATAL("posix_spawn_file_actions_addclose(%s)", strerror(ret));
+  }
+}
+
+void Application::Pipe::close(const close_t& arg)
+{
+  int type= int(arg);
+
+  if (_open[type])
+  {
+    if (::close(_pipe_fd[type]) == -1)
+    {
+      Error << "close(" << strerror(errno) << ")";
+    }
+    _open[type]= false;
+    _pipe_fd[type]= -1;
+  }
+}
+
+void Application::create_argv(const char *args[])
+{
+  delete_argv();
+  if (_use_libtool)
+  {
+    assert(libtool());
+    vchar::append(built_argv, libtool());
+    vchar::append(built_argv, "--mode=execute");
+  }
+
+  if (_use_valgrind)
+  {
+    /*
+      valgrind --error-exitcode=1 --leak-check=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE
+    */
+    vchar::append(built_argv, "valgrind");
+    vchar::append(built_argv, "--error-exitcode=1");
+    vchar::append(built_argv, "--leak-check=yes");
+#if 0
+    vchar::append(built_argv, "--show-reachable=yes"));
+#endif
+    vchar::append(built_argv, "--track-fds=yes");
+#if 0
+    built_argv[x++]= strdup("--track-origin=yes");
+#endif
+    vchar::append(built_argv, "--malloc-fill=A5");
+    vchar::append(built_argv, "--free-fill=DE");
+
+    std::string log_file= create_tmpfile("valgrind");
+    libtest::vchar_t buffer;
+    buffer.resize(1024);
+    int length= snprintf(&buffer[0], buffer.size(), "--log-file=%s", log_file.c_str());
+    fatal_assert(length > 0 and size_t(length) < buffer.size());
+    vchar::append(built_argv, &buffer[0]);
+  }
+  else if (_use_ptrcheck)
+  {
+    /*
+      valgrind --error-exitcode=1 --tool=exp-ptrcheck --log-file= 
+    */
+    vchar::append(built_argv, "valgrind");
+    vchar::append(built_argv, "--error-exitcode=1");
+    vchar::append(built_argv, "--tool=exp-ptrcheck");
+    std::string log_file= create_tmpfile("ptrcheck");
+    libtest::vchar_t buffer;
+    buffer.resize(1024);
+    int length= snprintf(&buffer[0], buffer.size(), "--log-file=%s", log_file.c_str());
+    fatal_assert(length > 0 and size_t(length) < buffer.size());
+    vchar::append(built_argv, &buffer[0]);
+  }
+  else if (_use_gdb)
+  {
+    vchar::append(built_argv, "gdb");
+  }
+
+  vchar::append(built_argv, _exectuble_with_path.c_str());
+
+  for (Options::const_iterator iter= _options.begin(); iter != _options.end(); ++iter)
+  {
+    vchar::append(built_argv, (*iter).first.c_str());
+    if ((*iter).second.empty() == false)
+    {
+      vchar::append(built_argv, (*iter).second.c_str());
+    }
+  }
+
+  if (args)
+  {
+    for (const char **ptr= args; *ptr; ++ptr)
+    {
+      vchar::append(built_argv, *ptr);
+    }
+  }
+  built_argv.push_back(nullptr);
+}
+
+std::string Application::print()
+{
+  return print_argv(built_argv);
+}
+
+std::string Application::arguments()
+{
+  std::stringstream arg_buffer;
+
+  // Skip printing out the libtool reference
+  for (size_t x= _use_libtool ? 2 : 0; x < _argc; ++x)
+  {
+    if (built_argv[x])
+    {
+      arg_buffer << built_argv[x] << " ";
+    }
+  }
+
+  return arg_buffer.str();
+}
+
+void Application::delete_argv()
+{
+  std::for_each(built_argv.begin(), built_argv.end(), FreeFromVector());
+
+  built_argv.clear();
+  _argc= 0;
+}
+
+
+int exec_cmdline(const std::string& command, const char *args[], bool use_libtool)
+{
+  Application app(command, use_libtool);
+
+  Application::error_t ret= app.run(args);
+
+  if (Application::SUCCESS == ret) {
+    ret = app.join();
+  }
+
+  if (ret != Application::SUCCESS)
+  {
+    auto out = app.output();
+    Error << command << " stdout: " << out.first;
+    Error << command << " stderr: " << out.second;
+  }
+
+  return int(ret);
+}
+
+} // namespace exec_cmdline
diff --git a/src/libtest/cmdline.h b/src/libtest/cmdline.h
new file mode 100644 (file)
index 0000000..244c646
--- /dev/null
@@ -0,0 +1,256 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <spawn.h>
+
+// http://www.gnu.org/software/automake/manual/automake.html#Using-the-TAP-test-protocol
+#ifndef EXIT_SKIP
+# define EXIT_SKIP 77
+#endif
+
+#ifndef EXIT_FATAL
+# define EXIT_FATAL 99
+#endif
+
+#ifndef EX_NOEXEC
+# define EX_NOEXEC 126
+#endif
+
+#ifndef EX_NOTFOUND
+# define EX_NOTFOUND 127
+#endif
+
+namespace libtest {
+
+class Application {
+private:
+  typedef std::vector< std::pair<std::string, std::string> > Options;
+
+public:
+
+  enum error_t {
+    SUCCESS= EXIT_SUCCESS,
+    FAILURE= EXIT_FAILURE,
+    UNINITIALIZED,
+    SIGTERM_KILLED,
+    UNKNOWN,
+    UNKNOWN_SIGNAL,
+    INVALID_POSIX_SPAWN= 127
+  };
+
+  static const char* toString(error_t arg)
+  {
+    switch (arg)
+    {
+    case Application::SUCCESS:
+      return "EXIT_SUCCESS";
+
+    case Application::UNINITIALIZED:
+      return "UNINITIALIZED";
+
+    case Application::SIGTERM_KILLED:
+      return "Exit happened via SIGTERM";
+
+    case Application::FAILURE:
+      return "EXIT_FAILURE";
+
+    case Application::UNKNOWN_SIGNAL:
+      return "Exit happened via a signal which was not SIGTERM";
+
+    case Application::INVALID_POSIX_SPAWN:
+      return "127: Invalid call to posix_spawn()";
+
+    case Application::UNKNOWN:
+    default:
+      break;
+    }
+
+    return "EXIT_UNKNOWN";
+  }
+
+  class Pipe {
+  public:
+    Pipe(int);
+    ~Pipe();
+
+    int fd();
+
+    enum close_t {
+      READ= 0,
+      WRITE= 1
+    };
+
+    void reset();
+    void close(const close_t& arg);
+    void dup_for_spawn(posix_spawn_file_actions_t& file_actions);
+
+    void nonblock();
+    void cloexec();
+    bool read(libtest::vchar_t&);
+
+  private:
+    const int _std_fd;
+    int _pipe_fd[2];
+    bool _open[2];
+  };
+
+public:
+  Application(const std::string& arg, const bool _use_libtool_arg= false);
+
+  virtual ~Application();
+
+  void add_option(const std::string&);
+  void add_option(const std::string&, const std::string&);
+  void add_long_option(const std::string& option_name, const std::string& option_value);
+  error_t run(const char *args[]= NULL);
+  Application::error_t join();
+
+  libtest::vchar_t stdout_result() const
+  {
+    return _stdout_buffer;
+  }
+
+  size_t stdout_result_length() const
+  {
+    return _stdout_buffer.size();
+  }
+
+  const char* stdout_c_str() const
+  {
+    return &_stdout_buffer[0];
+  }
+
+  libtest::vchar_t stderr_result() const
+  {
+    return _stderr_buffer;
+  }
+
+  const char* stderr_c_str() const
+  {
+    return &_stderr_buffer[0];
+  }
+
+  size_t stderr_result_length() const
+  {
+    return _stderr_buffer.size();
+  }
+
+  std::string print();
+
+  void use_valgrind(bool arg)
+  {
+    _use_valgrind= arg;
+  }
+
+  bool check() const;
+
+  bool slurp();
+  std::pair<std::string, std::string> output();
+  void murder();
+
+  void clear()
+  {
+    slurp();
+    _stdout_buffer.clear();
+    _stderr_buffer.clear();
+  }
+
+  void use_gdb(bool arg)
+  {
+    _use_gdb= arg;
+  }
+
+  void use_ptrcheck(bool arg)
+  {
+    _use_ptrcheck= arg;
+  }
+
+  std::string arguments();
+
+  std::string gdb_filename()
+  {
+    return  _gdb_filename;
+  }
+
+  pid_t pid() const
+  {
+    return _pid;
+  }
+
+  void will_fail()
+  {
+    _will_fail= true;
+  }
+
+private:
+  void create_argv(const char *args[]);
+  void delete_argv();
+  void add_to_build_argv(const char*);
+
+private:
+  const bool _use_libtool;
+  bool _use_valgrind;
+  bool _use_gdb;
+  bool _use_ptrcheck;
+  bool _will_fail;
+  size_t _argc;
+  std::string _exectuble_name;
+  std::string _exectuble;
+  std::string _exectuble_with_path;
+  std::string _gdb_filename;
+  Options _options;
+  Pipe stdin_fd;
+  Pipe stdout_fd;
+  Pipe stderr_fd;
+  libtest::vchar_ptr_t built_argv;
+  pid_t _pid;
+  libtest::vchar_t _stdout_buffer;
+  libtest::vchar_t _stderr_buffer;
+  int _status;
+  pthread_t _thread;
+  error_t _app_exit_state;
+};
+
+static inline std::ostream& operator<<(std::ostream& output, const enum Application::error_t &arg)
+{
+  return output << Application::toString(arg);
+}
+
+int exec_cmdline(const std::string& executable, const char *args[], bool use_libtool= false);
+
+}
diff --git a/src/libtest/collection.cc b/src/libtest/collection.cc
new file mode 100644 (file)
index 0000000..ff9c886
--- /dev/null
@@ -0,0 +1,216 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include <libtest/common.h>
+
+// @todo possibly have this code fork off so if it fails nothing goes bad
+static test_return_t runner_code(libtest::Framework* frame,
+                                 test_st* run, 
+                                 libtest::Timer& _timer)
+{ // Runner Code
+
+  assert(frame->runner());
+  assert(run->test_fn);
+
+  test_return_t return_code;
+  try 
+  {
+    _timer.reset();
+    assert(frame);
+    assert(frame->runner());
+    assert(run->test_fn);
+    return_code= frame->runner()->main(run->test_fn, frame->creators_ptr());
+  }
+  // Special case where check for the testing of the exception
+  // system.
+  catch (const libtest::fatal& e)
+  {
+    if (libtest::fatal::is_disabled())
+    {
+      libtest::fatal::increment_disabled_counter();
+      return_code= TEST_SUCCESS;
+    }
+    else
+    {
+      throw;
+    }
+  }
+
+  _timer.sample();
+
+  return return_code;
+}
+
+namespace libtest {
+
+Collection::Collection(Framework* frame_arg,
+                       collection_st* arg) :
+  _name(arg->name),
+  _pre(arg->pre),
+  _post(arg->post),
+  _tests(arg->tests),
+  _frame(frame_arg),
+  _success(0),
+  _skipped(0),
+  _failed(0),
+  _total(0),
+  _formatter(frame_arg->name(), _name)
+{
+  fatal_assert(arg);
+}
+
+test_return_t Collection::exec()
+{
+  if (test_success(_frame->runner()->setup(_pre, _frame->creators_ptr())))
+  {
+    for (test_st *run= _tests; run->name; run++)
+    {
+      formatter()->push_testcase(run->name);
+      if (_frame->match(run->name))
+      {
+        formatter()->skipped();
+        continue;
+      }
+      _total++;
+
+      test_return_t return_code;
+      try 
+      {
+        if (run->requires_flush)
+        {
+          if (test_failed(_frame->runner()->flush(_frame->creators_ptr())))
+          {
+            Error << "frame->runner()->flush(creators_ptr)";
+            _skipped++;
+            formatter()->skipped();
+            continue;
+          }
+        }
+
+        set_alarm();
+
+        try 
+        {
+          return_code= runner_code(_frame, run, _timer);
+        }
+        catch (...)
+        {
+          cancel_alarm();
+
+          throw;
+        }
+        libtest::cancel_alarm();
+      }
+      catch (const libtest::fatal& e)
+      {
+        _failed++;
+        formatter()->failed();
+        stream::make_cerr err(e.file(), e.line(), e.func());
+        err << e.what();
+        for (auto server : _frame->servers().servers)
+        {
+          auto output = server->output();
+          if (output.first.size())
+          {
+            err << "Server(" << server->port() << ") stdout:\n" << output.first << "\n";
+          }
+          if (output.second.size())
+          {
+            err << "Server(" << server->port() << ") stderr:\n" << output.second << "\n";
+          }
+        }
+        throw;
+      }
+
+      switch (return_code)
+      {
+      case TEST_SUCCESS:
+        _success++;
+        formatter()->success(_timer);
+        break;
+
+      case TEST_FAILURE:
+        _failed++;
+        formatter()->failed();
+        for (auto server : _frame->servers().servers)
+        {
+          auto output = server->output();
+          if (output.first.size())
+          {
+            Out << "Server(" << server->port() << ") stdout:\n" << output.first << "\n";
+          }
+          if (output.second.size())
+          {
+            Out << "Server(" << server->port() << ") stderr:\n" << output.second << "\n";
+          }
+        }
+        break;
+
+      case TEST_SKIPPED:
+        _skipped++;
+        formatter()->skipped();
+        break;
+
+      default:
+        FATAL("invalid return code");
+      }
+#if 0
+      @TODO add code here to allow for a collection to define a method to reset to allow tests to continue.
+#endif
+    }
+
+    (void) _frame->runner()->teardown(_post, _frame->creators_ptr());
+  }
+
+  if (_failed == 0 and _skipped == 0 and _success)
+  {
+    return TEST_SUCCESS;
+  }
+
+  if (_failed)
+  {
+    return TEST_FAILURE;
+  }
+
+  fatal_assert(_skipped or _success == 0);
+
+  return TEST_SKIPPED;
+}
+
+} // namespace libtest
+
diff --git a/src/libtest/collection.h b/src/libtest/collection.h
new file mode 100644 (file)
index 0000000..a9f9cba
--- /dev/null
@@ -0,0 +1,112 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libtest/formatter.hpp>
+
+#include <libtest/timer.hpp>
+
+namespace { class Framework; }
+
+
+/**
+  A structure which describes a collection of test cases.
+*/
+struct collection_st {
+  const char *name;
+  test_callback_fn *pre;
+  test_callback_fn *post;
+  struct test_st *tests;
+};
+
+namespace libtest {
+
+class Collection {
+public:
+  Collection(libtest::Framework*, collection_st*);
+
+  test_return_t exec();
+
+  const char* name()
+  {
+    return _name.c_str();
+  }
+
+  uint32_t success()
+  {
+    return _success;
+  }
+
+  uint32_t skipped()
+  {
+    return _skipped;
+  }
+
+  uint32_t failed()
+  {
+    return _failed;
+  }
+
+  uint32_t total()
+  {
+    return _total;
+  }
+
+  libtest::Formatter* formatter()
+  {
+    return &_formatter;
+  }
+
+private:
+  std::string _name;
+  test_callback_fn *_pre;
+  test_callback_fn *_post;
+  struct test_st *_tests;
+  libtest::Framework* _frame;
+  uint32_t _success;
+  uint32_t _skipped;
+  uint32_t _failed;
+  uint32_t _total;
+  libtest::Timer _timer;
+  libtest::Formatter _formatter;
+
+private:
+  Collection( const Collection& );
+  const Collection& operator=( const Collection& );
+};
+
+} // namespace libtest
diff --git a/src/libtest/common.h b/src/libtest/common.h
new file mode 100644 (file)
index 0000000..90d8b6a
--- /dev/null
@@ -0,0 +1,121 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/*
+  Common include file for libtest
+*/
+
+#pragma once
+
+#include <cassert>
+#include <cerrno>
+#include <cstdlib>
+#include <sstream>
+#include <string>
+
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#endif
+
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H 
+# include <sys/resource.h> 
+#endif
+#ifdef HAVE_FNMATCH_H
+# include <fnmatch.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+#if defined(WIN32)
+# include "win32/wrappers.h"
+# define get_socket_errno() WSAGetLastError()
+#else
+# ifdef HAVE_UNISTD_H
+#  include <unistd.h>
+# endif
+# define INVALID_SOCKET -1
+# define SOCKET_ERROR -1
+# define closesocket(a) close(a)
+# define get_socket_errno() errno
+#endif
+
+#include <libtest/test.hpp>
+
+#include <libtest/is_pid.hpp>
+
+#include <libtest/gearmand.h>
+#include <libtest/blobslap_worker.h>
+#include <libtest/memcached.h>
+#include <libtest/drizzled.h>
+
+#include <libtest/libtool.hpp>
+#include <libtest/killpid.h>
+#include <libtest/signal.h>
+#include <libtest/dns.hpp>
+#include <libtest/formatter.hpp>
+
+struct FreeFromVector
+{
+  template <class T>
+    void operator() ( T* ptr) const
+    {
+      if (ptr)
+      {
+        free(ptr);
+        ptr= NULL;
+      }
+    }
+};
+
+struct DeleteFromVector
+{
+  template <class T>
+    void operator() ( T* ptr) const
+    {
+      delete ptr;
+      ptr= NULL;
+    }
+};
diff --git a/src/libtest/comparison.cc b/src/libtest/comparison.cc
new file mode 100644 (file)
index 0000000..c0c2193
--- /dev/null
@@ -0,0 +1,87 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+namespace libtest {
+
+bool jenkins_is_caller(void)
+{
+  if (bool(getenv("JENKINS_HOME")))
+  {
+    return true;
+  }
+
+  return false;
+}
+
+bool gdb_is_caller(void)
+{
+  if (bool(getenv("LOG_COMPILER")) and strstr(getenv("LOG_COMPILER"), "gdb"))
+  {
+    return true;
+  }
+
+  if (bool(getenv("LIBTEST_IN_GDB")))
+  {
+    return true;
+  }
+
+  return false;
+}
+
+bool helgrind_is_caller(void)
+{
+  if (bool(getenv("LOG_COMPILER")) and strstr(getenv("LOG_COMPILER"), "helgrind"))
+  {
+    return true;
+  }
+
+  return false;
+}
+
+bool _in_valgrind(const char*, int, const char*)
+{
+  if (valgrind_is_caller())
+  {
+    return true;
+  }
+
+  return false;
+}
+
+} // namespace libtest
diff --git a/src/libtest/comparison.hpp b/src/libtest/comparison.hpp
new file mode 100644 (file)
index 0000000..9a7d81c
--- /dev/null
@@ -0,0 +1,160 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <typeinfo>
+
+#if defined(HAVE_LIBMEMCACHED) && HAVE_LIBMEMCACHED
+#include <libmemcached-1.0/memcached.h>
+#include <libmemcachedutil-1.0/ostream.hpp>
+#include <libtest/memcached.hpp>
+#endif
+
+#if defined(HAVE_LIBGEARMAN) && HAVE_LIBGEARMAN
+#include <libgearman-1.0/ostream.hpp>
+#endif
+
+namespace libtest {
+
+LIBTEST_API
+bool jenkins_is_caller(void);
+
+LIBTEST_API
+bool gdb_is_caller(void);
+
+LIBTEST_API
+bool _in_valgrind(const char *file, int line, const char *func);
+
+LIBTEST_API
+bool helgrind_is_caller(void);
+
+template <class T_comparable>
+bool _compare_truth(const char *file, int line, const char *func, T_comparable __expected, const char *assertation_label)
+{
+  if (__expected == false)
+  {
+    libtest::stream::make_cerr(file, line, func) << "Assertation  \"" << assertation_label << "\"";
+    return false;
+  }
+
+  return true;
+}
+
+template <class T1_comparable, class T2_comparable>
+bool _compare(const char *file, int line, const char *func, const T1_comparable& __expected, const T2_comparable& __actual, bool use_io)
+{
+  if (__expected != __actual)
+  {
+    if (use_io)
+    {
+      libtest::stream::make_cerr(file, line, func) << "Expected \"" << __expected << "\" got \"" << __actual << "\"";
+    }
+
+    return false;
+  }
+
+  return true;
+}
+
+template <class T1_comparable, class T2_comparable>
+bool _compare_strcmp(const char *file, int line, const char *func, const T1_comparable *__expected, const T2_comparable *__actual)
+{
+  if (__expected == NULL)
+  {
+    FATAL("Expected value was NULL, programmer error");
+  }
+
+  if (__actual == NULL)
+  {
+    libtest::stream::make_cerr(file, line, func) << "Expected " << __expected << " but got NULL";
+    return false;
+  }
+
+  if (strncmp(__expected, __actual, strlen(__expected)))
+  {
+    libtest::stream::make_cerr(file, line, func) << "Expected " << __expected << " passed \"" << __actual << "\"";
+    return false;
+  }
+
+  return true;
+}
+
+template <class T_comparable>
+bool _compare_zero(const char *file, int line, const char *func, T_comparable __actual)
+{
+  if (T_comparable(0) != __actual)
+  {
+    libtest::stream::make_cerr(file, line, func) << "Expected 0 got \"" << __actual << "\"";
+    return false;
+  }
+
+  return true;
+}
+
+template <class T1_comparable, class T2_comparable>
+bool _ne_compare(const char *file, int line, const char *func, T1_comparable __expected, T2_comparable __actual, bool io_error= true)
+{
+  if (__expected == __actual)
+  {
+    if (io_error)
+    {
+      libtest::stream::make_cerr(file, line, func) << "Expected \"" << __expected << "\" got \"" << __actual << "\"";
+    }
+
+    return false;
+  }
+
+  return true;
+}
+
+template <class T_comparable, class T_expression_string>
+bool _assert_truth(const char *file, int line, const char *func, T_comparable __truth, T_expression_string __expression, const char* __explain= NULL)
+{
+  if (__truth)
+  {
+    return true;
+  }
+
+  if (__explain)
+  {
+    libtest::stream::make_cerr(file, line, func) << "Assertion \"" << __expression << "\" warning:" << __explain;
+  }
+
+  return false;
+}
+
+} // namespace libtest
diff --git a/src/libtest/core.cc b/src/libtest/core.cc
new file mode 100644 (file)
index 0000000..2542f43
--- /dev/null
@@ -0,0 +1,66 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+
+namespace libtest {
+
+void create_core(void)
+{
+#if defined(__APPLE__) && __APPLE__
+  if (__APPLE__)
+  {
+    return;
+  }
+#endif
+  if (getenv("YATL_COREDUMP"))
+  {
+    pid_t pid= fork();
+
+    if (pid == 0)
+    {
+      abort();
+    }
+    else
+    {
+      while (waitpid(pid, NULL, 0) != pid) {};
+    }
+  }
+}
+
+} // namespace libtest
diff --git a/src/libtest/core.h b/src/libtest/core.h
new file mode 100644 (file)
index 0000000..654fcaf
--- /dev/null
@@ -0,0 +1,44 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+LIBTEST_API
+void create_core(void);
+
+} // namespace libtest
diff --git a/src/libtest/core_count.cc b/src/libtest/core_count.cc
new file mode 100644 (file)
index 0000000..36ebc22
--- /dev/null
@@ -0,0 +1,135 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include <cstdlib>
+#include <fcntl.h>
+#include <getopt.h>
+#include <iostream>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <libtest/cpu.hpp>
+
+static void version_command(const char *command_name, int major_version, int minor_version)
+{
+  std::cout << command_name << " " << major_version << "." << minor_version << std::endl;
+}
+
+static void help_command(const char *command_name,
+                         int major_version, int minor_version,
+                         const struct option *long_options)
+{
+  std::cout << command_name << " " << major_version << "." << minor_version << std::endl;
+  std::cout << "Prints the number of cores found on the local host." << std::endl << std::endl;
+
+  for (uint32_t x= 0; long_options[x].name; x++)
+  {
+    std::cout << "\t --" << long_options[x].name << char(long_options[x].has_arg ? '=' : ' ') << std::endl;
+  }
+
+  std::cout << std::endl;
+}
+
+enum {
+  OPT_HELP,
+  OPT_VERSION
+};
+
+static void options_parse(int argc, char *argv[])
+{
+  static struct option long_options[]=
+  {
+    { "version", no_argument, NULL, OPT_VERSION},
+    { "help", no_argument, NULL, OPT_HELP},
+    {0, 0, 0, 0},
+  };
+
+  bool opt_version= false;
+  bool opt_help= false;
+  int option_index= 0;
+
+  while (1)
+  {
+    int option_rv= getopt_long(argc, argv, "", long_options, &option_index);
+    if (option_rv == -1) 
+    {
+      break;
+    }
+
+    switch (option_rv)
+    {
+    case OPT_HELP: /* --help or -h */
+      opt_help= true;
+      break;
+
+    case OPT_VERSION: /* --version or -v */
+      opt_version= true;
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(EXIT_FAILURE);
+
+    default:
+      help_command(argv[0], 1, 0, long_options);
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  if (opt_version)
+  {
+    version_command(argv[0], 1, 0);
+    exit(EXIT_SUCCESS);
+  }
+
+  if (opt_help)
+  {
+    help_command(argv[0], 1, 0, long_options);
+    exit(EXIT_SUCCESS);
+  }
+}
+
+int main(int argc, char *argv[])
+{
+  options_parse(argc, argv);
+
+  std::cout << libtest::number_of_cpus() << std::endl;
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/libtest/cpu.cc b/src/libtest/cpu.cc
new file mode 100644 (file)
index 0000000..c62d6c2
--- /dev/null
@@ -0,0 +1,85 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+#include <unistd.h>
+
+#pragma GCC diagnostic ignored "-Wundef"
+
+#if defined(HAVE_LINUX_SYSCTL_H) && HAVE_LINUX_SYSCTL_H
+#include <linux/sysctl.h>
+#elif defined(HAVE_SYS_SYSCTL_H) && HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
+namespace libtest {
+
+size_t number_of_cpus()
+{
+  size_t number_of_cpu= 1;
+#if defined(__linux) && __linux
+  number_of_cpu= sysconf(_SC_NPROCESSORS_ONLN);
+#elif defined(HAVE_SYS_SYSCTL_H) && defined(CTL_HW) && defined(HW_NCPU) && defined(HW_AVAILCPU) && defined(HW_NCPU)
+  int mib[4];
+  size_t len= sizeof(number_of_cpu); 
+
+  /* set the mib for hw.ncpu */
+  mib[0] = CTL_HW;
+  mib[1] = HW_AVAILCPU;  // alternatively, try HW_NCPU;
+
+  /* get the number of CPUs from the system */
+  sysctl(mib, 2, &number_of_cpu, &len, NULL, 0);
+
+  if (number_of_cpu < 1) 
+  {
+    mib[1]= HW_NCPU;
+    sysctl(mib, 2, &number_of_cpu, &len, NULL, 0 );
+
+    if (number_of_cpu < 1 )
+    {
+      number_of_cpu = 1;
+    }
+  }
+#else
+ // Guessing number of CPU
+#endif
+
+  return number_of_cpu;
+}
+
+} // namespace libtest
diff --git a/src/libtest/cpu.hpp b/src/libtest/cpu.hpp
new file mode 100644 (file)
index 0000000..4127709
--- /dev/null
@@ -0,0 +1,43 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+size_t number_of_cpus();
+
+} // namespace libtest
diff --git a/src/libtest/dns.cc b/src/libtest/dns.cc
new file mode 100644 (file)
index 0000000..75a5bbf
--- /dev/null
@@ -0,0 +1,118 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+namespace libtest {
+
+bool lookup(const char* host)
+{
+  bool success= false;
+  assert(host and host[0]);
+  if (host and host[0])
+  {
+    struct addrinfo *addrinfo= NULL;
+    struct addrinfo hints;
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_socktype= SOCK_STREAM;
+    hints.ai_protocol= IPPROTO_TCP;
+
+    int limit= 5;
+    while (--limit and success == false)
+    {
+      if (addrinfo)
+      {
+        freeaddrinfo(addrinfo);
+        addrinfo= NULL;
+      }
+
+      int ret;
+      if ((ret= getaddrinfo(host, "echo", &hints, &addrinfo)) == 0)
+      {
+        success= true;
+        break;
+      }
+
+      switch (ret)
+      {
+      case EAI_AGAIN:
+        continue;
+
+      case EAI_NONAME:
+      default:
+        break;
+      }
+
+      break;
+    }
+
+    if (addrinfo)
+    {
+      freeaddrinfo(addrinfo);
+    }
+  }
+
+  return success;
+}
+
+
+bool check_dns()
+{
+  if (valgrind_is_caller())
+  {
+    return false;
+  }
+
+  if (lookup("exist.gearman.info") == false)
+  {
+    return false;
+  }
+
+  if (lookup("does_not_exist.gearman.info")) // This should fail, if it passes,...
+  {
+    fatal_assert("Your service provider sucks and is providing bogus DNS. You might be in an airport.");
+  }
+
+  return true;
+}
+
+} // namespace libtest
+
diff --git a/src/libtest/dns.hpp b/src/libtest/dns.hpp
new file mode 100644 (file)
index 0000000..438a922
--- /dev/null
@@ -0,0 +1,44 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+bool check_dns();
+bool lookup(const char*);
+
+} // namespace libtest
diff --git a/src/libtest/dream.cc b/src/libtest/dream.cc
new file mode 100644 (file)
index 0000000..42f9222
--- /dev/null
@@ -0,0 +1,58 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+namespace libtest {
+
+void dream(time_t tv_sec, long tv_nsec)
+{
+#if defined(WIN32)
+  if (tv_sec == 0 and tv_nsec)
+  {
+    tv_sec++;
+  }
+  sleep(tv_sec);
+#else
+  struct timespec requested;
+  requested.tv_sec= tv_sec;
+  requested.tv_nsec= tv_nsec;
+  nanosleep(&requested, NULL);
+#endif
+}
+
+}
diff --git a/src/libtest/dream.h b/src/libtest/dream.h
new file mode 100644 (file)
index 0000000..41cabaf
--- /dev/null
@@ -0,0 +1,44 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+void dream(time_t tv_sec, long tv_nsec= 0);
+
+}
+
diff --git a/src/libtest/drizzled.cc b/src/libtest/drizzled.cc
new file mode 100644 (file)
index 0000000..3a93b66
--- /dev/null
@@ -0,0 +1,210 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+#include <libtest/drizzled.h>
+
+#include "util/instance.hpp"
+#include "util/operation.hpp"
+
+using namespace datadifferential;
+using namespace libtest;
+
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <signal.h>
+#include <sstream>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+#if defined(HAVE_LIBDRIZZLE) && HAVE_LIBDRIZZLE
+# include <libdrizzle-5.1/drizzle_client.h>
+#endif
+
+using namespace libtest;
+
+namespace libtest {
+bool ping_drizzled(const in_port_t _port)
+{
+  (void)(_port);
+#if defined(HAVE_LIBDRIZZLE) && HAVE_LIBDRIZZLE
+  if (HAVE_LIBDRIZZLE)
+  {
+    drizzle_st *drizzle= drizzle_create(getenv("MYSQL_SERVER"),
+                                        getenv("MYSQL_PORT") ? atoi("MYSQL_PORT") : DRIZZLE_DEFAULT_TCP_PORT,
+                                        getenv("MYSQL_USER"),
+                                        getenv("MYSQL_PASSWORD"),
+                                        getenv("MYSQL_SCHEMA"), 0);
+
+    if (drizzle == NULL)
+    {
+      return false;
+    }
+
+    bool success= false;
+
+    drizzle_return_t rc;
+    if ((rc= drizzle_connect(drizzle)) == DRIZZLE_RETURN_OK)
+    {
+      drizzle_result_st *result= drizzle_ping(drizzle, &rc);
+      success= bool(result);
+      drizzle_result_free(result);
+    }
+
+    if (success == true)
+    { }
+    else if (rc != DRIZZLE_RETURN_OK)
+    {
+      Error << drizzle_error(drizzle) << " localhost:" << _port;
+    }
+
+    drizzle_quit(drizzle);
+
+    return success;
+  }
+#endif
+
+  return false;
+}
+} // namespace libtest
+
+class Drizzle : public libtest::Server
+{
+private:
+public:
+  Drizzle(const std::string& host_arg, in_port_t port_arg) :
+    libtest::Server(host_arg, port_arg, DRIZZLED_BINARY, false)
+  {
+    set_pid_file();
+  }
+
+  bool ping()
+  {
+    size_t limit= 5;
+    while (_app.check() and --limit)
+    {
+      if (ping_drizzled(_port))
+      {
+        return true;
+      }
+      libtest::dream(1, 0);
+    }
+
+    return false;
+  }
+
+  const char *name()
+  {
+    return "drizzled";
+  };
+
+  void log_file_option(Application&, const std::string&)
+  {
+  }
+
+  bool has_log_file_option() const
+  {
+    return true;
+  }
+
+  bool broken_pid_file()
+  {
+    return true;
+  }
+
+  bool is_libtool()
+  {
+    return false;
+  }
+
+  bool has_syslog() const
+  {
+    return true;
+  }
+
+  bool has_port_option() const
+  {
+    return true;
+  }
+
+  void port_option(Application& app, in_port_t arg)
+  {
+    if (arg > 0)
+    {
+      libtest::vchar_t buffer;
+      buffer.resize(1024);
+      snprintf(&buffer[1024], buffer.size(), "--drizzle-protocol.port=%d", int(arg));
+      app.add_option(&buffer[1024]);
+    }
+  }
+
+  bool build();
+};
+
+bool Drizzle::build()
+{
+  if (getuid() == 0 or geteuid() == 0)
+  {
+    add_option("--user=root");
+  }
+
+  add_option("--verbose=INSPECT");
+#if 0
+  add_option("--datadir=var/drizzle");
+#endif
+
+  return true;
+}
+
+namespace libtest {
+
+libtest::Server *build_drizzled(const char *hostname, in_port_t try_port)
+{
+  return new Drizzle(hostname, try_port);
+}
+
+}
diff --git a/src/libtest/drizzled.h b/src/libtest/drizzled.h
new file mode 100644 (file)
index 0000000..c3e3055
--- /dev/null
@@ -0,0 +1,50 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <arpa/inet.h>
+
+namespace libtest { struct Server; }
+
+namespace libtest {
+
+libtest::Server *build_drizzled(const char *hostname, in_port_t try_port);
+
+bool ping_drizzled(const in_port_t);
+
+}
+
diff --git a/src/libtest/error.h b/src/libtest/error.h
new file mode 100644 (file)
index 0000000..f567d2a
--- /dev/null
@@ -0,0 +1,54 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+enum test_return_t {
+  TEST_SUCCESS,
+  TEST_FAILURE,
+  TEST_SKIPPED
+};
+
+
+static inline bool test_success(test_return_t rc)
+{
+  return (rc == TEST_SUCCESS);
+}
+
+static inline bool test_failed(test_return_t rc)
+{
+  return (rc != TEST_SUCCESS);
+}
diff --git a/src/libtest/exception.cc b/src/libtest/exception.cc
new file mode 100644 (file)
index 0000000..0b18f77
--- /dev/null
@@ -0,0 +1,108 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+#include <cstdarg>
+
+namespace libtest {
+
+exception::exception(const char *file_arg, int line_arg, const char *func_arg):
+  std::exception(),
+  _line(line_arg),
+  _file(file_arg),
+  _func(func_arg),
+  _error_message(NULL),
+  _error_message_size(0)
+{
+}
+
+#ifndef __INTEL_COMPILER
+# pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#endif
+void exception::init(va_list args_)
+{
+  const char *format= va_arg(args_, const char *);
+  int error_message_length= vasprintf(&_error_message, format, args_);
+  assert(error_message_length != -1);
+  if (error_message_length > 0)
+  {
+    _error_message_size= error_message_length +1;
+  }
+}
+
+exception::~exception() throw()
+{
+  if (_error_message)
+  {
+    free(_error_message);
+  }
+}
+
+void exception::what(size_t length_, const char* message_)
+{
+  if (length_ > 0 and message_)
+  {
+    char *ptr= (char*) realloc(_error_message, length_ +1);
+    if (ptr)
+    {
+      _error_message= ptr;
+      memcpy(_error_message, message_, length_);
+      _error_message[length_]= 0;
+    }
+  }
+}
+
+exception::exception(const exception& other) :
+  std::exception(),
+  _line(other._line),
+  _file(other._file),
+  _func(other._func),
+  _error_message_size(0)
+{
+  if (other.length() > 0)
+  {
+    _error_message= (char*) malloc(other.length() +1);
+    if (_error_message)
+    {
+      memcpy(_error_message, other._error_message, other.length());
+      _error_message_size= other.length();
+    }
+  }
+}
+
+} // namespace libtest
+
diff --git a/src/libtest/exception.hpp b/src/libtest/exception.hpp
new file mode 100644 (file)
index 0000000..3d20e8b
--- /dev/null
@@ -0,0 +1,94 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+class exception : public std::exception
+{
+public:
+  exception(const char *file, int line, const char *func);
+
+  exception( const exception& );
+
+  virtual ~exception() throw();
+
+  virtual const char* what() const throw()
+  {
+    if (_error_message)
+    {
+      return _error_message;
+    }
+
+    return "";
+  }
+
+  void what(size_t, const char*);
+
+  size_t length() const
+  {
+    return _error_message_size;
+  }
+
+  int line() const
+  {
+    return _line;
+  }
+
+  const char* file() const
+  {
+    return _file;
+  }
+
+  const char* func() const
+  {
+    return _func;
+  }
+
+protected:
+  void init(va_list);
+
+private:
+  int _line;
+  const char*  _file;
+  const char* _func;
+  char* _error_message;
+  size_t _error_message_size;
+};
+
+} // namespace libtest
+
diff --git a/src/libtest/exception/disconnected.hpp b/src/libtest/exception/disconnected.hpp
new file mode 100644 (file)
index 0000000..6e9f4c4
--- /dev/null
@@ -0,0 +1,62 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include "libtest/exception.hpp"
+
+namespace libtest {
+
+class disconnected : public libtest::exception
+{
+public:
+  disconnected(const char *file, int line, const char *func, const std::string&, const unsigned port, ...);
+
+  disconnected(const disconnected&);
+
+  // The following are just for unittesting the exception class
+  static bool is_disabled();
+  static void disable();
+  static void enable();
+  static uint32_t disabled_counter();
+  static void increment_disabled_counter();
+
+private:
+  in_port_t _port;
+  char _instance[BUFSIZ];
+};
+
+} // namespace libtest
diff --git a/src/libtest/exception/fatal.cc b/src/libtest/exception/fatal.cc
new file mode 100644 (file)
index 0000000..5a3bab5
--- /dev/null
@@ -0,0 +1,119 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+#include "libtest/exception.hpp"
+#include <cstdarg>
+
+namespace libtest {
+
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+
+fatal::fatal(const char *file_arg, int line_arg, const char *func_arg, ...) :
+  libtest::exception(file_arg, line_arg, func_arg)
+{
+  va_list args;
+  va_start(args, func_arg);
+  init(args);
+  va_end(args);
+}
+
+fatal::fatal( const fatal& other ) :
+  libtest::exception(other)
+{
+}
+
+static bool _disabled= false;
+static uint32_t _counter= 0;
+
+bool fatal::is_disabled() throw()
+{
+  return _disabled;
+}
+
+void fatal::disable() throw()
+{
+  _counter= 0;
+  _disabled= true;
+}
+
+void fatal::enable() throw()
+{
+  _counter= 0;
+  _disabled= false;
+}
+
+uint32_t fatal::disabled_counter() throw()
+{
+  return _counter;
+}
+
+void fatal::increment_disabled_counter() throw()
+{
+  _counter++;
+}
+
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+disconnected::disconnected(const char *file_arg, int line_arg, const char *func_arg,
+                           const std::string& instance, const unsigned port, ...) :
+  libtest::exception(file_arg, line_arg, func_arg),
+  _port(port)
+{
+  va_list args;
+  va_start(args, port);
+  const char *format= va_arg(args, const char *);
+  char last_error[BUFSIZ];
+  (void)vsnprintf(last_error, sizeof(last_error), format, args);
+  va_end(args);
+
+  char buffer_error[BUFSIZ];
+  int error_length= snprintf(buffer_error, sizeof(buffer_error), "%s:%u %s", instance.c_str(), uint32_t(port), last_error);
+
+  if (error_length > 0)
+  {
+    what(size_t(error_length), buffer_error);
+  }
+}
+
+disconnected::disconnected(const disconnected& other):
+  libtest::exception(other),
+  _port(other._port)
+{
+  strncpy(_instance, other._instance, BUFSIZ);
+}
+
+} // namespace libtest
diff --git a/src/libtest/exception/fatal.hpp b/src/libtest/exception/fatal.hpp
new file mode 100644 (file)
index 0000000..5ee1aac
--- /dev/null
@@ -0,0 +1,87 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+class fatal : public libtest::exception
+{
+public:
+  fatal(const char *file, int line, const char *func, ...);
+
+  fatal(const fatal&);
+
+  // The following are just for unittesting the exception class
+  static bool is_disabled() throw();
+  static void disable() throw();
+  static void enable() throw();
+  static uint32_t disabled_counter() throw();
+  static void increment_disabled_counter() throw();
+
+  test_return_t return_code() const
+  {
+    return TEST_SKIPPED;
+  }
+
+private:
+};
+
+} // namespace libtest
+
+#define FATAL(...) \
+do \
+{ \
+  throw libtest::fatal(LIBYATL_DEFAULT_PARAM, __VA_ARGS__); \
+} while (0)
+
+#define FATAL_IF(__expression, ...) \
+do \
+{ \
+  if ((__expression)) { \
+    throw libtest::fatal(LIBYATL_DEFAULT_PARAM, (#__expression)); \
+  } \
+} while (0)
+
+#define FATAL_IF_(__expression, ...) \
+do \
+{ \
+  if ((__expression)) { \
+    throw libtest::fatal(LIBYATL_DEFAULT_PARAM, __VA_ARGS__); \
+  } \
+} while (0)
+
+#define fatal_assert(__assert) if((__assert)) {} else { throw libtest::fatal(LIBYATL_DEFAULT_PARAM, #__assert); }
diff --git a/src/libtest/failed.cc b/src/libtest/failed.cc
new file mode 100644 (file)
index 0000000..df5d083
--- /dev/null
@@ -0,0 +1,80 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+#include <libtest/failed.h>
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace libtest {
+
+struct failed_st {
+  failed_st(const std::string& collection_arg, const std::string& test_arg) :
+    collection(collection_arg),
+    test(test_arg)
+  { }
+
+  std::string collection;
+  std::string test;
+};
+
+typedef std::vector<failed_st> Failures;
+
+class Failed
+{
+private:
+  Failures failures;
+
+public:
+  void push(const char *collection, const char *test)
+  {
+    failures.push_back(failed_st(collection, test));
+  }
+
+  void print_failed_test(void)
+  {
+    for (Failures::iterator iter= failures.begin(); iter != failures.end(); ++iter)
+    {
+      Error << "\t" << (*iter).collection << " " << (*iter).test;
+    }
+  }
+};
+
+} // namespace libtest
diff --git a/src/libtest/formatter.cc b/src/libtest/formatter.cc
new file mode 100644 (file)
index 0000000..443256b
--- /dev/null
@@ -0,0 +1,275 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include <libtest/common.h>
+
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+#include <ostream>
+
+namespace libtest {
+
+std::string& escape4XML(std::string const& arg, std::string& escaped_string)
+{
+  escaped_string.clear();
+
+  escaped_string+= '"';
+  for (std::string::const_iterator x= arg.begin(), end= arg.end(); x != end; ++x)
+  {
+    unsigned char c= *x;
+    if (c == '&')
+    {
+      escaped_string+= "&amp;";
+    }
+    else if (c == '>')
+    {
+      escaped_string+= "&gt;";
+    }
+    else if (c == '<')
+    {
+      escaped_string+= "&lt;";
+    }
+    else if (c == '\'')
+    {
+      escaped_string+= "&apos;";  break;
+    }
+    else if (c == '"')
+    {
+      escaped_string+= "&quot;";
+    }
+    else if (c == ' ')
+    {
+      escaped_string+= ' ';
+    }
+    else if (isalnum(c))
+    {
+      escaped_string+= c;
+    }
+    else 
+    {
+      char const* const hexdig= "0123456789ABCDEF";
+      escaped_string+= "&#x";
+      escaped_string+= hexdig[c >> 4];
+      escaped_string+= hexdig[c & 0xF];
+      escaped_string+= ';';
+    }
+  }
+  escaped_string+= '"';
+
+  return escaped_string;
+}
+
+class TestCase {
+public:
+  TestCase(const std::string& arg):
+    _name(arg),
+    _result(TEST_FAILURE)
+  {
+  }
+
+  const std::string& name() const
+  {
+    return _name;
+  }
+
+  test_return_t result() const
+  {
+    return _result;
+  }
+
+  void result(test_return_t arg)
+  {
+    _result= arg;
+  }
+
+  void result(test_return_t arg, const libtest::Timer& timer_)
+  {
+    _result= arg;
+    _timer= timer_;
+  }
+
+  const libtest::Timer& timer() const
+  {
+    return _timer;
+  }
+
+  void timer(libtest::Timer& arg)
+  {
+    _timer= arg;
+  }
+
+private:
+  std::string _name;
+  test_return_t _result;
+  libtest::Timer _timer;
+};
+
+Formatter::Formatter(const std::string& frame_name, const std::string& arg)
+{
+  _suite_name= frame_name;
+  _suite_name+= ".";
+  _suite_name+= arg;
+}
+
+Formatter::~Formatter()
+{
+  std::for_each(_testcases.begin(), _testcases.end(), DeleteFromVector());
+  _testcases.clear();
+}
+
+TestCase* Formatter::current()
+{
+  return _testcases.back();
+}
+
+void Formatter::skipped()
+{
+  assert(current());
+  current()->result(TEST_SKIPPED);
+
+  Out
+    << "[ " << test_strerror(current()->result()) << " ]"
+    << "\t\t"
+    << name() << "." << current()->name()
+    ;
+
+  reset();
+}
+
+void Formatter::failed()
+{
+  assert(current());
+  current()->result(TEST_FAILURE);
+
+  Out
+    << "[ " << test_strerror(current()->result()) << " ]"
+    << "\t\t"
+    << name() << "." << current()->name()
+    ;
+
+  reset();
+}
+
+void Formatter::success(const libtest::Timer& timer_)
+{
+  assert(current());
+  current()->result(TEST_SUCCESS, timer_);
+
+  Out
+    << "[ " << test_strerror(current()->result()) << " ]"
+    << "\t"
+    << current()->timer()
+    << "\t"
+    << name() << "." << current()->name()
+    ;
+
+  reset();
+}
+
+void Formatter::xml(libtest::Framework& framework_, std::ofstream& output)
+{
+  std::string escaped_string;
+
+  output << "<testsuites name=" 
+    << escape4XML(framework_.name(), escaped_string) << ">" << std::endl;
+
+  for (Suites::iterator framework_iter= framework_.suites().begin();
+       framework_iter != framework_.suites().end();
+       ++framework_iter)
+  {
+    output << "\t<testsuite name=" 
+      << escape4XML((*framework_iter)->name(), escaped_string)
+#if 0
+      << "  classname=\"\" package=\"\"" 
+#endif
+      << ">" << std::endl;
+
+    for (TestCases::iterator case_iter= (*framework_iter)->formatter()->testcases().begin();
+         case_iter != (*framework_iter)->formatter()->testcases().end();
+         ++case_iter)
+    {
+      output << "\t\t<testcase name=" 
+        << escape4XML((*case_iter)->name(), escaped_string)
+        << " time=\"" 
+        << (*case_iter)->timer().elapsed_milliseconds() 
+        << "\""; 
+
+      switch ((*case_iter)->result())
+      {
+        case TEST_SKIPPED:
+        output << ">" << std::endl;
+        output << "\t\t <skipped/>" << std::endl;
+        output << "\t\t</testcase>" << std::endl;
+        break;
+
+        case TEST_FAILURE:
+        output << ">" << std::endl;
+        output << "\t\t <failure message=\"\" type=\"\"/>"<< std::endl;
+        output << "\t\t</testcase>" << std::endl;
+        break;
+
+        case TEST_SUCCESS:
+        output << "/>" << std::endl;
+        break;
+      }
+    }
+    output << "\t</testsuite>" << std::endl;
+  }
+  output << "</testsuites>" << std::endl;
+}
+
+void Formatter::push_testcase(const std::string& arg)
+{
+  assert(_suite_name.empty() == false);
+  TestCase* _current_testcase= new TestCase(arg);
+  _testcases.push_back(_current_testcase);
+
+  assert(current());
+
+  Echo
+    << "\t\t\t"
+    << name() << "." << current()->name()
+    << "... \r"
+    ;
+}
+
+void Formatter::reset()
+{
+}
+} // namespace libtest
diff --git a/src/libtest/formatter.hpp b/src/libtest/formatter.hpp
new file mode 100644 (file)
index 0000000..10818d4
--- /dev/null
@@ -0,0 +1,85 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <string>
+
+namespace libtest { class Framework; }
+
+
+namespace libtest {
+
+class TestCase;
+typedef std::vector<libtest::TestCase*> TestCases;
+
+class Formatter {
+public:
+  Formatter(const std::string& frame_name, const std::string& arg);
+
+  ~Formatter();
+
+  void skipped();
+
+  void failed();
+
+  void success(const libtest::Timer&);
+
+  void push_testcase(const std::string&);
+
+  const std::string& name() const
+  {
+    return _suite_name;
+  }
+
+  TestCases& testcases()
+  {
+    return _testcases;
+  }
+
+  static void xml(libtest::Framework&, std::ofstream&);
+
+private:
+  void reset();
+
+  TestCase* current();
+
+private:
+  std::string _suite_name;
+  TestCases _testcases;
+};
+
+} // namespace libtest
diff --git a/src/libtest/framework.cc b/src/libtest/framework.cc
new file mode 100644 (file)
index 0000000..2c9ba74
--- /dev/null
@@ -0,0 +1,234 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include <libtest/common.h>
+#include <libtest/collection.h>
+#include <libtest/signal.h>
+
+#include <algorithm>
+#include <fnmatch.h>
+#include <iostream>
+
+namespace libtest {
+
+Framework::Framework(libtest::SignalThread& signal_,
+                     const std::string& name_,
+                     const std::string& only_run_arg,
+                     const std::string& wildcard_arg) :
+  _total(0),
+  _success(0),
+  _skipped(0),
+  _failed(0),
+  _create(NULL),
+  _destroy(NULL),
+  _on_error(NULL),
+  _runner(NULL),
+  _socket(false),
+  _creators_ptr(NULL),
+  _signal(signal_),
+  _only_run(only_run_arg),
+  _wildcard(wildcard_arg),
+  _name(name_)
+{
+  get_world(this);
+}
+
+void Framework::collections(collection_st collections_[])
+{
+  for (collection_st *next= collections_; next and next->name; next++)
+  {
+    _collection.push_back(new Collection(this, next));
+  }
+}
+
+Framework::~Framework()
+{
+  if (_destroy and _destroy(_creators_ptr))
+  {
+    Error << "Failure in _destroy(), some resources may not have been cleaned up.";
+  }
+
+  _servers.shutdown();
+
+  delete _runner;
+
+  std::for_each(_collection.begin(), _collection.end(), DeleteFromVector());
+  _collection.clear();
+}
+
+bool Framework::match(const char* arg)
+{
+  if (_wildcard.empty() == false and fnmatch(_wildcard.c_str(), arg, 0))
+  {
+    return true;
+  }
+
+  return false;
+}
+
+void Framework::exec()
+{
+  for (std::vector<Collection*>::iterator iter= _collection.begin();
+       iter != _collection.end() and (_signal.is_shutdown() == false);
+       ++iter)
+  {
+    if (*iter)
+    {
+      if (_only_run.empty() == false and
+          fnmatch(_only_run.c_str(), (*iter)->name(), 0))
+      {
+        continue;
+      }
+
+      _total++;
+
+      try {
+        switch ((*iter)->exec())
+        {
+          case TEST_FAILURE:
+            _failed++;
+            break;
+
+          case TEST_SKIPPED:
+            _skipped++;
+            break;
+
+            // exec() can return SUCCESS, but that doesn't mean that some tests did
+            // not fail or get skipped.
+          case TEST_SUCCESS:
+            _success++;
+            break;
+        }
+      }
+      catch (const libtest::fatal& e)
+      {
+        _failed++;
+        stream::cerr(e.file(), e.line(), e.func()) << e.what();
+      }
+      catch (const libtest::disconnected& e)
+      {
+        _failed++;
+        Error << "Unhandled disconnection occurred:" << e.what();
+        throw;
+      }
+      catch (...)
+      {
+        _failed++;
+        throw;
+      }
+    }
+  }
+
+  void xml(const std::string& testsuites_name, std::ostream& output);
+}
+
+uint32_t Framework::sum_total()
+{
+  uint32_t count= 0;
+  for (std::vector<Collection*>::iterator iter= _collection.begin();
+       iter != _collection.end();
+       ++iter)
+  {
+    count+= (*iter)->total();
+  }
+
+  return count;
+}
+
+uint32_t Framework::sum_success()
+{
+  uint32_t count= 0;
+  for (std::vector<Collection*>::iterator iter= _collection.begin();
+       iter != _collection.end();
+       ++iter)
+  {
+    count+= (*iter)->success();
+  }
+
+  return count;
+}
+
+uint32_t Framework::sum_skipped()
+{
+  uint32_t count= 0;
+  for (std::vector<Collection*>::iterator iter= _collection.begin();
+       iter != _collection.end();
+       ++iter)
+  {
+    count+= (*iter)->skipped();
+  }
+
+  return count;
+}
+
+uint32_t Framework::sum_failed()
+{
+  uint32_t count= 0;
+  for (std::vector<Collection*>::iterator iter= _collection.begin();
+       iter != _collection.end();
+       ++iter)
+  {
+    count+= (*iter)->failed();
+  }
+
+  return count;
+}
+
+libtest::Runner *Framework::runner()
+{
+  if (_runner == NULL)
+  {
+    _runner= new Runner;
+  }
+  _runner->set_servers(_servers);
+
+  return _runner;
+}
+
+test_return_t Framework::create()
+{
+  test_return_t rc= TEST_SUCCESS;
+  if (_create)
+  {
+    _creators_ptr= _create(_servers, rc);
+  }
+
+  return rc;
+}
+
+} // namespace libtest
diff --git a/src/libtest/framework.h b/src/libtest/framework.h
new file mode 100644 (file)
index 0000000..361779d
--- /dev/null
@@ -0,0 +1,200 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libtest/signal.h>
+
+/**
+  Framework is the structure which is passed to the test implementation to be filled.
+  This must be implemented in order for the test framework to load the tests. We call
+  get_world() in order to fill this structure.
+*/
+
+#include <vector>
+
+namespace { class Collection; }
+typedef std::vector<libtest::Collection*> Suites;
+
+namespace libtest {
+
+class Framework {
+public:
+
+public:
+  test_return_t create();
+
+  const std::string& name() const
+  {
+    return _name;
+  }
+
+  void create(test_callback_create_fn* arg)
+  {
+    _create= arg;
+  }
+
+  void destroy(test_callback_destroy_fn* arg)
+  {
+    _destroy= arg;
+  }
+
+  void collections(collection_st arg[]);
+
+  void set_on_error(test_callback_error_fn *arg)
+  {
+    _on_error= arg;
+  }
+
+  test_return_t on_error(const enum test_return_t, void *);
+
+  void set_socket()
+  {
+    _servers.set_socket();
+  }
+
+  void set_sasl(const std::string& username_arg, const std::string& password_arg)
+  {
+    _servers.set_sasl(username_arg, password_arg);
+  }
+
+  libtest::server_startup_st& servers()
+  {
+    return _servers;
+  }
+
+  void set_runner(libtest::Runner *arg)
+  {
+    _runner= arg;
+  }
+
+  libtest::Runner *runner();
+
+  void exec();
+
+  libtest::Collection& collection();
+
+  virtual ~Framework();
+
+  Framework(libtest::SignalThread&,
+            const std::string&,
+            const std::string&,
+            const std::string&);
+
+  bool match(const char* arg);
+
+  void *creators_ptr()
+  {
+    return _creators_ptr;
+  }
+
+  libtest::SignalThread& signal()
+  {
+    return _signal;
+  }
+
+  uint32_t sum_total();
+  uint32_t sum_success();
+  uint32_t sum_skipped();
+  uint32_t sum_failed();
+
+  size_t size() 
+  {
+    return _collection.size();
+  }
+
+  uint32_t total() const
+  {
+    return _total;
+  }
+
+  uint32_t success() const
+  {
+    return _success;
+  }
+
+  uint32_t skipped() const
+  {
+    return _skipped;
+  }
+
+  uint32_t failed() const
+  {
+    return _failed;
+  }
+
+  Suites& suites()
+  {
+    return _collection;
+  }
+
+private:
+  uint32_t _total;
+  uint32_t _success;
+  uint32_t _skipped;
+  uint32_t _failed;
+  
+  /* These methods are called outside of any collection call. */
+  test_callback_create_fn *_create;
+  test_callback_destroy_fn *_destroy;
+
+  /**
+    If an error occurs during the test, this is called.
+  */
+  test_callback_error_fn *_on_error;
+
+  /**
+    Runner represents the callers for the tests. If not implemented we will use
+    a set of default implementations.
+  */
+  libtest::Runner *_runner;
+
+  libtest::server_startup_st _servers;
+  bool _socket;
+  void *_creators_ptr;
+  unsigned long int _servers_to_run;
+  Suites _collection;
+  libtest::SignalThread& _signal;
+  std::string _only_run;
+  std::string _wildcard;
+  std::string _name;
+
+private:
+  Framework( const Framework& );
+  const Framework& operator=( const Framework& );
+};
+
+} // namespace libtest
diff --git a/src/libtest/gearmand.cc b/src/libtest/gearmand.cc
new file mode 100644 (file)
index 0000000..852cf19
--- /dev/null
@@ -0,0 +1,178 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+#include <libtest/gearmand.h>
+
+using namespace libtest;
+
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <signal.h>
+#include <sstream>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+using namespace libtest;
+
+class Gearmand : public libtest::Server
+{
+private:
+public:
+  Gearmand(const std::string& host_arg, in_port_t port_arg, bool libtool_, const char* binary);
+
+  bool ping()
+  {
+    reset_error();
+
+    if (out_of_ban_killed())
+    {
+      return false;
+    }
+
+    SimpleClient client(_hostname, _port);
+
+    std::string response;
+    bool ret= client.send_message("version", response);
+
+    if (client.is_error())
+    {
+      error(client.error());
+    }
+
+    return ret;
+  }
+
+  const char *name()
+  {
+    return "gearmand";
+  };
+
+  void log_file_option(Application& app, const std::string& arg)
+  {
+    if (arg.empty() == false)
+    {
+      std::string buffer("--log-file=");
+      buffer+= arg;
+      app.add_option("--verbose=DEBUG");
+      app.add_option(buffer);
+    }
+  }
+
+  bool has_log_file_option() const
+  {
+    return true;
+  }
+
+  bool is_libtool()
+  {
+    return true;
+  }
+
+  bool has_syslog() const
+  {
+    return false; //  --syslog.errmsg-enable
+  }
+
+  bool has_port_option() const
+  {
+    return true;
+  }
+
+  bool build();
+};
+
+Gearmand::Gearmand(const std::string& host_arg, in_port_t port_arg, bool libtool_, const char* binary_arg) :
+  libtest::Server(host_arg, port_arg, binary_arg, libtool_)
+{
+  set_pid_file();
+}
+
+bool Gearmand::build()
+{
+  if (getuid() == 0 or geteuid() == 0)
+  {
+    add_option("-u", "root");
+  }
+
+  add_option("--listen=localhost");
+
+  return true;
+}
+
+namespace libtest {
+
+libtest::Server *build_gearmand(const char *hostname, in_port_t try_port, const char* binary)
+{
+  if (binary == NULL)
+  {
+#if defined(HAVE_GEARMAND_BINARY)
+# if defined(GEARMAND_BINARY)
+    if (HAVE_GEARMAND_BINARY)
+    {
+      binary= GEARMAND_BINARY;
+    }
+# endif
+#endif
+  }
+
+  if (binary == NULL)
+  {
+    return NULL;
+  }
+
+  bool is_libtool_script= true;
+
+  if (binary[0] == '/')
+  {
+    is_libtool_script= false;
+  }
+
+  return new Gearmand(hostname, try_port, is_libtool_script, binary);
+}
+
+}
diff --git a/src/libtest/gearmand.h b/src/libtest/gearmand.h
new file mode 100644 (file)
index 0000000..41317d7
--- /dev/null
@@ -0,0 +1,45 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest { struct Server; }
+
+namespace libtest {
+
+libtest::Server *build_gearmand(const char *hostname, in_port_t try_port, const char* binary= NULL);
+
+}
diff --git a/src/libtest/get.h b/src/libtest/get.h
new file mode 100644 (file)
index 0000000..e21ac0a
--- /dev/null
@@ -0,0 +1,51 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  /* How we make all of this work :) */
+  LIBTEST_API
+    void get_world(libtest::Framework *world);
+
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/src/libtest/has.cc b/src/libtest/has.cc
new file mode 100644 (file)
index 0000000..74b4aa2
--- /dev/null
@@ -0,0 +1,232 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+#include <cstdio>
+#include <cstdlib>
+#include <unistd.h>
+
+namespace libtest {
+
+bool has_libmemcached_sasl(void)
+{
+#ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
+  return LIBMEMCACHED_WITH_SASL_SUPPORT;
+#else
+  return false;
+#endif
+}
+
+bool has_libmemcached(void)
+{
+#if defined(HAVE_LIBMEMCACHED) && HAVE_LIBMEMCACHED
+  if (HAVE_LIBMEMCACHED)
+  {
+    return true;
+  }
+#endif
+
+  return false;
+}
+
+bool has_libdrizzle(void)
+{
+#if defined(HAVE_LIBDRIZZLE) && HAVE_LIBDRIZZLE
+  if (HAVE_LIBDRIZZLE)
+  {
+    return true;
+  }
+#endif
+
+  return false;
+}
+
+bool has_postgres_support(void)
+{
+  char *getenv_ptr;
+  if (bool((getenv_ptr= getenv("POSTGRES_IS_RUNNING_AND_SETUP"))))
+  {
+    (void)(getenv_ptr);
+#if defined(HAVE_LIBPQ) && HAVE_LIBPQ
+    if (HAVE_LIBPQ)
+    {
+      return true;
+    }
+#endif
+  }
+
+  return false;
+}
+
+
+bool has_gearmand()
+{
+#if defined(GEARMAND_BINARY) && defined(HAVE_GEARMAND_BINARY) && HAVE_GEARMAND_BINARY
+  if (HAVE_GEARMAND_BINARY)
+  {
+    std::stringstream arg_buffer;
+
+    char *getenv_ptr;
+    if (bool((getenv_ptr= getenv("PWD"))) and 
+        ((strcmp(GEARMAND_BINARY, "./gearmand/gearmand") == 0) or (strcmp(GEARMAND_BINARY, "gearmand/gearmand") == 0)))
+    {
+      arg_buffer << getenv_ptr;
+      arg_buffer << "/";
+    }
+    arg_buffer << GEARMAND_BINARY;
+
+    if (access(arg_buffer.str().c_str(), X_OK) == 0)
+    {
+      return true;
+    }
+  }
+#endif
+
+  return false;
+}
+
+bool has_drizzled()
+{
+#if defined(DRIZZLED_BINARY) && defined(HAVE_DRIZZLED_BINARY) && HAVE_DRIZZLED_BINARY
+  if (HAVE_DRIZZLED_BINARY)
+  {
+    if (access(DRIZZLED_BINARY, X_OK) == 0)
+    {
+      return true;
+    }
+  }
+#endif
+
+  return false;
+}
+
+bool has_mysqld()
+{
+#if defined(MYSQLD_BINARY) && defined(HAVE_MYSQLD_BUILD) && HAVE_MYSQLD_BUILD
+  if (HAVE_MYSQLD_BUILD)
+  {
+    if (access(MYSQLD_BINARY, X_OK) == 0)
+    {
+      return true;
+    }
+  }
+#endif
+
+  return false;
+}
+
+static char memcached_binary_path[FILENAME_MAX];
+
+static void initialize_memcached_binary_path()
+{
+  memcached_binary_path[0]= 0;
+
+#if defined(MEMCACHED_BINARY) && defined(HAVE_MEMCACHED_BINARY) && HAVE_MEMCACHED_BINARY
+  if (HAVE_MEMCACHED_BINARY)
+  {
+    std::stringstream arg_buffer;
+
+    char *getenv_ptr;
+    if (bool((getenv_ptr= getenv("PWD"))) and strcmp(MEMCACHED_BINARY, "memcached/memcached") == 0)
+    {
+      arg_buffer << getenv_ptr;
+      arg_buffer << "/";
+    }
+    arg_buffer << MEMCACHED_BINARY;
+
+    if (access(arg_buffer.str().c_str(), X_OK) == 0)
+    {
+      strncpy(memcached_binary_path, arg_buffer.str().c_str(), FILENAME_MAX-1);
+    }
+  }
+#endif
+}
+
+static pthread_once_t memcached_binary_once= PTHREAD_ONCE_INIT;
+static void initialize_memcached_binary(void)
+{
+  int ret;
+  if ((ret= pthread_once(&memcached_binary_once, initialize_memcached_binary_path)) != 0)
+  {
+    FATAL(strerror(ret));
+  }
+}
+
+bool has_memcached()
+{
+  initialize_memcached_binary();
+
+  if (memcached_binary_path[0] and (strlen(memcached_binary_path) > 0))
+  {
+    return true;
+  }
+
+  return false;
+}
+
+const char* memcached_binary()
+{
+  initialize_memcached_binary();
+
+  if (memcached_binary_path[0])
+  {
+    return memcached_binary_path;
+  }
+
+  return NULL;
+}
+
+const char *gearmand_binary() 
+{
+#if defined(GEARMAND_BINARY)
+  return GEARMAND_BINARY;
+#else
+  return NULL;
+#endif
+}
+
+const char *drizzled_binary() 
+{
+#if defined(DRIZZLED_BINARY)
+  return DRIZZLED_BINARY;
+#else
+  return NULL;
+#endif
+}
+
+} // namespace libtest
diff --git a/src/libtest/has.hpp b/src/libtest/has.hpp
new file mode 100644 (file)
index 0000000..59ee88f
--- /dev/null
@@ -0,0 +1,76 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+LIBTEST_API
+bool has_libmemcached_sasl(void);
+
+LIBTEST_API
+bool has_libmemcached();
+
+LIBTEST_API
+bool has_libdrizzle();
+
+LIBTEST_API
+bool has_postgres_support();
+
+LIBTEST_API
+bool has_memcached();
+
+LIBTEST_API
+bool has_memcached_sasl();
+
+LIBTEST_API
+bool has_gearmand();
+
+LIBTEST_API
+bool has_drizzled();
+
+LIBTEST_API
+bool has_mysqld();
+
+LIBTEST_API
+const char* memcached_binary();
+
+LIBTEST_API
+const char *gearmand_binary(); 
+
+LIBTEST_API
+const char *drizzled_binary();
+} // namespace libtest
diff --git a/src/libtest/http.cc b/src/libtest/http.cc
new file mode 100644 (file)
index 0000000..465ce61
--- /dev/null
@@ -0,0 +1,217 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include <libtest/common.h>
+
+#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
+#include <curl/curl.h>
+#else
+class CURL;
+#endif
+
+
+static void cleanup_curl(void)
+{
+#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
+  curl_global_cleanup();
+#endif
+}
+
+static void initialize_curl_startup()
+{
+#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
+  if (curl_global_init(CURL_GLOBAL_ALL))
+  {
+    FATAL("curl_global_init(CURL_GLOBAL_ALL) failed");
+  }
+#endif
+
+  if (atexit(cleanup_curl))
+  {
+    FATAL("atexit() failed");
+  }
+}
+
+static pthread_once_t start_key_once= PTHREAD_ONCE_INIT;
+static void initialize_curl(void)
+{
+  int ret;
+  if ((ret= pthread_once(&start_key_once, initialize_curl_startup)) != 0)
+  {
+    FATAL(strerror(ret));
+  }
+}
+
+namespace libtest {
+namespace http {
+
+#define YATL_USERAGENT "YATL/1.0"
+
+static size_t http_get_result_callback(void *ptr, size_t size, size_t nmemb, void *data)
+{
+  vchar_t *_body= (vchar_t*)data;
+
+  _body->resize(size * nmemb);
+  memcpy(&(*_body)[0], ptr, _body->size());
+
+  return _body->size();
+}
+
+static void init(CURL *curl, const std::string& url)
+{
+  (void)http_get_result_callback;
+  (void)curl;
+  (void)url;
+#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
+  if (HAVE_LIBCURL)
+  {
+    assert(curl);
+    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
+    curl_easy_setopt(curl, CURLOPT_USERAGENT, YATL_USERAGENT);
+  }
+#endif
+}
+
+HTTP::HTTP(const std::string& url_arg) :
+  _url(url_arg),
+  _response(0)
+{
+  initialize_curl();
+}
+
+bool GET::execute()
+{
+  (void)init;
+
+#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
+  if (HAVE_LIBCURL)
+  {
+    CURL *curl= curl_easy_init();
+
+    init(curl, url());
+
+    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_result_callback);
+    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&_body);
+
+    CURLcode retref= curl_easy_perform(curl);
+    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, _response);
+
+    curl_easy_cleanup(curl);
+
+    return bool(retref == CURLE_OK);
+  }
+#endif
+
+  return false;
+}
+
+bool POST::execute()
+{
+#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
+  if (HAVE_LIBCURL)
+  {
+    CURL *curl= curl_easy_init();;
+
+    init(curl, url());
+
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, _body.size());
+    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (void *)&_body[0]);
+
+    CURLcode retref= curl_easy_perform(curl);
+    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, _response);
+
+    curl_easy_cleanup(curl);
+
+    return bool(retref == CURLE_OK);
+  }
+#endif
+
+  return false;
+}
+
+bool TRACE::execute()
+{
+#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
+  if (HAVE_LIBCURL)
+  {
+    CURL *curl= curl_easy_init();;
+
+    init(curl, url());
+
+    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "TRACE");
+    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_result_callback);
+    curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&_body[0]);
+
+    CURLcode retref= curl_easy_perform(curl);
+    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, _response);
+
+    curl_easy_cleanup(curl);
+
+    return retref == CURLE_OK;
+  }
+#endif
+
+  return false;
+}
+
+bool HEAD::execute()
+{
+#if defined(HAVE_LIBCURL) && HAVE_LIBCURL
+  if (HAVE_LIBCURL)
+  {
+    CURL *curl= curl_easy_init();
+
+    init(curl, url());
+
+    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "HEAD");
+    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_result_callback);
+
+    CURLcode retref= curl_easy_perform(curl);
+    curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, _response);
+
+    curl_easy_cleanup(curl);
+
+    return retref == CURLE_OK;
+  }
+#endif
+
+  return false;
+}
+
+} // namespace http
+} // namespace libtest
diff --git a/src/libtest/http.hpp b/src/libtest/http.hpp
new file mode 100644 (file)
index 0000000..6827821
--- /dev/null
@@ -0,0 +1,132 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libtest/vchar.hpp>
+
+namespace libtest {
+namespace http {
+
+class HTTP {
+public:
+
+  HTTP(const std::string& url_arg);
+
+  virtual bool execute()= 0;
+
+  virtual ~HTTP()
+  { }
+
+  const std::string& url() const
+  {
+    return _url;
+  }
+
+  long response()
+  {
+    return _response;
+  }
+
+private:
+  std::string _url;
+
+protected:
+  long _response;
+};
+
+class GET: public HTTP {
+public:
+
+  GET(const std::string& url_arg) :
+    HTTP(url_arg)
+  {
+  }
+
+  bool execute();
+
+private:
+  libtest::vchar_t _body;
+};
+
+class POST: public HTTP {
+public:
+
+  POST(const std::string& url_arg,
+       const vchar_t& post_arg) :
+    HTTP(url_arg),
+    _post(post_arg)
+  {
+  }
+
+  bool execute();
+
+private:
+  libtest::vchar_t _post;
+  libtest::vchar_t _body;
+};
+
+class TRACE: public HTTP {
+public:
+
+  TRACE(const std::string& url_arg,
+        const vchar_t& body_arg) :
+    HTTP(url_arg),
+    _body(body_arg)
+  {
+  }
+
+  bool execute();
+
+private:
+  libtest::vchar_t _body;
+};
+
+class HEAD: public HTTP {
+public:
+
+  HEAD(const std::string& url_arg) :
+    HTTP(url_arg)
+  {
+  }
+
+  bool execute();
+
+private:
+};
+
+} // namespace http
+} // namespace libtest
diff --git a/src/libtest/is_local.cc b/src/libtest/is_local.cc
new file mode 100644 (file)
index 0000000..ef4059c
--- /dev/null
@@ -0,0 +1,60 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+
+namespace libtest {
+
+bool test_is_local()
+{
+  return (getenv("LIBTEST_LOCAL"));
+}
+
+static bool _is_massive= false;
+void is_massive(bool arg)
+{
+  _is_massive= arg;
+}
+
+bool is_massive()
+{
+  return _is_massive;
+}
+
+} // namespace libtest
+
diff --git a/src/libtest/is_local.hpp b/src/libtest/is_local.hpp
new file mode 100644 (file)
index 0000000..0835553
--- /dev/null
@@ -0,0 +1,50 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+LIBTEST_API
+bool test_is_local();
+
+LIBTEST_API
+void is_massive(bool);
+
+LIBTEST_API
+bool is_massive();
+
+} // namespace libtest
diff --git a/src/libtest/is_pid.hpp b/src/libtest/is_pid.hpp
new file mode 100644 (file)
index 0000000..3c514a9
--- /dev/null
@@ -0,0 +1,43 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+static inline bool is_pid_valid(const pid_t pid)
+{
+  return (pid > 1) ? true : false;
+}
+
diff --git a/src/libtest/killpid.cc b/src/libtest/killpid.cc
new file mode 100644 (file)
index 0000000..2cefff2
--- /dev/null
@@ -0,0 +1,225 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <sstream>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+
+#include <libtest/killpid.h>
+#include <libtest/stream.h>
+
+using namespace libtest;
+
+bool kill_pid(pid_t pid_arg)
+{
+  assert(pid_arg > 0);
+  if (pid_arg < 1)
+  {
+    Error << "Invalid pid:" << pid_arg;
+    return false;
+  }
+
+  if ((::kill(pid_arg, SIGTERM) == -1))
+  {
+    switch (errno)
+    {
+    case EPERM:
+      Error << "Does someone else have a process running locally for " << int(pid_arg) << "?";
+      return false;
+
+    case ESRCH:
+      Error << "Process " << int(pid_arg) << " not found.";
+      return false;
+
+    default:
+    case EINVAL:
+      Error << "kill() " << strerror(errno);
+      return false;
+    }
+  }
+
+  {
+    uint32_t this_wait= 0;
+    uint32_t timeout= 20; // This number should be high enough for valgrind startup (which is slow)
+    uint32_t waited;
+    uint32_t retry;
+
+    for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
+    {
+      int status= 0;
+      if (waitpid(pid_arg, &status, WNOHANG) == 0)
+      {
+        break;
+      }
+      else if (errno == ECHILD)
+      {
+        // Server has already gone away
+        break;
+      }
+      else if (waited >= timeout)
+      {
+        // Timeout failed
+        kill(pid_arg, SIGKILL);
+        break;
+      }
+
+      this_wait= retry * retry / 3 + 1;
+      libtest::dream(this_wait, 0);
+    }
+  }
+
+  return true;
+}
+
+bool check_pid(const std::string &filename)
+{
+  if (filename.empty())
+  {
+    return false;
+  }
+
+  FILE *fp;
+  if ((fp= fopen(filename.c_str(), "r")))
+  {
+    libtest::vchar_t pid_buffer;
+    pid_buffer.resize(1024);
+
+    char *ptr= fgets(&pid_buffer[0], int(pid_buffer.size()), fp);
+    fclose(fp);
+
+    if (ptr)
+    {
+      pid_t pid= (pid_t)atoi(&pid_buffer[0]);
+      if (pid > 0)
+      {
+        return (::kill(pid, 0) == 0);
+      }
+    }
+  }
+  
+  return false;
+}
+
+
+bool kill_file(const std::string &filename)
+{
+  if (filename.empty())
+  {
+    return true;
+  }
+
+  FILE *fp;
+  if ((fp= fopen(filename.c_str(), "r")))
+  {
+    libtest::vchar_t pid_buffer;
+    pid_buffer.resize(1024);
+
+    char *ptr= fgets(&pid_buffer[0], int(pid_buffer.size()), fp);
+    fclose(fp);
+
+    if (ptr)
+    {
+      pid_t pid= (pid_t)atoi(&pid_buffer[0]);
+      if (pid != 0)
+      {
+        bool ret= kill_pid(pid);
+        unlink(filename.c_str()); // If this happens we may be dealing with a dead server that left its pid file.
+
+        return ret;
+      }
+    }
+  }
+  
+  return false;
+}
+
+#define STRINGIFY(x) #x
+#define TOSTRING(x) STRINGIFY(x)
+#define LIBTEST_AT __FILE__ ":" TOSTRING(__LINE__)
+
+pid_t get_pid_from_file(const std::string &filename, std::stringstream& error_message)
+{
+  pid_t ret= -1;
+
+  if (filename.empty())
+  {
+    error_message << LIBTEST_AT << " empty pid file";
+    return ret;
+  }
+
+  FILE *fp;
+  if ((fp= fopen(filename.c_str(), "r")))
+  {
+    libtest::vchar_t pid_buffer;
+    pid_buffer.resize(1024);
+
+    char *ptr= fgets(&pid_buffer[0], int(pid_buffer.size()), fp);
+    if (ptr)
+    {
+      ret= (pid_t)atoi(&pid_buffer[0]);
+      if (ret < 1)
+      {
+        error_message << LIBTEST_AT << " Invalid pid was read from file " << filename;
+      }
+    }
+    else
+    {
+      error_message << LIBTEST_AT << " File " << filename << " was empty ";
+    }
+
+    fclose(fp);
+
+    return ret;
+  }
+  else
+  {
+    libtest::vchar_t buffer;
+    buffer.resize(1024);
+    char *current_directory= getcwd(&buffer[0], buffer.size());
+    error_message << "Error while opening " << current_directory << "/" << filename << " " << strerror(errno);
+  }
+  
+  return ret;
+}
diff --git a/src/libtest/killpid.h b/src/libtest/killpid.h
new file mode 100644 (file)
index 0000000..6bf5dee
--- /dev/null
@@ -0,0 +1,51 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+bool kill_pid(pid_t pid_arg);
+
+bool kill_file(const std::string &filename);
+
+bool check_pid(const std::string &filename);
+
+pid_t get_pid_from_file(const std::string &filename, std::stringstream& error_message);
+
+static inline bool check_pid(pid_t pid_arg)
+{
+  return (pid_arg > 1);
+}
diff --git a/src/libtest/libtool.cc b/src/libtest/libtool.cc
new file mode 100644 (file)
index 0000000..9d4b0f5
--- /dev/null
@@ -0,0 +1,73 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+#include <string>
+
+char _libtool[1024]= { 0 };
+
+namespace libtest {
+
+const char *libtool(void)
+{
+  if (_libtool[0] == 0)
+  {
+    std::string libtool_buffer;
+    if (getenv("PWD"))
+    {
+      libtool_buffer+= getenv("PWD");
+      libtool_buffer+= "/";
+    }
+    else
+    {
+      libtool_buffer+= "./";
+    }
+
+    libtool_buffer+= "libtool";
+    if (access(libtool_buffer.c_str(), R_OK | W_OK | X_OK))
+    {
+      Error << "Could not find libtool via access(" << libtool_buffer << ") :" << strerror(errno);
+      return NULL;
+    }
+
+    snprintf(_libtool, sizeof(_libtool), "%s", libtool_buffer.c_str());
+  }
+
+  return _libtool;
+}
+
+} // namespace libtest
diff --git a/src/libtest/libtool.hpp b/src/libtest/libtool.hpp
new file mode 100644 (file)
index 0000000..925b55d
--- /dev/null
@@ -0,0 +1,43 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+const char *libtool(void);
+
+}
diff --git a/src/libtest/lite.h b/src/libtest/lite.h
new file mode 100644 (file)
index 0000000..36f873e
--- /dev/null
@@ -0,0 +1,413 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+# include <cstdarg>
+# include <cstddef>
+# include <cstdio>
+# include <cstdlib>
+# include <cstring>
+#else
+# include <stdarg.h>
+# include <stdbool.h>
+# include <stddef.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#if defined(WIN32)
+# include <malloc.h>
+#else
+# include <alloca.h>
+#endif
+
+#ifndef __PRETTY_FUNCTION__
+# define __PRETTY_FUNCTION__ __func__
+#endif
+
+#ifndef EXIT_SKIP
+# define EXIT_SKIP 77
+#endif
+
+#ifndef YATL_FULL
+# define YATL_FULL 0
+#endif
+
+#ifndef FAIL
+# define FAIL(__message_format, ...)
+#endif
+
+#ifndef SKIP
+# define SKIP(__message_format, ...)
+#endif
+
+#include <libtest/valgrind.h>
+
+static inline size_t yatl_strlen(const char *s)
+{
+  if (s)
+  {
+    return strlen(s);
+  }
+
+  return (size_t)(0);
+}
+
+static inline int yatl_strcmp(const char *s1, const char *s2, size_t *s1_length, size_t *s2_length)
+{
+  *s1_length= yatl_strlen(s1);
+  *s2_length= yatl_strlen(s2);
+
+  if (*s1_length == 0 &&  *s1_length == *s2_length)
+  {
+    return 0;
+  }
+
+  if (*s1_length == 0 && *s2_length)
+  {
+    return 1;
+  }
+
+  if (*s1_length &&  *s2_length == 0)
+  {
+    return 1;
+  }
+
+  return strcmp(s1, s2);
+}
+
+#define SKIP_IF(__expression) \
+do \
+{ \
+  if ((__expression)) { \
+    if (YATL_FULL) { \
+      SKIP(#__expression); \
+    } \
+    fprintf(stdout, "\n%s:%d: %s SKIP '!(%s)'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression); \
+    exit(EXIT_SKIP); \
+  } \
+} while (0)
+
+#define SKIP_IF_(__expression, ...) \
+do \
+{ \
+  if ((__expression)) { \
+    size_t ask= snprintf(0, 0, __VA_ARGS__); \
+    ask++; \
+    char *buffer= (char*)alloca(sizeof(char) * ask); \
+    snprintf(buffer, ask, __VA_ARGS__); \
+    if (YATL_FULL) { \
+      SKIP(#__expression, buffer); \
+    } \
+    fprintf(stdout, "\n%s:%d: %s SKIP '%s' [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression, buffer); \
+    exit(EXIT_SKIP); \
+  } \
+} while (0)
+
+#define SKIP_UNLESS(__expression) \
+do \
+{ \
+  if (! (__expression)) { \
+    if (YATL_FULL) { \
+      SKIP(#__expression); \
+    } \
+    fprintf(stdout, "\n%s:%d: %s SKIP '(%s)'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression); \
+    exit(EXIT_SKIP); \
+  } \
+} while (0)
+
+#define SKIP_UNLESS_(__expression, ...) \
+do \
+{ \
+  if (! (__expression)) { \
+    size_t ask= snprintf(0, 0, __VA_ARGS__); \
+    ask++; \
+    char *buffer= (char*)alloca(sizeof(char) * ask); \
+    snprintf(buffer, ask, __VA_ARGS__); \
+    if (YATL_FULL) { \
+      SKIP(#__expression, buffer); \
+    } \
+    fprintf(stdout, "\n%s:%d: %s SKIP '%s' [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression, buffer); \
+    exit(EXIT_SKIP); \
+  } \
+} while (0)
+
+#define ASSERT_TRUE(__expression) \
+do \
+{ \
+  if (! (__expression)) { \
+    if (YATL_FULL) { \
+      FAIL("Assertion '%s'", #__expression); \
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '%s'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression);\
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_FALSE(__expression) \
+do \
+{ \
+  if ((__expression)) { \
+    if (YATL_FULL) { \
+     FAIL("Assertion '!%s'", #__expression); \
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '!%s'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression);\
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_NULL_(__expression, ...) \
+do \
+{ \
+  if ((__expression) != NULL) { \
+    size_t ask= snprintf(0, 0, __VA_ARGS__); \
+    ask++; \
+    char *buffer= (char*)alloca(sizeof(char) * ask); \
+    snprintf(buffer, ask, __VA_ARGS__); \
+    if (YATL_FULL) { \
+      FAIL("Assertion '%s' != NULL [ %s ]", #__expression, buffer);\
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '%s' != NULL [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression, buffer);\
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_NOT_NULL(__expression) \
+do \
+{ \
+  if ((__expression) == NULL) { \
+    if (YATL_FULL) { \
+      FAIL("Assertion '%s' == NULL", #__expression,);\
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '%s' == NULL\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression,);\
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_NOT_NULL_(__expression, ...) \
+do \
+{ \
+  if ((__expression) == NULL) { \
+    size_t ask= snprintf(0, 0, __VA_ARGS__); \
+    ask++; \
+    char *buffer= (char*)alloca(sizeof(char) * ask); \
+    snprintf(buffer, ask, __VA_ARGS__); \
+    if (YATL_FULL) { \
+      FAIL("Assertion '%s' == NULL [ %s ]", #__expression, buffer);\
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '%s' == NULL [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression, buffer);\
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_TRUE_(__expression, ...) \
+do \
+{ \
+  if (! (__expression)) { \
+    size_t ask= snprintf(0, 0, __VA_ARGS__); \
+    ask++; \
+    char *buffer= (char*)alloca(sizeof(char) * ask); \
+    snprintf(buffer, ask, __VA_ARGS__); \
+    if (YATL_FULL) { \
+      FAIL("Assertion '%s' [ %s ]", #__expression, buffer); \
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '%s' [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression, buffer); \
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_EQ(__expected, __actual) \
+do \
+{ \
+  if ((__expected) != (__actual)) { \
+    if (YATL_FULL) { \
+      FAIL("Assertion '%s' != '%s'", #__expected, #__actual); \
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '%s' != '%s'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expected, #__actual); \
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_EQ_(__expected, __actual, ...) \
+do \
+{ \
+  if ((__expected) != (__actual)) { \
+    size_t ask= snprintf(0, 0, __VA_ARGS__); \
+    ask++; \
+    char *buffer= (char*)alloca(sizeof(char) * ask); \
+    snprintf(buffer, ask, __VA_ARGS__); \
+    if (YATL_FULL) { \
+      FAIL("Assertion '%s' != '%s' [ %s ]", #__expected, #__actual, buffer); \
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '%s' != '%s' [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expected, #__actual, buffer); \
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_STREQ(__expected_str, __actual_str) \
+do \
+{ \
+  size_t __expected_length; \
+  size_t __actual_length; \
+  int ret= yatl_strcmp(__expected_str, __actual_str, &__expected_length, &__actual_length); \
+  if (ret) { \
+    if (YATL_FULL) { \
+      FAIL("Assertion '%.*s' != '%.*s'\n", \
+           (int)(__expected_length), (__expected_str), \
+           (int)__actual_length, (__actual_str)) ; \
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '%.*s' != '%.*s'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, \
+            (int)(__expected_length), (__expected_str), \
+            (int)__actual_length, (__actual_str)) ; \
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_STREQ_(__expected_str, __actual_str, ...) \
+do \
+{ \
+  size_t __expected_length; \
+  size_t __actual_length; \
+  int ret= yatl_strcmp(__expected_str, __actual_str, &__expected_length, &__actual_length); \
+  if (ret) { \
+    size_t ask= snprintf(0, 0, __VA_ARGS__); \
+    ask++; \
+    char *buffer= (char*)alloca(sizeof(char) * ask); \
+    ask= snprintf(buffer, ask, __VA_ARGS__); \
+    if (YATL_FULL) { \
+      FAIL("Assertion '%.*s' != '%.*s' [ %.*s ]", \
+           (int)(__expected_length), (__expected_str), \
+           (int)(__actual_length), (__actual_str), \
+           (int)(ask), buffer); \
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '%.*s' != '%.*s' [ %.*s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, \
+            (int)(__expected_length), (__expected_str), \
+            (int)(__actual_length), (__actual_str), \
+            (int)(ask), buffer); \
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_STRNE(__expected_str, __actual_str) \
+do \
+{ \
+  size_t __expected_length; \
+  size_t __actual_length; \
+  int ret= yatl_strcmp(__expected_str, __actual_str, &__expected_length, &__actual_length); \
+  if (ret == 0) { \
+    if (YATL_FULL) { \
+      FAIL("Assertion '%.*s' == '%.*s'", \
+           (int)(__expected_length), (__expected_str), \
+           (int)__actual_length, (__actual_str)) ; \
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '%.*s' == '%.*s'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, \
+            (int)(__expected_length), (__expected_str), \
+            (int)__actual_length, (__actual_str)) ; \
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_STRNE_(__expected_str, __actual_str, ...) \
+do \
+{ \
+  size_t __expected_length; \
+  size_t __actual_length; \
+  int ret= yatl_strcmp(__expected_str, __actual_str, &__expected_length, &__actual_length); \
+  if (ret == 0) { \
+    size_t ask= snprintf(0, 0, __VA_ARGS__); \
+    ask++; \
+    char *buffer= (char*)alloca(sizeof(char) * ask); \
+    ask= snprintf(buffer, ask, __VA_ARGS__); \
+    if (YATL_FULL) { \
+      FAIL("Assertion '%.*s' == '%.*s' [ %.*s ]", \
+           (int)(__expected_length), (__expected_str), \
+           (int)(__actual_length), (__actual_str), \
+           (int)(ask), buffer); \
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '%.*s' == '%.*s' [ %.*s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, \
+            (int)(__expected_length), (__expected_str), \
+            (int)(__actual_length), (__actual_str), \
+            (int)(ask), buffer); \
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_NEQ(__expected, __actual) \
+do \
+{ \
+  if ((__expected) == (__actual)) { \
+    if (YATL_FULL) { \
+      FAIL("Assertion '%s' == '%s'", #__expected, #__actual); \
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '%s' == '%s'\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expected, #__actual); \
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_NEQ_(__expected, __actual, ...) \
+do \
+{ \
+  if ((__expected) == (__actual)) { \
+    size_t ask= snprintf(0, 0, __VA_ARGS__); \
+    ask++; \
+    char *buffer= (char*)alloca(sizeof(char) * ask); \
+    snprintf(buffer, ask, __VA_ARGS__); \
+    if (YATL_FULL) { \
+      FAIL("Assertion '%s' == '%s' [ %s ]", #__expected, #__actual, buffer); \
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '%s' == '%s' [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expected, #__actual, buffer); \
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
+
+#define ASSERT_FALSE_(__expression, ...) \
+do \
+{ \
+  if ((__expression)) { \
+    size_t ask= snprintf(0, 0, __VA_ARGS__); \
+    ask++; \
+    char *buffer= (char*)alloca(sizeof(char) * ask); \
+    snprintf(buffer, ask, __VA_ARGS__); \
+    if (YATL_FULL) { \
+      FAIL("Assertion '!%s' [ %s ]", #__expression, buffer); \
+    } \
+    fprintf(stderr, "\n%s:%d: %s Assertion '!%s' [ %s ]\n", __FILE__, __LINE__, __PRETTY_FUNCTION__, #__expression, buffer); \
+    exit(EXIT_FAILURE); \
+  } \
+} while (0)
diff --git a/src/libtest/main.cc b/src/libtest/main.cc
new file mode 100644 (file)
index 0000000..f20cb95
--- /dev/null
@@ -0,0 +1,396 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <fnmatch.h>
+#include <iostream>
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#include <fstream>
+#include <memory>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <signal.h>
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+#if __cplusplus >= 201103L
+# define UNIQUE_PTR std::unique_ptr
+#else
+# define UNIQUE_PTR std::auto_ptr
+#endif
+
+using namespace libtest;
+
+static void stats_print(libtest::Framework *frame)
+{
+  if (frame->failed() == 0 and frame->success() == 0)
+  {
+    return;
+  }
+
+  Outn();
+  Out << "Collections\t\t\t\t\t" << frame->total();
+  Out << "\tFailed\t\t\t\t\t" << frame->failed();
+  Out << "\tSkipped\t\t\t\t\t" << frame->skipped();
+  Out << "\tSucceeded\t\t\t\t" << frame->success();
+  Outn();
+  Out << "Tests\t\t\t\t\t" << frame->sum_total();
+  Out << "\tFailed\t\t\t\t" << frame->sum_failed();
+  Out << "\tSkipped\t\t\t\t" << frame->sum_skipped();
+  Out << "\tSucceeded\t\t\t" << frame->sum_success();
+}
+
+#include <getopt.h>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+  bool opt_massive= false;
+  unsigned long int opt_repeat= 1; // Run all tests once
+  bool opt_quiet= false;
+  std::string collection_to_run;
+  std::string wildcard;
+  std::string binary_name;
+
+  const char *just_filename= rindex(argv[0], '/');
+  if (just_filename)
+  {
+    just_filename++;
+  }
+  else
+  {
+    just_filename= argv[0];
+  }
+
+  if (just_filename[0] == 'l' and just_filename[1] == 't' and  just_filename[2] == '-')
+  {
+    just_filename+= 3;
+  }
+  binary_name.append(just_filename);
+
+  /*
+    Valgrind does not currently work reliably, or sometimes at all, on OSX
+    - Fri Jun 15 11:24:07 EDT 2012
+  */
+#if defined(__APPLE__) && __APPLE__
+  if (valgrind_is_caller())
+  {
+    return EXIT_SKIP;
+  }
+#endif
+
+  // Options parsing
+  {
+    enum long_option_t {
+      OPT_LIBYATL_VERSION,
+      OPT_LIBYATL_MATCH_COLLECTION,
+      OPT_LIBYATL_MASSIVE,
+      OPT_LIBYATL_QUIET,
+      OPT_LIBYATL_MATCH_WILDCARD,
+      OPT_LIBYATL_REPEAT
+    };
+
+    static struct option long_options[]=
+    {
+      { "version", no_argument, NULL, OPT_LIBYATL_VERSION },
+      { "quiet", no_argument, NULL, OPT_LIBYATL_QUIET },
+      { "repeat", required_argument, NULL, OPT_LIBYATL_REPEAT },
+      { "collection", required_argument, NULL, OPT_LIBYATL_MATCH_COLLECTION },
+      { "wildcard", required_argument, NULL, OPT_LIBYATL_MATCH_WILDCARD },
+      { "massive", no_argument, NULL, OPT_LIBYATL_MASSIVE },
+      { 0, 0, 0, 0 }
+    };
+
+    int option_index= 0;
+    while (1)
+    {
+      int option_rv= getopt_long(argc, argv, "", long_options, &option_index);
+      if (option_rv == -1)
+      {
+        break;
+      }
+
+      switch (option_rv)
+      {
+      case OPT_LIBYATL_VERSION:
+        break;
+
+      case OPT_LIBYATL_QUIET:
+        opt_quiet= true;
+        break;
+
+      case OPT_LIBYATL_REPEAT:
+        errno= 0;
+        opt_repeat= strtoul(optarg, (char **) NULL, 10);
+        if (errno != 0)
+        {
+          Error << "unknown value passed to --repeat: `" << optarg << "`";
+          exit(EXIT_FAILURE);
+        }
+        break;
+
+      case OPT_LIBYATL_MATCH_COLLECTION:
+        collection_to_run= optarg;
+        break;
+
+      case OPT_LIBYATL_MATCH_WILDCARD:
+        wildcard= optarg;
+        break;
+
+      case OPT_LIBYATL_MASSIVE:
+        opt_massive= true;
+        break;
+
+      case '?':
+        /* getopt_long already printed an error message. */
+        Error << "unknown option to getopt_long()";
+        exit(EXIT_FAILURE);
+
+      default:
+        break;
+      }
+    }
+  }
+
+  srandom((unsigned int)time(NULL));
+
+  errno= 0;
+  if (bool(getenv("YATL_REPEAT")))
+  {
+    errno= 0;
+    opt_repeat= strtoul(getenv("YATL_REPEAT"), (char **) NULL, 10);
+    if (errno != 0)
+    {
+      Error << "ENV YATL_REPEAT passed an invalid value: `" << getenv("YATL_REPEAT") << "`";
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  if ((bool(getenv("YATL_QUIET")) and (strcmp(getenv("YATL_QUIET"), "0") == 0)) or opt_quiet)
+  {
+    opt_quiet= true;
+  }
+  else if (getenv("JENKINS_URL"))
+  {
+    if (bool(getenv("YATL_QUIET")) and (strcmp(getenv("YATL_QUIET"), "1") == 0))
+    { }
+    else
+    {
+      opt_quiet= true;
+    }
+  }
+
+  if ((bool(getenv("YATL_RUN_MASSIVE_TESTS"))) or opt_massive)
+  {
+    opt_massive= true;
+  }
+
+  if (opt_quiet)
+  {
+    close(STDOUT_FILENO);
+  }
+
+  if (opt_massive)
+  {
+    is_massive(opt_massive);
+  }
+
+  libtest::vchar_t tmp_directory;
+  tmp_directory.resize(1024);
+  if (getenv("LIBTEST_TMP"))
+  {
+    snprintf(&tmp_directory[0], tmp_directory.size(), "%s", getenv("LIBTEST_TMP"));
+  }
+  else
+  {
+    snprintf(&tmp_directory[0], tmp_directory.size(), "%s", LIBTEST_TEMP);
+  }
+
+  if (chdir(&tmp_directory[0]) == -1)
+  {
+    libtest::vchar_t getcwd_buffer;
+    getcwd_buffer.resize(1024);
+    char *dir= getcwd(&getcwd_buffer[0], getcwd_buffer.size());
+
+    Error << "Unable to chdir() from " << dir << " to " << &tmp_directory[0] << " errno:" << strerror(errno);
+    return EXIT_FAILURE;
+  }
+
+  if (getenv("YATL_COLLECTION_TO_RUN"))
+  {
+    if (strlen(getenv("YATL_COLLECTION_TO_RUN")))
+    {
+      collection_to_run= getenv("YATL_COLLECTION_TO_RUN");
+    }
+  }
+
+  if (collection_to_run.compare("none") == 0)
+  {
+    return EXIT_SUCCESS;
+  }
+
+  if (collection_to_run.empty() == false)
+  {
+    Out << "Only testing " <<  collection_to_run;
+  }
+
+  int exit_code;
+
+  try 
+  {
+    do
+    {
+      exit_code= EXIT_SUCCESS;
+      fatal_assert(sigignore(SIGPIPE) == 0);
+
+      libtest::SignalThread signal;
+      if (signal.setup() == false)
+      {
+        Error << "Failed to setup signals";
+        return EXIT_FAILURE;
+      }
+
+      UNIQUE_PTR<libtest::Framework> frame(new libtest::Framework(signal, binary_name, collection_to_run, wildcard));
+
+      // Run create(), bail on error.
+      {
+        switch (frame->create())
+        {
+        case TEST_SUCCESS:
+          break;
+
+        case TEST_SKIPPED:
+          SKIP("SKIP was returned from framework create()");
+          break;
+
+        case TEST_FAILURE:
+          std::cerr << "Could not call frame->create()" << std::endl;
+          return EXIT_FAILURE;
+        }
+      }
+
+      frame->exec();
+
+      if (signal.is_shutdown() == false)
+      {
+        signal.set_shutdown(SHUTDOWN_GRACEFUL);
+      }
+
+      shutdown_t status= signal.get_shutdown();
+      if (status == SHUTDOWN_FORCED)
+      {
+        Out << "Tests were aborted.";
+        exit_code= EXIT_FAILURE;
+      }
+      else if (frame->failed())
+      {
+        Out << "Some test failed.";
+        exit_code= EXIT_FAILURE;
+      }
+      else if (frame->skipped() and frame->failed() and frame->success())
+      {
+        Out << "Some tests were skipped.";
+      }
+      else if (frame->success() and (frame->failed() == 0))
+      {
+        Out;
+        Out << "All tests completed successfully.";
+      }
+
+      stats_print(frame.get());
+
+      std::ofstream xml_file;
+      std::string file_name;
+      file_name.append(&tmp_directory[0]);
+      file_name.append(frame->name());
+      file_name.append(".xml");
+      xml_file.open(file_name.c_str(), std::ios::trunc);
+      libtest::Formatter::xml(*frame, xml_file);
+
+      Outn(); // Generate a blank to break up the messages if make check/test has been run
+    } while (exit_code == EXIT_SUCCESS and --opt_repeat);
+  }
+  catch (const libtest::__skipped& e)
+  {
+    return EXIT_SKIP;
+  }
+  catch (const libtest::__failure& e)
+  {
+    libtest::stream::make_cout(e.file(), e.line(), e.func()) << e.what();
+    exit_code= EXIT_FAILURE;
+  }
+  catch (const libtest::fatal& e)
+  {
+    std::cerr << "FATAL:" << e.what() << std::endl;
+    exit_code= EXIT_FAILURE;
+  }
+  catch (const libtest::disconnected& e)
+  {
+    std::cerr << "Unhandled disconnection occurred:" << e.what() << std::endl;
+    exit_code= EXIT_FAILURE;
+  }
+  catch (const std::exception& e)
+  {
+    std::cerr << "std::exception:" << e.what() << std::endl;
+    exit_code= EXIT_FAILURE;
+  }
+  catch (char const* s)
+  {
+    std::cerr << "Exception:" << s << std::endl;
+    exit_code= EXIT_FAILURE;
+  }
+  catch (...)
+  {
+    std::cerr << "Unknown exception halted execution." << std::endl;
+    exit_code= EXIT_FAILURE;
+  }
+
+  return exit_code;
+}
diff --git a/src/libtest/memcached.cc b/src/libtest/memcached.cc
new file mode 100644 (file)
index 0000000..caeb11c
--- /dev/null
@@ -0,0 +1,261 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include "libtest/common.h"
+
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <libtest/server.h>
+#include <libtest/wait.h>
+
+#include <libtest/memcached.h>
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+namespace libtest {
+
+class Memcached : public libtest::Server
+{
+  std::string _username;
+  std::string _password;
+
+public:
+  Memcached(const std::string& host_arg,
+            const in_port_t port_arg,
+            const bool is_socket_arg,
+            const std::string& username_arg,
+            const std::string& password_arg) :
+    libtest::Server(host_arg, port_arg, 
+                    memcached_binary(), false, is_socket_arg),
+    _username(username_arg),
+    _password(password_arg)
+  { }
+
+  Memcached(const std::string& host_arg, const in_port_t port_arg, const bool is_socket_arg) :
+    libtest::Server(host_arg, port_arg,
+                    memcached_binary(), false, is_socket_arg)
+  {
+    set_pid_file();
+  }
+
+  virtual const char *sasl() const
+  {
+    return "-S";
+  }
+
+  bool is_sasl() const
+  {
+    return _username.size() && _password.size();
+  }
+
+  const std::string& password() const
+  {
+    return _password;
+  }
+
+  const std::string& username() const
+  {
+    return _username;
+  }
+
+  bool wait_for_pidfile() const
+  {
+    Wait wait(pid(), 4);
+
+    return wait.successful();
+  }
+
+  bool ping()
+  {
+    if (out_of_ban_killed())
+    {
+      return false;
+    }
+
+    if (is_socket() or is_sasl())
+    {
+      return _app.check();
+    }
+
+    SimpleClient client(_hostname, _port);
+
+    std::string response;
+    return client.send_message("version", response);
+  }
+
+  const char *name()
+  {
+    return "memcached";
+  };
+
+  const char *executable()
+  {
+    return memcached_binary();
+  }
+
+  bool is_libtool()
+  {
+    return false;
+  }
+
+  virtual void pid_file_option(Application& app, const std::string& arg)
+  {
+    if (arg.empty() == false)
+    {
+      app.add_option("-P", arg);
+    }
+  }
+
+  const char *socket_file_option() const
+  {
+    return "-s ";
+  }
+
+  virtual void port_option(Application& app, in_port_t arg)
+  {
+    char buffer[30];
+    snprintf(buffer, sizeof(buffer), "%d", int(arg));
+    app.add_option("-p", buffer);
+
+    if(!is_sasl())
+    {
+      app.add_option("-U", buffer);
+    }
+  }
+
+  bool has_port_option() const
+  {
+    return true;
+  }
+
+  bool has_socket_file_option() const
+  {
+    return has_socket();
+  }
+
+  void socket_file_option(Application& app, const std::string& socket_arg)
+  {
+    if (socket_arg.empty() == false)
+    {
+      app.add_option("-s", socket_arg);
+    }
+  }
+
+  bool broken_socket_cleanup()
+  {
+    return true;
+  }
+
+  // Memcached's pidfile is broken
+  bool broken_pid_file()
+  {
+    return true;
+  }
+
+  bool build();
+};
+
+
+#include <sstream>
+
+bool Memcached::build()
+{
+  if (getuid() == 0 or geteuid() == 0)
+  {
+    add_option("-u", "root");
+  }
+
+  add_option("-l", "localhost");
+#ifdef __APPLE__
+#else
+  add_option("-m", "128");
+  add_option("-M");
+#endif
+
+  if (is_sasl())
+  {
+    add_option(sasl());
+  }
+
+  //add_option("-vvv");
+
+  return true;
+}
+
+libtest::Server *build_memcached(const std::string& hostname, const in_port_t try_port)
+{
+  if (has_memcached())
+  {
+    return new Memcached(hostname, try_port, false);
+  }
+
+  return NULL;
+}
+
+libtest::Server *build_memcached_socket(const std::string& socket_file, const in_port_t try_port)
+{
+  if (has_memcached())
+  {
+    return new Memcached(socket_file, try_port, true);
+  }
+
+  return NULL;
+}
+
+libtest::Server *build_memcached_sasl(const std::string &hostname, const in_port_t try_port, const std::string &username, const std::string &password)
+{
+  if (has_memcached())
+  {
+    return new Memcached(hostname, try_port, false, username, password);
+  }
+
+  return NULL;
+}
+
+} // namespace libtest
diff --git a/src/libtest/memcached.h b/src/libtest/memcached.h
new file mode 100644 (file)
index 0000000..7dc9c4d
--- /dev/null
@@ -0,0 +1,48 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+libtest::Server *build_memcached(const std::string& hostname, const in_port_t try_port);
+
+libtest::Server *build_memcached_socket(const std::string& socket_file, const in_port_t try_port);
+
+libtest::Server *build_memcached_sasl(const std::string &hostname, const in_port_t try_port, const std::string &username, const std::string &password);
+
+}
+
diff --git a/src/libtest/memcached.hpp b/src/libtest/memcached.hpp
new file mode 100644 (file)
index 0000000..5d010fa
--- /dev/null
@@ -0,0 +1,100 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#if defined(HAVE_LIBMEMCACHED) && HAVE_LIBMEMCACHED
+inline bool operator== (const memcached_st& memc, const memcached_return_t rc)
+{
+  if (memcached_last_error(const_cast<memcached_st *>(&memc)) == rc)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+inline bool operator!= (const memcached_st& memc, memcached_return_t rc)
+{
+  if (memcached_last_error(const_cast<memcached_st *>(&memc)) != rc)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+inline bool operator== (memcached_st* const memc, memcached_return_t rc)
+{
+  if (memcached_last_error(memc) == rc)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+inline bool operator!= (memcached_st* const memc, memcached_return_t rc)
+{
+  if (memcached_last_error(memc) != rc)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+inline bool operator!= (memcached_return_t rc, const memcached_st& memc)
+{
+  if (memcached_last_error(const_cast<memcached_st *>(&memc)) != rc)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+inline bool operator!= (memcached_return_t rc, memcached_st* const memc)
+{
+  if (memcached_last_error(memc) != rc)
+  {
+    return true;
+  }
+
+  return false;
+}
+#endif
+
diff --git a/src/libtest/poll_error.hpp b/src/libtest/poll_error.hpp
new file mode 100644 (file)
index 0000000..b75066f
--- /dev/null
@@ -0,0 +1,100 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+  Structures for generic tests.
+*/
+
+#include <cstdio>
+#include <poll.h>
+
+void print_poll(pollfd& fds)
+{
+  if (fds.revents & POLLERR)
+  {
+    fprintf(stderr, "\tPOLLERR\n");
+  }
+
+  if (fds.revents & POLLHUP)
+  {
+    fprintf(stderr, "\tPOLLHUP\n");
+  }
+
+  if (fds.revents & POLLIN)
+  {
+    fprintf(stderr, "\tPOLLIN\n");
+  }
+
+  if (fds.revents & POLLIN)
+  {
+    fprintf(stderr, "\tPOLLIN\n");
+  }
+
+  if (fds.revents & POLLNVAL)
+  {
+    fprintf(stderr, "\tPOLLNVAL\n");
+  }
+
+  if (fds.revents & POLLOUT)
+  {
+    fprintf(stderr, "\tPOLLOUT\n");
+  }
+
+  if (fds.revents & POLLPRI)
+  {
+    fprintf(stderr, "\tPOLLPRI\n");
+  }
+
+  if (fds.revents & POLLRDBAND)
+  {
+    fprintf(stderr, "\tPOLLPRI\n");
+  }
+
+  if (fds.revents & POLLRDNORM)
+  {
+    fprintf(stderr, "\tPOLLRDNORM\n");
+  }
+
+  if (fds.revents & POLLWRBAND)
+  {
+    fprintf(stderr, "\tPOLLWRBAND\n");
+  }
+
+  if (fds.revents & POLLWRNORM)
+  {
+    fprintf(stderr, "\tPOLLWRNORM\n");
+  }
+}
diff --git a/src/libtest/port.cc b/src/libtest/port.cc
new file mode 100644 (file)
index 0000000..d8e8c12
--- /dev/null
@@ -0,0 +1,231 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <fnmatch.h>
+#include <iostream>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h> 
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <utility>
+#include <vector>
+
+#include <signal.h>
+
+#include <libtest/signal.h>
+
+#ifndef SOCK_CLOEXEC 
+#  define SOCK_CLOEXEC 0
+#endif
+
+#ifndef SOCK_NONBLOCK 
+#  define SOCK_NONBLOCK 0
+#endif
+
+#ifndef FD_CLOEXEC
+#  define FD_CLOEXEC 0
+#endif
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+using namespace libtest;
+
+struct socket_st {
+  typedef std::vector< std::pair< int, in_port_t> > socket_port_t;
+  socket_port_t _pair;
+  in_port_t last_port;
+
+  socket_st():
+    last_port(0)
+  { }
+
+  void release(in_port_t _arg)
+  {
+    for (socket_port_t::iterator iter= _pair.begin();
+         iter != _pair.end();
+         ++iter)
+    {
+      if ((*iter).second == _arg)
+      {
+        shutdown((*iter).first, SHUT_RDWR);
+        close((*iter).first);
+      }
+    }
+  }
+
+  ~socket_st()
+  {
+    for (socket_port_t::iterator iter= _pair.begin();
+         iter != _pair.end();
+         ++iter)
+    {
+      shutdown((*iter).first, SHUT_RDWR);
+      close((*iter).first);
+    }
+  }
+};
+
+static socket_st all_socket_fd;
+
+static in_port_t global_port= 0;
+
+namespace libtest {
+
+in_port_t default_port()
+{
+  if (global_port == 0)
+  {
+    global_port= get_free_port();
+  }
+
+  return global_port;
+}
+
+void release_port(in_port_t arg)
+{
+  all_socket_fd.release(arg);
+}
+
+in_port_t get_free_port()
+{
+  const in_port_t default_port= in_port_t(-1);
+
+  int retries= 1024;
+
+  in_port_t ret_port;
+  while (--retries)
+  {
+    ret_port= default_port;
+    int sd;
+    if ((sd= socket(AF_INET, SOCK_STREAM, 0)) != SOCKET_ERROR)
+    {
+      int optval= 1;
+      if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) != SOCKET_ERROR)
+      { 
+        struct sockaddr_in sin;
+        sin.sin_port= 0;
+        sin.sin_addr.s_addr= 0;
+        sin.sin_addr.s_addr= INADDR_ANY;
+        sin.sin_family= AF_INET;
+
+        int bind_ret;
+        do
+        {
+          if ((bind_ret= bind(sd, (struct sockaddr *)&sin, sizeof(struct sockaddr_in) )) != SOCKET_ERROR)
+          {
+            socklen_t addrlen= sizeof(sin);
+
+            if (getsockname(sd, (struct sockaddr *)&sin, &addrlen) != -1)
+            {
+              ret_port= sin.sin_port;
+            }
+          }
+          else
+          {
+            if (errno != EADDRINUSE)
+            {
+              Error << strerror(errno);
+            }
+          }
+
+          if (errno == EADDRINUSE)
+          {
+            libtest::dream(2, 0);
+          }
+        } while (bind_ret == -1 and errno == EADDRINUSE);
+
+        all_socket_fd._pair.push_back(std::make_pair(sd, ret_port));
+      }
+      else
+      {
+        Error << strerror(errno);
+      }
+    }
+    else
+    {
+      Error << strerror(errno);
+    }
+
+    if (ret_port == default_port)
+    {
+      Error << "no ret_port set:" << strerror(errno);
+    }
+    else if (ret_port > 1024 and ret_port != all_socket_fd.last_port)
+    {
+      break;
+    }
+  }
+
+  // We handle the case where if we max out retries, we still abort.
+  if (retries == 0)
+  {
+    FATAL("No port could be found, exhausted retry");
+  }
+
+  if (ret_port == 0)
+  {
+    FATAL("No port could be found");
+  }
+
+  if (ret_port == default_port)
+  {
+    FATAL("No port could be found");
+  }
+
+  if (ret_port <= 1024)
+  {
+    FATAL("No port could be found, though some where available below or at 1024");
+  }
+
+  all_socket_fd.last_port= ret_port;
+  release_port(ret_port);
+
+  return ret_port;
+}
+
+} // namespace libtest
diff --git a/src/libtest/port.h b/src/libtest/port.h
new file mode 100644 (file)
index 0000000..55cef53
--- /dev/null
@@ -0,0 +1,56 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+  Structures for generic tests.
+*/
+
+#pragma once
+
+#define LIBTEST_FAIL_PORT 23
+
+namespace libtest {
+
+LIBTEST_API
+in_port_t default_port();
+
+LIBTEST_API
+in_port_t get_free_port();
+
+LIBTEST_API
+void release_port(in_port_t arg);
+
+} // namespace libtest
diff --git a/src/libtest/result.cc b/src/libtest/result.cc
new file mode 100644 (file)
index 0000000..3e4523d
--- /dev/null
@@ -0,0 +1,82 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+#include <cstdarg>
+
+namespace libtest {
+
+__test_result::__test_result(const char *file_arg, int line_arg, const char *func_arg):
+  libtest::exception(file_arg, line_arg, func_arg)
+  {
+  }
+
+__success::__success(const char *file_arg, int line_arg, const char *func_arg):
+  __test_result(file_arg, line_arg, func_arg)
+{
+}
+
+__skipped::__skipped(const char *file_arg, int line_arg, const char *func_arg, ...):
+  __test_result(file_arg, line_arg, func_arg)
+{
+  va_list args;
+  va_start(args, func_arg);
+  init(args);
+  va_end(args);
+}
+
+__skipped::__skipped(const __skipped& other) :
+  __test_result(other)
+{
+}
+
+__failure::__failure(const char *file_arg, int line_arg, const char *func_arg, ...) :
+  __test_result(file_arg, line_arg, func_arg)
+{
+  va_list args;
+  va_start(args, func_arg);
+  init(args);
+  va_end(args);
+}
+
+__failure::__failure(const __failure& other) :
+  __test_result(other)
+{
+}
+
+
+} // namespace libtest
diff --git a/src/libtest/result.hpp b/src/libtest/result.hpp
new file mode 100644 (file)
index 0000000..79acbb4
--- /dev/null
@@ -0,0 +1,56 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libtest/result/base.hpp>
+#include <libtest/result/fail.hpp>
+#include <libtest/result/skip.hpp>
+#include <libtest/result/success.hpp>
+
+#define _SUCCESS throw libtest::__success(LIBYATL_DEFAULT_PARAM)
+
+#define SKIP(...) \
+do \
+{ \
+  throw libtest::__skipped(LIBYATL_DEFAULT_PARAM, __VA_ARGS__); \
+} while (0)
+
+#define FAIL(...) \
+do \
+{ \
+  throw libtest::__failure(LIBYATL_DEFAULT_PARAM, __VA_ARGS__); \
+} while (0)
diff --git a/src/libtest/result/base.hpp b/src/libtest/result/base.hpp
new file mode 100644 (file)
index 0000000..5f093f8
--- /dev/null
@@ -0,0 +1,54 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include "libtest/exception.hpp"
+#include "libtest/error.h"
+
+namespace libtest {
+
+class __test_result : public libtest::exception
+{
+public:
+  __test_result(const char *file, int line, const char *func);
+
+  virtual test_return_t return_code() const= 0;
+
+private:
+};
+
+} // namespace libtest
diff --git a/src/libtest/result/fail.hpp b/src/libtest/result/fail.hpp
new file mode 100644 (file)
index 0000000..3aec9c1
--- /dev/null
@@ -0,0 +1,56 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+class __failure : public __test_result
+{
+public:
+  __failure(const char *file, int line, const char *func, ...);
+
+  __failure(const __failure&);
+
+  test_return_t return_code() const
+  {
+    return TEST_FAILURE;
+  }
+
+private:
+};
+
+} // namespace libtest
diff --git a/src/libtest/result/skip.hpp b/src/libtest/result/skip.hpp
new file mode 100644 (file)
index 0000000..7409d71
--- /dev/null
@@ -0,0 +1,54 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+class __skipped : public __test_result
+{
+public:
+  __skipped(const char *file, int line, const char *func, ...);
+
+  __skipped(const __skipped&);
+
+  test_return_t return_code() const
+  {
+    return TEST_SKIPPED;
+  }
+};
+
+} // namespace libtest
diff --git a/src/libtest/result/success.hpp b/src/libtest/result/success.hpp
new file mode 100644 (file)
index 0000000..a34e677
--- /dev/null
@@ -0,0 +1,59 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+class __success : public __test_result
+{
+public:
+  __success(const char *file, int line, const char *func);
+
+  const char* what() const throw()
+  {
+    return "SUCCESS";
+  }
+
+  test_return_t return_code() const
+  {
+    return TEST_SUCCESS;
+  }
+
+private:
+};
+
+} // namespace libtest
diff --git a/src/libtest/run-ci.gdb b/src/libtest/run-ci.gdb
new file mode 100644 (file)
index 0000000..20724b0
--- /dev/null
@@ -0,0 +1,7 @@
+set logging on
+set logging overwrite on
+set environment LIBTEST_IN_GDB=1
+set ASAN_OPTIONS=abort_on_error=1
+run
+thread apply all bt
+quit
diff --git a/src/libtest/run.gdb b/src/libtest/run.gdb
new file mode 100644 (file)
index 0000000..c35ab76
--- /dev/null
@@ -0,0 +1,7 @@
+set logging on
+set logging overwrite on
+set environment LIBTEST_IN_GDB=1
+#set ASAN_OPTIONS=abort_on_error=1
+handle SIGVTALRM stop
+run
+thread apply all bt
diff --git a/src/libtest/runner.cc b/src/libtest/runner.cc
new file mode 100644 (file)
index 0000000..2f94ad3
--- /dev/null
@@ -0,0 +1,203 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+namespace libtest {
+
+Runner::Runner() :
+  _servers(NULL)
+{
+}
+
+test_return_t Runner::main(test_callback_fn* func, void *object)
+{
+  test_return_t ret;
+  try {
+    ret= run(func, object);
+  }
+  catch (const libtest::__skipped& e)
+  {
+    ret= TEST_SKIPPED;
+  }
+  catch (const libtest::__failure& e)
+  {
+    libtest::stream::make_cerr(e.file(), e.line(), e.func()) << e.what();
+    ret= TEST_FAILURE;
+  }
+  catch (const libtest::__success&)
+  {
+    ret= TEST_SUCCESS;
+  }
+  catch (const libtest::fatal&)
+  {
+    throw;
+  }
+  catch (const std::exception& e)
+  {
+    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << e.what();
+    throw;
+  }
+  catch (...)
+  {
+    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << "Unknown exception thrown";
+    throw;
+  }
+
+  return ret;
+}
+
+test_return_t Runner::setup(test_callback_fn* func, void *object)
+{
+  test_return_t ret;
+  try {
+    ret= pre(func, object);
+  }
+  catch (const libtest::__skipped& e)
+  {
+    ret= TEST_SKIPPED;
+  }
+  catch (const libtest::__failure& e)
+  {
+    libtest::stream::make_cout(e.file(), e.line(), e.func()) << e.what();
+    ret= TEST_FAILURE;
+  }
+  catch (const libtest::__success&)
+  {
+    ret= TEST_SUCCESS;
+  }
+  catch (const libtest::fatal& e)
+  {
+    throw;
+  }
+  catch (const std::exception& e)
+  {
+    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << e.what();
+    throw;
+  }
+  catch (...)
+  {
+    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << "Unknown exception thrown";
+    throw;
+  }
+
+  return ret;
+}
+
+test_return_t Runner::teardown(test_callback_fn* func, void *object)
+{
+  test_return_t ret;
+  try {
+    ret= post(func, object);
+  }
+  catch (const libtest::__skipped& e)
+  {
+    ret= TEST_SKIPPED;
+  }
+  catch (const libtest::__failure& e)
+  {
+    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << e.what();
+    ret= TEST_FAILURE;
+  }
+  catch (const libtest::__success&)
+  {
+    ret= TEST_SUCCESS;
+  }
+  catch (const libtest::fatal& e)
+  {
+    throw;
+  }
+  catch (const std::exception& e)
+  {
+    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << e.what();
+    throw;
+  }
+  catch (...)
+  {
+    libtest::stream::make_cerr(LIBYATL_DEFAULT_PARAM) << "Unknown exception thrown";
+    throw;
+  }
+
+  return ret;
+}
+
+test_return_t Runner::flush(void*)
+{
+  return TEST_SUCCESS;
+}
+
+test_return_t Runner::run(test_callback_fn* func, void *object)
+{
+  if (func)
+  {
+    return func(object);
+  }
+
+  return TEST_SUCCESS;
+}
+
+test_return_t Runner::pre(test_callback_fn* func, void *object)
+{
+  if (func)
+  {
+    return func(object);
+  }
+
+  return TEST_SUCCESS;
+}
+
+test_return_t Runner::post(test_callback_fn* func, void *object)
+{
+  if (func)
+  {
+    return func(object);
+  }
+
+  return TEST_SUCCESS;
+}
+
+void Runner::set_servers(libtest::server_startup_st& arg)
+{
+  _servers= &arg;
+}
+
+bool Runner::check()
+{
+  return _servers ? _servers->check() : true;
+}
+
+} // namespace libtest
diff --git a/src/libtest/runner.h b/src/libtest/runner.h
new file mode 100644 (file)
index 0000000..627a0a8
--- /dev/null
@@ -0,0 +1,73 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+namespace libtest {
+
+/**
+  Structure which houses the actual callers for the test cases contained in
+  the collections.
+*/
+class Runner {
+public:
+  test_return_t main(test_callback_fn* func, void *object);
+  test_return_t setup(test_callback_fn* func, void *object);
+  test_return_t teardown(test_callback_fn* func, void *object);
+
+  Runner();
+
+  void set_servers(libtest::server_startup_st& arg);
+
+  bool check();
+
+  virtual ~Runner() { }
+
+  virtual test_return_t flush(void*);
+  virtual test_return_t run(test_callback_fn* func, void *object);
+  virtual test_return_t pre(test_callback_fn* func, void *object);
+  virtual test_return_t post(test_callback_fn* func, void *object);
+
+private:
+  libtest::server_startup_st* _servers;
+
+private:
+  Runner( const Runner& );
+  const Runner& operator=( const Runner& );
+};
+
+} // namespace Runner
diff --git a/src/libtest/server.cc b/src/libtest/server.cc
new file mode 100644 (file)
index 0000000..bfb265c
--- /dev/null
@@ -0,0 +1,532 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include <libtest/common.h>
+
+#include <cassert>
+#include <cerrno>
+#include <climits>
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+#include <algorithm> 
+#include <functional> 
+#include <locale>
+#include <unistd.h>
+
+// trim from end 
+static inline std::string &rtrim(std::string &s)
+{ 
+  s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end()); 
+  return s; 
+}
+
+#include <libtest/server.h>
+#include <libtest/stream.h>
+#include <libtest/killpid.h>
+
+namespace libtest {
+
+std::ostream& operator<<(std::ostream& output, const Server &arg)
+{
+  if (arg.is_socket())
+  {
+    output << arg.hostname();
+  }
+  else
+  {
+    output << arg.hostname() << ":" << arg.port();
+  }
+
+  if (arg.has_pid())
+  {
+    output << " Pid:" <<  arg.pid();
+  }
+
+  if (arg.has_socket())
+  {
+    output << " Socket:" <<  arg.socket();
+  }
+
+  if (arg.running().empty() == false)
+  {
+    output << " Exec:" <<  arg.running();
+  }
+
+  return output;  // for multiple << operators
+}
+
+#ifdef __GLIBC__
+namespace {
+
+class Buffer
+{
+public:
+  Buffer(char *b) : b_(b) {}
+   ~Buffer() { if (b_) free(b_); }
+  char* buf() { return b_; }
+private:
+  char *b_;
+};
+
+}
+#endif // __GLIBC__
+
+#define MAGIC_MEMORY 123570
+
+Server::Server(const std::string& host_arg, const in_port_t port_arg,
+               const std::string& executable, const bool _is_libtool,
+               bool is_socket_arg) :
+  _magic(MAGIC_MEMORY),
+  _is_socket(is_socket_arg),
+  _port(port_arg),
+  _hostname(host_arg),
+  _app(executable, _is_libtool),
+  out_of_ban_killed_(false),
+  _timeout(40)
+{
+}
+
+Server::~Server()
+{
+  kill();
+}
+
+bool Server::check()
+{
+  _app.clear();
+  return _app.check();
+}
+
+bool Server::validate()
+{
+  return _magic == MAGIC_MEMORY;
+}
+
+// If the server exists, kill it
+bool Server::cycle()
+{
+  uint32_t limit= 3;
+
+  // Try to ping, and kill the server #limit number of times
+  while (--limit and 
+         is_pid_valid(_app.pid()))
+  {
+    if (kill())
+    {
+      Log << "Killed existing server," << *this;
+      dream(0, 50000);
+      continue;
+    }
+  }
+
+  // For whatever reason we could not kill it, and we reached limit
+  if (limit == 0)
+  {
+    Error << "Reached limit, could not kill server";
+    return false;
+  }
+
+  return true;
+}
+
+bool Server::wait_for_pidfile() const
+{
+  Wait wait(pid_file(), 4);
+
+  return wait.successful();
+}
+
+bool Server::init(const char *argv[])
+{
+  if (argv)
+  {
+    for (const char **ptr= argv; *ptr ; ++ptr)
+    {
+      if (ptr)
+      {
+        add_option(*ptr);
+      }
+    }
+  }
+
+  return build();
+}
+
+bool Server::has_pid() const
+{
+  return (_app.pid() > 1);
+}
+
+
+bool Server::start()
+{
+  if (getenv("YATL_GDB_SERVER"))
+  {
+    _app.use_gdb(true);
+  }
+
+  if (port() == LIBTEST_FAIL_PORT)
+  {
+    throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
+                                hostname(), port(), "Called failure");
+  }
+
+  if (getenv("YATL_PTRCHECK_SERVER"))
+  {
+    _app.use_ptrcheck(true);
+  }
+  else if (getenv("YATL_VALGRIND_SERVER"))
+  {
+    _app.use_valgrind(true);
+  }
+
+  out_of_ban_killed(false);
+  if (args(_app) == false)
+  {
+    throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
+                                hostname(), port(), "Could not build command()");
+  }
+
+  libtest::release_port(_port);
+
+  Application::error_t ret;
+  if (Application::SUCCESS !=  (ret= _app.run()))
+  {
+    throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
+                                hostname(), port(), "Application::run() %s", libtest::Application::toString(ret));
+    return false;
+  }
+  _running= _app.print();
+
+  if (valgrind_is_caller())
+  {
+    dream(5, 50000);
+  }
+
+  size_t repeat= 5;
+  _app.slurp();
+  while (--repeat)
+  {
+    if (pid_file().empty() == false)
+    {
+      Wait wait(pid_file(), 8);
+
+      if (wait.successful() == false)
+      {
+        if (_app.check())
+        {
+          _app.slurp();
+          continue;
+        }
+
+#ifdef __GLIBC__
+        Buffer buf( get_current_dir_name());
+        char *getcwd_buf= buf.buf();
+#else
+        libtest::vchar_t buf;
+        buf.resize(PATH_MAX);
+        char *getcwd_buf= getcwd(&buf[0], buf.size());
+#endif // __GLIBC__
+        throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
+                                    hostname(), port(),
+                                    "Unable to open pidfile in %s for: %s stderr:%s",
+                                    getcwd_buf ? getcwd_buf : "",
+                                    _running.c_str(),
+                                    _app.stderr_c_str());
+      }
+    }
+  }
+
+  bool pinged= false;
+  uint32_t this_wait= 0;
+  {
+    uint32_t waited;
+    uint32_t retry;
+
+    for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
+    {
+      if (_app.check() == false)
+      {
+        break;
+      }
+
+      if ((pinged= ping()) == true)
+      {
+        break;
+      }
+      else if (waited >= _timeout)
+      {
+        break;
+      }
+
+      this_wait= retry * retry / 3 + 1;
+      libtest::dream(this_wait, 0);
+    }
+  }
+
+  if (pinged == false)
+  {
+#if 0
+    Error << "Failed to ping(" << _app.pid() << ") wait: " << this_wait << " " << hostname() << ":" << port() << " run:" << _running << " " << error();
+#endif
+
+    // If we happen to have a pid file, lets try to kill it
+    if ((pid_file().empty() == false) and (access(pid_file().c_str(), R_OK) == 0))
+    {
+      _app.slurp();
+      if (kill_file(pid_file()) == false)
+      {
+        throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
+                                    hostname(), port(),
+                                    "Failed to kill off server, waited: %u after startup occurred, when pinging failed: %.*s stderr:%.*s",
+                                    this_wait,
+                                    int(_running.size()), _running.c_str(),
+                                    int(_app.stderr_result_length()), _app.stderr_c_str());
+      }
+      else
+      {
+        throw libtest::disconnected(LIBYATL_DEFAULT_PARAM, 
+                                    hostname(), port(),
+                                    "Failed native ping(), pid: %d was alive: %s waited: %u server started, having pid_file. exec: %.*s stderr:%.*s",
+                                    int(_app.pid()),
+                                    _app.check() ? "true" : "false",
+                                    this_wait,
+                                    int(_running.size()), _running.c_str(),
+                                    int(_app.stderr_result_length()), _app.stderr_c_str());
+      }
+    }
+    else
+    {
+      throw libtest::disconnected(LIBYATL_DEFAULT_PARAM,
+                                  hostname(), port(),
+                                  "Failed native ping(), pid: %d is alive: %s waited: %u server started. exec: %.*s stderr:%.*s",
+                                  int(_app.pid()),
+                                  _app.check() ? "true" : "false",
+                                  this_wait,
+                                  int(_running.size()), _running.c_str(),
+                                  int(_app.stderr_result_length()), _app.stderr_c_str());
+    }
+    _running.clear();
+
+    return false;
+  }
+
+  return has_pid();
+}
+
+void Server::reset_pid()
+{
+  _running.clear();
+  _pid_file.clear();
+}
+
+pid_t Server::pid() const
+{
+  return _app.pid();
+}
+
+void Server::add_option(const std::string& arg)
+{
+  _options.push_back(std::make_pair(arg, std::string()));
+}
+
+void Server::add_option(const std::string& name_, const std::string& value_)
+{
+  _options.push_back(std::make_pair(name_, value_));
+}
+
+bool Server::set_socket_file()
+{
+  libtest::vchar_t file_buffer;
+  file_buffer.resize(FILENAME_MAX);
+  file_buffer[0]= 0;
+
+  if (broken_pid_file())
+  {
+    snprintf(&file_buffer[0], file_buffer.size(), "/tmp/%s.socketXXXXXX", name());
+  }
+  else
+  {
+    snprintf(&file_buffer[0], file_buffer.size(), "var/run/%s.socketXXXXXX", name());
+  }
+
+  int fd;
+  if ((fd= mkstemp(&file_buffer[0])) == -1)
+  {
+    perror(&file_buffer[0]);
+    return false;
+  }
+  close(fd);
+  unlink(&file_buffer[0]);
+
+  _socket= &file_buffer[0];
+
+  return true;
+}
+
+bool Server::set_pid_file()
+{
+  libtest::vchar_t file_buffer;
+  file_buffer.resize(FILENAME_MAX);
+  file_buffer[0]= 0;
+
+  if (broken_pid_file())
+  {
+    snprintf(&file_buffer[0], file_buffer.size(), "/tmp/%s.pidXXXXXX", name());
+  }
+  else
+  {
+    snprintf(&file_buffer[0], file_buffer.size(), "var/run/%s.pidXXXXXX", name());
+  }
+
+  int fd;
+  if ((fd= mkstemp(&file_buffer[0])) == -1)
+  {
+    throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "mkstemp() failed on %s with %s", &file_buffer[0], strerror(errno));
+  }
+  close(fd);
+  unlink(&file_buffer[0]);
+
+  _pid_file= &file_buffer[0];
+
+  return true;
+}
+
+bool Server::set_log_file()
+{
+  libtest::vchar_t file_buffer;
+  file_buffer.resize(FILENAME_MAX);
+  file_buffer[0]= 0;
+
+  snprintf(&file_buffer[0], file_buffer.size(), "var/log/%s.logXXXXXX", name());
+  int fd;
+  if ((fd= mkstemp(&file_buffer[0])) == -1)
+  {
+    throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "mkstemp() failed on %s with %s", &file_buffer[0], strerror(errno));
+  }
+  close(fd);
+
+  _log_file= &file_buffer[0];
+
+  return true;
+}
+
+bool Server::args(Application& app)
+{
+
+  // Set a log file if it was requested (and we can)
+  if (has_log_file_option())
+  {
+    set_log_file();
+    log_file_option(app, _log_file);
+  }
+
+  if (getenv("LIBTEST_SYSLOG") and has_syslog())
+  {
+    app.add_option("--syslog");
+  }
+
+  // Update pid_file
+  {
+    if (_pid_file.empty() and set_pid_file() == false)
+    {
+      return false;
+    }
+
+    pid_file_option(app, pid_file());
+  }
+
+  if (has_socket_file_option())
+  {
+    if (set_socket_file() == false)
+    {
+      return false;
+    }
+
+    socket_file_option(app, _socket);
+  }
+
+  if (has_port_option())
+  {
+    port_option(app, _port);
+  }
+
+  for (Options::const_iterator iter= _options.begin(); iter != _options.end(); ++iter)
+  {
+    if ((*iter).first.empty() == false)
+    {
+      if ((*iter).second.empty() == false)
+      {
+        app.add_option((*iter).first, (*iter).second);
+      }
+      else
+      {
+        app.add_option((*iter).first);
+      }
+    }
+  }
+
+  return true;
+}
+
+bool Server::kill()
+{
+  if (check_pid(_app.pid())) // If we kill it, reset
+  {
+    _app.murder();
+    if (broken_pid_file() and pid_file().empty() == false)
+    {
+      unlink(pid_file().c_str());
+    }
+
+    if (broken_socket_cleanup() and has_socket() and not socket().empty())
+    {
+      unlink(socket().c_str());
+    }
+
+    reset_pid();
+
+    return true;
+  }
+
+  return false;
+}
+
+} // namespace libtest
diff --git a/src/libtest/server.h b/src/libtest/server.h
new file mode 100644 (file)
index 0000000..73ad3bf
--- /dev/null
@@ -0,0 +1,302 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libtest/cmdline.h>
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <string>
+#include <unistd.h>
+#include <vector>
+
+namespace libtest {
+
+struct Server {
+private:
+  typedef std::vector< std::pair<std::string, std::string> > Options;
+
+private:
+  uint64_t _magic;
+  bool _is_socket;
+  std::string _socket;
+  std::string _sasl;
+  std::string _pid_file;
+  std::string _log_file;
+  std::string _base_command; // executable command which include libtool, valgrind, gdb, etc
+  std::string _running; // Current string being used for system()
+
+protected:
+  in_port_t _port;
+  std::string _hostname;
+  std::string _extra_args;
+
+public:
+  Server(const std::string& hostname, const in_port_t port_arg,
+         const std::string& executable, const bool _is_libtool,
+         const bool is_socket_arg= false);
+
+  virtual ~Server();
+
+  virtual const char *name()= 0;
+  virtual bool is_libtool()= 0;
+
+  virtual bool has_socket_file_option() const
+  {
+    return false;
+  }
+
+  virtual void socket_file_option(Application& app, const std::string& socket_arg)
+  {
+    if (socket_arg.empty() == false)
+    {
+      std::string buffer("--socket=");
+      buffer+= socket_arg;
+      app.add_option(buffer);
+    }
+  }
+
+  virtual bool has_log_file_option() const
+  {
+    return false;
+  }
+
+  virtual void log_file_option(Application& app, const std::string& arg)
+  {
+    if (arg.empty() == false)
+    {
+      std::string buffer("--log-file=");
+      buffer+= arg;
+      app.add_option(buffer);
+    }
+  }
+
+  virtual void pid_file_option(Application& app, const std::string& arg)
+  {
+    if (arg.empty() == false)
+    {
+      std::string buffer("--pid-file=");
+      buffer+= arg;
+      app.add_option(buffer);
+    }
+  }
+
+  virtual bool has_port_option() const
+  {
+    return false;
+  }
+
+  virtual void port_option(Application& app, in_port_t arg)
+  {
+    if (arg > 0)
+    {
+      char buffer[1024];
+      snprintf(buffer, sizeof(buffer), "--port=%d", int(arg));
+      app.add_option(buffer);
+    }
+  }
+
+  virtual bool broken_socket_cleanup()
+  {
+    return false;
+  }
+
+  virtual bool broken_pid_file()
+  {
+    return false;
+  }
+
+  const std::string& pid_file() const
+  {
+    return _pid_file;
+  }
+
+  const std::string& base_command() const
+  {
+    return _base_command;
+  }
+
+  const std::string& log_file() const
+  {
+    return _log_file;
+  }
+
+  const std::string& hostname() const
+  {
+    return _hostname;
+  }
+
+  const std::string& socket() const
+  {
+    return _socket;
+  }
+
+  bool has_socket() const
+  {
+    return _is_socket;
+  }
+
+  bool cycle();
+
+  virtual bool ping()= 0;
+
+  bool init(const char *argv[]);
+  virtual bool build()= 0;
+
+  void add_option(const std::string&);
+  void add_option(const std::string&, const std::string&);
+
+  in_port_t port() const
+  {
+    return _port;
+  }
+
+  bool has_port() const
+  {
+    return (_port != 0);
+  }
+
+  virtual bool has_syslog() const
+  {
+    return false;
+  }
+
+  // Reset a server if another process has killed the server
+  void reset()
+  {
+    _pid_file.clear();
+    _log_file.clear();
+  }
+
+  std::pair<std::string, std::string> output()
+  {
+    return _app.output();
+  }
+
+  pid_t pid() const;
+
+  bool has_pid() const;
+
+  virtual bool has_pid_file() const
+  {
+    return true;
+  }
+
+  const std::string& error()
+  {
+    return _error;
+  }
+
+  void error(std::string arg)
+  {
+    _error= arg;
+  }
+
+  void reset_error()
+  {
+    _error.clear();
+  }
+
+  virtual bool wait_for_pidfile() const;
+
+  bool check_pid(pid_t pid_arg) const
+  {
+    return (pid_arg > 1);
+  }
+
+  bool is_socket() const
+  {
+    return _is_socket;
+  }
+
+  const std::string running() const
+  {
+    return _running;
+  }
+
+  bool check();
+
+  std::string log_and_pid();
+
+  bool kill();
+  bool start();
+  bool command(libtest::Application& app);
+
+  bool validate();
+
+  void out_of_ban_killed(bool arg)
+  {
+    out_of_ban_killed_= arg;
+  }
+
+  bool out_of_ban_killed()
+  {
+    return out_of_ban_killed_;
+  }
+
+  void timeout(uint32_t timeout_)
+  {
+    _timeout= timeout_;
+  }
+
+protected:
+  bool set_pid_file();
+  Options _options;
+  Application _app;
+
+private:
+  bool is_helgrind() const;
+  bool is_valgrind() const;
+  bool is_debug() const;
+  bool set_log_file();
+  bool set_socket_file();
+  void reset_pid();
+  bool out_of_ban_killed_;
+  bool args(Application&);
+
+  std::string _error;
+  uint32_t _timeout; // This number should be high enough for valgrind startup (which is slow)
+};
+
+std::ostream& operator<<(std::ostream& output, const libtest::Server &arg);
+
+} // namespace libtest
+
+
diff --git a/src/libtest/server_container.cc b/src/libtest/server_container.cc
new file mode 100644 (file)
index 0000000..e6d2f1d
--- /dev/null
@@ -0,0 +1,403 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include "libtest/common.h"
+
+#include <cerrno>
+#include <cstdlib>
+#include <iostream>
+
+#include <algorithm> 
+#include <functional> 
+#include <locale>
+
+// trim from end 
+static inline std::string &rtrim(std::string &s)
+{ 
+  s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end()); 
+  return s; 
+}
+
+namespace libtest {
+
+Server* server_startup_st::last()
+{
+  return servers.back();
+}
+
+void server_startup_st::push_server(Server *arg)
+{
+  servers.push_back(arg);
+
+  std::string server_config_string;
+  if (arg->has_socket())
+  {
+    server_config_string+= "--socket=";
+    server_config_string+= '"';
+    server_config_string+= arg->socket();
+    server_config_string+= '"';
+    server_config_string+= " ";
+  }
+  else
+  {
+    libtest::vchar_t port_str;
+    port_str.resize(NI_MAXSERV);
+    snprintf(&port_str[0], port_str.size(), "%u", int(arg->port()));
+
+    server_config_string+= "--server=";
+    server_config_string+= arg->hostname();
+    server_config_string+= ":";
+    server_config_string+= &port_str[0];
+    server_config_string+= " ";
+  }
+
+  server_list+= server_config_string;
+}
+
+Server* server_startup_st::pop_server()
+{
+  Server *tmp= servers.back();
+  servers.pop_back();
+  return tmp;
+}
+
+// host_to_shutdown => host number to shutdown in array
+bool server_startup_st::shutdown(uint32_t host_to_shutdown)
+{
+  if (servers.size() > host_to_shutdown)
+  {
+    Server* tmp= servers[host_to_shutdown];
+
+    if (tmp and tmp->kill() == false)
+    { }
+    else
+    {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void server_startup_st::clear()
+{
+  std::for_each(servers.begin(), servers.end(), DeleteFromVector());
+  servers.clear();
+}
+
+bool server_startup_st::check() const
+{
+  bool success= true;
+  for (std::vector<Server *>::const_iterator iter= servers.begin(); iter != servers.end(); ++iter)
+  {
+    if ((*iter)->check()  == false)
+    {
+      success= false;
+    }
+  }
+
+  return success;
+}
+
+bool server_startup_st::shutdown()
+{
+  bool success= true;
+  for (std::vector<Server *>::iterator iter= servers.begin(); iter != servers.end(); ++iter)
+  {
+    if ((*iter)->has_pid() and (*iter)->kill() == false)
+    {
+      Error << "Unable to kill:" <<  *(*iter);
+      success= false;
+    }
+  }
+
+  return success;
+}
+
+void server_startup_st::restart()
+{
+  for (std::vector<Server *>::iterator iter= servers.begin(); iter != servers.end(); ++iter)
+  {
+    Server *server = *iter;
+
+    if (server->check()) {
+      server->kill();
+    }
+    server->start();
+  }
+}
+
+#define MAGIC_MEMORY 123575
+server_startup_st::server_startup_st() :
+  _magic(MAGIC_MEMORY),
+  _socket(false),
+  _sasl(false),
+  udp(0),
+  _servers_to_run(5)
+{ }
+
+server_startup_st::~server_startup_st()
+{
+  clear();
+}
+
+bool server_startup_st::validate()
+{
+  return _magic == MAGIC_MEMORY;
+}
+
+bool server_startup(server_startup_st& construct, const std::string& server_type, in_port_t try_port, const char *argv[])
+{
+  return construct.start_server(server_type, try_port, argv);
+}
+
+libtest::Server* server_startup_st::create(const std::string& server_type, in_port_t try_port, const bool is_socket)
+{
+  libtest::Server *server= NULL;
+
+  if (is_socket == false)
+  {
+    if (try_port <= 0)
+    {
+      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "was passed the invalid port number %d", int(try_port));
+    }
+  }
+
+  if (is_socket)
+  { 
+    if (server_type.compare("memcached") == 0)
+    {
+      server= build_memcached_socket("localhost", try_port);
+    }
+    else
+    {
+      Error << "Socket is not support for server: " << server_type;
+      return NULL;
+    }
+  }
+  else if (server_type.compare("gearmand") == 0)
+  {
+    server= build_gearmand("localhost", try_port);
+  }
+  else if (server_type.compare("hostile-gearmand") == 0)
+  {
+    server= build_gearmand("localhost", try_port, "gearmand/hostile_gearmand");
+  }
+  else if (server_type.compare("drizzled") == 0)
+  {
+    if (has_drizzled())
+    {
+      if (has_libdrizzle())
+      {
+        server= build_drizzled("localhost", try_port);
+      }
+    }
+  }
+  else if (server_type.compare("blobslap_worker") == 0)
+  {
+    if (has_gearmand())
+    {
+#ifdef GEARMAND_BLOBSLAP_WORKER
+      if (GEARMAND_BLOBSLAP_WORKER)
+      {
+        if (HAVE_LIBGEARMAN)
+        {
+          server= build_blobslap_worker(try_port);
+        }
+      }
+#endif // GEARMAND_BLOBSLAP_WORKER
+    }
+  }
+  else if (server_type.compare("memcached") == 0)
+  {
+    if (has_memcached())
+    {
+      server= build_memcached("localhost", try_port);
+    }
+  }
+  else if (server_type == "memcached-sasl")
+  {
+    server = build_memcached_sasl("localhost", try_port, _username, _password);
+  }
+
+  return server;
+}
+
+class ServerPtr {
+public:
+  ServerPtr(libtest::Server* server_):
+    _server(server_)
+  { }
+
+  ~ServerPtr()
+  {
+    delete _server;
+  }
+
+  void reset()
+  {
+    delete _server;
+    _server= NULL;
+  }
+
+  libtest::Server* release(libtest::Server* server_= NULL)
+  {
+    libtest::Server* tmp= _server;
+    _server= server_;
+    return tmp;
+  }
+
+  libtest::Server* operator->() const
+  {
+    return _server;
+  }
+
+  libtest::Server* operator&() const
+  { 
+    return _server;
+  }
+
+private:
+  libtest::Server* _server;
+};
+
+bool server_startup_st::_start_server(const bool is_socket,
+                                      const std::string& server_type,
+                                      in_port_t try_port,
+                                      const char *argv[])
+{
+  try {
+    ServerPtr server(create(server_type, try_port, is_socket));
+
+    if (&server == NULL)
+    {
+      Error << "Could not allocate server: " << server_type;
+      return false;
+    }
+
+    /*
+      We will now cycle the server we have created.
+    */
+    if (server->cycle() == false)
+    {
+      Error << "Could not start up server " << &server;
+      return false;
+    }
+
+    server->init(argv);
+
+#if 0
+    if (false)
+    {
+      Out << "Pausing for startup, hit return when ready.";
+      std::string gdb_command= server->base_command();
+      getchar();
+    }
+    else
+#endif
+
+      if (server->start() == false)
+      {
+        return false;
+      }
+      else
+      {
+        {
+#ifdef DEBUG
+          if (DEBUG)
+          {
+            Outn();
+            Out << "STARTING SERVER(pid:" << server->pid() << "): " << server->running();
+          }
+#endif
+        }
+      }
+
+    push_server(server.release());
+
+    if (is_socket and &server)
+    {
+      set_default_socket(server->socket().c_str());
+    }
+  }
+  catch (const libtest::disconnected& err)
+  {
+    if (fatal::is_disabled() == false and try_port != LIBTEST_FAIL_PORT)
+    {
+      stream::cerr(err.file(), err.line(), err.func()) << err.what();
+      return false;
+    }
+  }
+  catch (const libtest::__test_result& err)
+  {
+    stream::cerr(err.file(), err.line(), err.func()) << err.what();
+    return false;
+  }
+  catch (const std::exception& err)
+  {
+    Error << err.what();
+    return false;
+  }
+  catch (...)
+  {
+    Error << "error occured while creating server: " << server_type;
+    return false;
+  }
+
+  return true;
+}
+
+bool server_startup_st::start_server(const std::string& server_type, in_port_t try_port, const char *argv[])
+{
+  return _start_server(false, server_type, try_port, argv);
+}
+
+bool server_startup_st::start_socket_server(const std::string& server_type, const in_port_t try_port, const char *argv[])
+{
+  return _start_server(true, server_type, try_port, argv);
+}
+
+std::string server_startup_st::option_string() const
+{
+  std::string temp= server_list;
+  rtrim(temp);
+  return temp;
+}
+
+
+} // namespace libtest
diff --git a/src/libtest/server_container.h b/src/libtest/server_container.h
new file mode 100644 (file)
index 0000000..88e4763
--- /dev/null
@@ -0,0 +1,151 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <string>
+#include <unistd.h>
+#include <vector>
+
+namespace libtest {
+
+class server_startup_st
+{
+private:
+  uint64_t _magic;
+  std::string server_list;
+  bool _socket;
+  bool _sasl;
+  std::string _username;
+  std::string _password;
+
+public:
+
+  uint8_t udp;
+  std::vector<Server *> servers;
+
+  server_startup_st();
+  ~server_startup_st();
+
+  bool validate();
+
+  bool start_socket_server(const std::string& server_type, const in_port_t try_port, const char *argv[]);
+  bool start_server(const std::string& server_type, const in_port_t try_port, const char *argv[]);
+
+  uint32_t count() const
+  {
+    return uint32_t(servers.size());
+  }
+
+  void restart();
+
+  std::string option_string() const;
+
+  const std::string& password() const
+  {
+    return _password;
+  }
+
+  const std::string& username() const
+  {
+    return _username;
+  }
+
+  bool socket()
+  {
+    return _socket;
+  }
+
+  bool sasl()
+  {
+    return _sasl;
+  }
+
+  void set_socket()
+  {
+    _socket= true;
+  }
+
+  void set_sasl(const std::string& username_arg, const std::string& password_arg)
+  {
+    _sasl= true;
+    _username= username_arg;
+    _password= password_arg;
+  }
+
+
+  // Just remove everything after shutdown
+  void clear();
+
+  bool shutdown();
+  bool shutdown(uint32_t number_of_host);
+
+  bool check() const;
+
+  void push_server(Server *);
+  Server* last();
+  Server *pop_server();
+
+  Server* create(const std::string& server_type, in_port_t try_port, const bool is_socket);
+
+  unsigned long int servers_to_run() const
+  {
+    return _servers_to_run;
+  }
+
+  void set_servers_to_run(unsigned long int arg)
+  {
+    _servers_to_run= arg;
+  }
+
+private:
+  bool _start_server(const bool is_socket,
+                     const std::string& server_type,
+                     const in_port_t try_port,
+                     const char *argv[]);
+
+private:
+  unsigned long int _servers_to_run;
+};
+
+bool server_startup(server_startup_st&, const std::string&, in_port_t try_port, const char *argv[]);
+
+} // namespace libtest
diff --git a/src/libtest/signal.cc b/src/libtest/signal.cc
new file mode 100644 (file)
index 0000000..70012f1
--- /dev/null
@@ -0,0 +1,259 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+#include <csignal>
+
+#include <libtest/signal.h>
+
+using namespace libtest;
+
+#define MAGIC_MEMORY 123569
+
+bool SignalThread::is_shutdown()
+{
+  bool ret;
+  pthread_mutex_lock(&shutdown_mutex);
+  ret= bool(__shutdown != SHUTDOWN_RUNNING);
+  pthread_mutex_unlock(&shutdown_mutex);
+
+  return ret;
+}
+
+void SignalThread::set_shutdown(shutdown_t arg)
+{
+  pthread_mutex_lock(&shutdown_mutex);
+  __shutdown= arg;
+  pthread_mutex_unlock(&shutdown_mutex);
+
+  if (arg == SHUTDOWN_GRACEFUL)
+  {
+    if (pthread_kill(thread, SIGUSR2) == 0)
+    {
+      void *retval;
+      pthread_join(thread, &retval);
+    }
+  }
+}
+
+shutdown_t SignalThread::get_shutdown()
+{
+  shutdown_t local;
+  pthread_mutex_lock(&shutdown_mutex);
+  local= __shutdown;
+  pthread_mutex_unlock(&shutdown_mutex);
+
+  return local;
+}
+
+void SignalThread::post()
+{
+  sem_post(&lock);
+}
+
+void SignalThread::test()
+{
+  assert(magic_memory == MAGIC_MEMORY);
+  if (bool(getenv("LIBTEST_IN_GDB")) == false)
+  {
+    assert(sigismember(&set, SIGALRM));
+    assert(sigismember(&set, SIGABRT));
+    assert(sigismember(&set, SIGQUIT));
+    assert(sigismember(&set, SIGINT));
+    assert(sigismember(&set, SIGVTALRM));
+  }
+  assert(sigismember(&set, SIGUSR2));
+}
+
+bool SignalThread::unblock()
+{
+  int error;
+  if ((error= pthread_sigmask(SIG_UNBLOCK, &set, NULL)) != 0)
+  {
+    Error << "While trying to reset signal mask to original set, pthread_sigmask() died during pthread_sigmask(" << strerror(error) << ")";
+    return false;
+  }
+
+  return true;
+}
+
+SignalThread::~SignalThread()
+{
+  if (is_shutdown() == false)
+  {
+    set_shutdown(SHUTDOWN_GRACEFUL);
+  }
+
+#if 0
+  if (pthread_equal(thread, pthread_self()) != 0 and (pthread_kill(thread, 0) == ESRCH) == true)
+  {
+    void *retval;
+    pthread_join(thread, &retval);
+  }
+#endif
+  sem_destroy(&lock);
+
+  unblock();
+}
+
+extern "C" {
+
+static void *sig_thread(void *arg)
+{   
+  SignalThread *context= (SignalThread*)arg;
+
+  context->test();
+  context->post();
+
+  while (context->get_shutdown() == SHUTDOWN_RUNNING)
+  {
+    int sig;
+
+    if (context->wait(sig) == -1)
+    {
+      Error << "sigwait() returned errno:" << strerror(errno);
+      continue;
+    }
+
+    switch (sig)
+    {
+    case SIGALRM:
+    case SIGVTALRM:
+      Error << strsignal(sig);
+      if (gdb_is_caller())
+      {
+        abort();
+      }
+      exit(EXIT_FAILURE);
+
+    case SIGABRT:
+    case SIGUSR2:
+    case SIGINT:
+    case SIGQUIT:
+      if (context->is_shutdown() == false)
+      {
+        context->set_shutdown(SHUTDOWN_FORCED);
+      }
+      break;
+    case SIGPIPE:
+      {
+        Error << "Ignoring SIGPIPE";
+      }
+      break;
+
+    case 0:
+      Error << "Inside of gdb";
+      break;
+
+    default:
+      Error << "Signal handling thread got unexpected signal " <<  strsignal(sig);
+      break;
+    }
+  }
+
+  return NULL;
+}
+
+}
+
+SignalThread::SignalThread() :
+  magic_memory(MAGIC_MEMORY),
+  thread(pthread_self())
+{
+  pthread_mutex_init(&shutdown_mutex, NULL);
+  sigemptyset(&set);
+  if (bool(getenv("LIBTEST_IN_GDB")) == false)
+  {
+    sigaddset(&set, SIGALRM);
+    sigaddset(&set, SIGABRT);
+    sigaddset(&set, SIGQUIT);
+    sigaddset(&set, SIGINT);
+    sigaddset(&set, SIGVTALRM);
+  }
+  sigaddset(&set, SIGPIPE);
+
+  sigaddset(&set, SIGUSR2);
+
+  sem_init(&lock, 0, 0);
+
+  sigemptyset(&original_set);
+  pthread_sigmask(SIG_BLOCK, NULL, &original_set);
+}
+
+
+bool SignalThread::setup()
+{
+  set_shutdown(SHUTDOWN_RUNNING);
+
+  if (sigismember(&original_set, SIGQUIT))
+  {
+    Error << strsignal(SIGQUIT) << " has been previously set.";
+  }
+
+  if (sigismember(&original_set, SIGINT))
+  {
+    Error << strsignal(SIGINT) << " has been previously set.";
+  }
+
+  if (sigismember(&original_set, SIGVTALRM))
+  {
+    Error << strsignal(SIGVTALRM) << " has been previously set.";
+  }
+
+  if (sigismember(&original_set, SIGUSR2))
+  {
+    Error << strsignal(SIGUSR2) << " has been previously set.";
+  }
+
+  int error;
+  if ((error= pthread_sigmask(SIG_BLOCK, &set, NULL)) != 0)
+  {
+    Error << "pthread_sigmask() died during pthread_sigmask(" << strerror(error) << ")";
+    return false;
+  }
+
+  if ((error= pthread_create(&thread, NULL, &sig_thread, this)) != 0)
+  {
+    Error << "pthread_create() died during pthread_create(" << strerror(error) << ")";
+    return false;
+  }
+
+  sem_wait(&lock);
+
+  return true;
+}
diff --git a/src/libtest/signal.h b/src/libtest/signal.h
new file mode 100644 (file)
index 0000000..6e68bb3
--- /dev/null
@@ -0,0 +1,80 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once 
+
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+
+enum shutdown_t {
+  SHUTDOWN_RUNNING,
+  SHUTDOWN_GRACEFUL,
+  SHUTDOWN_FORCED
+};
+
+namespace libtest {
+
+class SignalThread {
+  sigset_t set;
+  sem_t lock;
+  uint64_t magic_memory;
+  volatile shutdown_t __shutdown;
+  pthread_mutex_t shutdown_mutex;
+  pthread_t thread;
+  sigset_t original_set;
+
+public:
+
+  SignalThread();
+  ~SignalThread();
+
+  void test();
+  void post();
+  bool setup();
+  bool unblock();
+
+  int wait(int& sig)
+  {
+    return sigwait(&set, &sig);
+  }
+
+  void set_shutdown(shutdown_t arg);
+  bool is_shutdown();
+  shutdown_t get_shutdown();
+};
+
+} // namespace libtest
diff --git a/src/libtest/skiptest.cc b/src/libtest/skiptest.cc
new file mode 100644 (file)
index 0000000..098a575
--- /dev/null
@@ -0,0 +1,57 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include <libtest/test.hpp>
+
+#include <cstdlib>
+#include <unistd.h>
+
+using namespace libtest;
+
+
+static void *world_create(server_startup_st&, test_return_t& rc)
+{
+  rc= TEST_SKIPPED;
+
+  return NULL;
+}
+
+void get_world(libtest::Framework *world)
+{
+  world->create(world_create);
+}
diff --git a/src/libtest/socket.cc b/src/libtest/socket.cc
new file mode 100644 (file)
index 0000000..9e06841
--- /dev/null
@@ -0,0 +1,62 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+static char global_socket[1024]= { 0 };
+
+namespace libtest {
+
+const char *default_socket()
+{
+  if (global_socket[0] == 0)
+  {
+    return NULL;
+  }
+
+  return global_socket;
+}
+
+void set_default_socket(const char *socket)
+{
+  if (socket)
+  {
+    strncpy(global_socket, socket, sizeof(global_socket)-1);
+  }
+}
+
+}
diff --git a/src/libtest/socket.hpp b/src/libtest/socket.hpp
new file mode 100644 (file)
index 0000000..9d13c34
--- /dev/null
@@ -0,0 +1,47 @@
+
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+namespace libtest {
+
+const char *default_socket();
+
+void set_default_socket(const char *socket);
+
+} // namespace libtest
+
diff --git a/src/libtest/stream.h b/src/libtest/stream.h
new file mode 100644 (file)
index 0000000..0124b9d
--- /dev/null
@@ -0,0 +1,266 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <iostream>
+#include <cassert>
+#include <sstream>
+#include <ctime>
+#include <ostream>
+
+namespace libtest {
+namespace stream {
+
+namespace detail {
+
+template<class Ch, class Tr, class A>
+  class channel {
+  private:
+
+  public:
+    typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
+
+  public:
+    void operator()(const stream_buffer& s, std::ostream& _out,
+                    const char* filename, int line_number, const char* func)
+    {
+      if (filename)
+      {
+        _out
+          << filename 
+          << ":" 
+          << line_number 
+          << ": in " 
+          << func << "() "
+          << s.str()
+          << std::endl;
+      }
+      else
+      {
+        _out
+          << s.str()
+          << std::endl;
+      }
+    }
+  };
+
+template<class Ch, class Tr, class A>
+  class channelln {
+  private:
+
+  public:
+    typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
+
+  public:
+    void operator()(const stream_buffer& s, std::ostream& _out,
+                    const char* filename, int line_number, const char* func)
+    {
+      if (filename)
+      {
+        _out
+          << std::endl
+          << filename 
+          << ":" 
+          << line_number 
+          << ": in " 
+          << func << "() "
+          << s.str()
+          << std::endl;
+      }
+      else
+      {
+        _out
+          << std::endl
+          << s.str()
+          << std::endl;
+      }
+    }
+  };
+
+template<class Ch, class Tr, class A>
+  class channelfl {
+  private:
+
+  public:
+    typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
+
+  public:
+    void operator()(const stream_buffer& s, std::ostream& _out,
+                    const char* filename, int line_number, const char* func)
+    {
+      if (filename)
+      {
+        _out
+          << filename
+          << ":"
+          << line_number
+          << ": in "
+          << func << "() "
+          << s.str()
+          << std::flush;
+      }
+      else
+      {
+        _out
+          << s.str()
+          << std::flush;
+      }
+    }
+  };
+
+template<template <class Ch, class Tr, class A> class OutputPolicy, class Ch = char, class Tr = std::char_traits<Ch>, class A = std::allocator<Ch> >
+  class log {
+  private:
+    typedef OutputPolicy<Ch, Tr, A> output_policy;
+
+  private:
+    std::ostream& _out;
+    const char *_filename;
+    int _line_number;
+    const char *_func;
+
+  public:
+    log(std::ostream& out_arg, const char* filename, int line_number, const char* func) :
+      _out(out_arg),
+      _filename(filename),
+      _line_number(line_number),
+      _func(func)
+    { }
+
+    virtual ~log()
+    {
+      output_policy()(arg, _out, _filename, _line_number, _func);
+    }
+
+  public:
+    template<class T>
+      log &operator<<(const T &x)
+      {
+        arg << x;
+        return *this;
+      }
+
+  private:
+    typename output_policy::stream_buffer arg;
+
+  private:
+    log( const log& );
+    const log& operator=( const log& );
+  };
+} // namespace detail
+
+class make_cerr : public detail::log<detail::channelln> {
+public:
+  make_cerr(const char* filename, int line_number, const char* func) :
+    detail::log<detail::channelln>(std::cerr, filename, line_number, func)
+  { }
+
+private:
+  make_cerr( const make_cerr& );
+  const make_cerr& operator=( const make_cerr& );
+};
+
+class cerr : public detail::log<detail::channel> {
+public:
+  cerr(const char* filename, int line_number, const char* func) :
+    detail::log<detail::channel>(std::cout, filename, line_number, func)
+  { }
+
+private:
+  cerr( const cerr& );
+  const cerr& operator=( const cerr& );
+};
+
+class clog : public detail::log<detail::channel> {
+public:
+  clog(const char* filename, int line_number, const char* func) :
+    detail::log<detail::channel>(std::clog, filename, line_number, func)
+  { }
+
+private:
+  clog( const clog& );
+  const clog& operator=( const clog& );
+};
+
+class make_cout : public detail::log<detail::channelln> {
+public:
+  make_cout(const char* filename, int line_number, const char* func) :
+    detail::log<detail::channelln>(std::cout, filename, line_number, func)
+  { }
+
+private:
+  make_cout( const make_cout& );
+  const make_cout& operator=( const make_cout& );
+};
+
+class cout : public detail::log<detail::channel> {
+public:
+  cout(const char* filename, int line_number, const char* func) :
+    detail::log<detail::channel>(std::cout, filename, line_number, func)
+  { }
+
+private:
+  cout( const cout& );
+  const cout& operator=( const cout& );
+};
+
+class cecho : public detail::log<detail::channelfl> {
+public:
+  cecho(const char* filename, int line_number, const char* func) :
+    detail::log<detail::channelfl>(std::cout, filename, line_number, func)
+  { }
+
+private:
+  cecho( const cecho& );
+  const cecho& operator=( const cecho& );
+};
+
+} // namespace stream
+
+#define Error stream::cerr(__FILE__, __LINE__, __func__)
+
+#define Echo stream::cecho(NULL, __LINE__, __func__)
+
+#define Out stream::cout(NULL, __LINE__, __func__)
+
+#define Outn() stream::cout(NULL, __LINE__, __func__) << " "
+
+#define Log stream::clog(NULL, __LINE__, __func__)
+
+#define Logn() stream::clog(NULL, __LINE__, __func__) << " "
+
+} // namespace libtest
diff --git a/src/libtest/strerror.cc b/src/libtest/strerror.cc
new file mode 100644 (file)
index 0000000..ebbc1e4
--- /dev/null
@@ -0,0 +1,71 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+namespace libtest { 
+
+const char *test_strerror(test_return_t code)
+{
+  switch (code) {
+  case TEST_SUCCESS:
+    return "ok";
+
+  case TEST_FAILURE:
+    return "failed";
+
+  case TEST_SKIPPED:
+    return "skipped";
+  }
+
+  FATAL("No port could be found");
+}
+
+} // namespace libtest
+
+
+std::ostream& operator<<(std::ostream& output, const enum test_return_t &arg)
+{
+  output << libtest::test_strerror(arg);
+  return output;
+}
+
+std::ostream& operator<<(std::ostream& output, const std::vector<char> &arg)
+{
+  output << "std::vector<char>:" << arg.size(); 
+  return output;
+}
diff --git a/src/libtest/strerror.h b/src/libtest/strerror.h
new file mode 100644 (file)
index 0000000..4c2e2d2
--- /dev/null
@@ -0,0 +1,54 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <vector>
+#include <iostream>
+
+namespace libtest {
+
+/**
+  @note Friendly print function for errors.
+*/
+LIBTEST_API
+const char *test_strerror(test_return_t code);
+
+} // namespace libtest
+
+std::ostream& operator<<(std::ostream& output, const enum test_return_t &arg);
+std::ostream& operator<<(std::ostream& output, const std::vector<char> &arg);
+
diff --git a/src/libtest/string.hpp b/src/libtest/string.hpp
new file mode 100644 (file)
index 0000000..c32c819
--- /dev/null
@@ -0,0 +1,46 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include "util/string.hpp"
+
+#define test_literal_param util_literal_param
+#define test_literal_compare_param util_literal_compare_param
+#define test_literal_param_size util_literal_param_size
+#define test_string_make_from_cstr util_string_make_from_cstr
+#define test_string_make_from_array util_string_make_from_array
+#define test_array_length util_array_length
diff --git a/src/libtest/test.h b/src/libtest/test.h
new file mode 100644 (file)
index 0000000..3c3c37d
--- /dev/null
@@ -0,0 +1,210 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+#include <libtest/lite.h>
+
+/**
+  A structure describing the test case.
+*/
+struct test_st {
+  const char *name;
+  bool requires_flush;
+  test_callback_fn *test_fn;
+};
+
+#define test_assert_errno(A) \
+do \
+{ \
+  if ((A)) { \
+    fprintf(stderr, "\n%s:%d: Assertion failed for %s: ", __FILE__, __LINE__, __func__);\
+    perror(#A); \
+    fprintf(stderr, "\n"); \
+    libtest::create_core(); \
+    assert((A)); \
+  } \
+} while (0)
+
+#define test_truth(A) \
+do \
+{ \
+  if (! (A)) { \
+    fprintf(stderr, "\n%s:%d: Assertion \"%s\" failed, in %s\n", __FILE__, __LINE__, #A, __func__);\
+    libtest::create_core(); \
+    return TEST_FAILURE; \
+  } \
+} while (0)
+
+#define test_true(A) \
+do \
+{ \
+  if (! (A)) { \
+    fprintf(stderr, "\n%s:%d: Assertion \"%s\" failed, in %s\n", __FILE__, __LINE__, #A, __func__);\
+    libtest::create_core(); \
+    return TEST_FAILURE; \
+  } \
+} while (0)
+
+#define test_true_got(A, B) test_true(A);
+#define test_true_hint(A, B) test_true(A);
+
+#define test_compare_hint(A, B, C) test_compare(A, B);
+#define test_compare_got(A, B, C) test_compare(A, B);
+
+#define test_skip(__expected, __actual) \
+do \
+{ \
+  if (libtest::_compare(__FILE__, __LINE__, __func__, ((__expected)), ((__actual)), false) == false) \
+  { \
+    return TEST_SKIPPED; \
+  } \
+} while (0)
+
+#define test_skip_valgrind() \
+do \
+{ \
+  if (libtest::_in_valgrind(__FILE__, __LINE__, __func__)) \
+  { \
+    return TEST_SKIPPED; \
+  } \
+} while (0)
+
+#define test_fail(A) \
+do \
+{ \
+  if (1) { \
+    fprintf(stderr, "\n%s:%d: Failed with %s, in %s\n", __FILE__, __LINE__, #A, __func__);\
+    libtest::create_core(); \
+    return TEST_FAILURE; \
+  } \
+} while (0)
+
+
+#define test_false(A) \
+do \
+{ \
+  if ((A)) { \
+    fprintf(stderr, "\n%s:%d: Assertion failed %s, in %s\n", __FILE__, __LINE__, #A, __func__);\
+    libtest::create_core(); \
+    return TEST_FAILURE; \
+  } \
+} while (0)
+
+#define test_false_with(A,B) \
+do \
+{ \
+  if ((A)) { \
+    fprintf(stderr, "\n%s:%d: Assertion failed %s with %s\n", __FILE__, __LINE__, #A, (B));\
+    libtest::create_core(); \
+    return TEST_FAILURE; \
+  } \
+} while (0)
+
+#define test_ne_compare(__expected, __actual) \
+do \
+{ \
+  if (libtest::_ne_compare(__FILE__, __LINE__, __func__, ((__expected)), ((__actual)), true) == false) \
+  { \
+    libtest::create_core(); \
+    return TEST_FAILURE; \
+  } \
+} while (0)
+
+#define test_compare(__expected, __actual) \
+do \
+{ \
+  if (libtest::_compare(__FILE__, __LINE__, __func__, ((__expected)), ((__actual)), true) == false) \
+  { \
+    libtest::create_core(); \
+    return TEST_FAILURE; \
+  } \
+} while (0)
+
+#define test_zero(__actual) \
+do \
+{ \
+  if (libtest::_compare_zero(__FILE__, __LINE__, __func__, ((__actual))) == false) \
+  { \
+    libtest::create_core(); \
+    return TEST_FAILURE; \
+  } \
+} while (0)
+
+#define test_null test_zero
+
+#define test_compare_warn(__expected, __actual) \
+do \
+{ \
+  void(libtest::_compare(__FILE__, __LINE__, __func__, (__expected), (__actual)), true); \
+} while (0)
+
+#define test_warn(__truth, __explain) \
+do \
+{ \
+  void(libtest::_assert_truth(__FILE__, __LINE__, __func__, bool((__truth)), #__truth, __explain)); \
+} while (0)
+
+#define test_strcmp(__expected, __actual) \
+do \
+{ \
+  void(libtest::_compare_strcmp(__FILE__, __LINE__, __func__, (__expected), (__actual))); \
+} while (0)
+
+#define test_memcmp(A,B,C) \
+do \
+{ \
+  if ((A) == NULL or (B) == NULL or memcmp((A), (B), (C))) \
+  { \
+    fprintf(stderr, "\n%s:%d: %.*s -> %.*s\n", __FILE__, __LINE__, (int)(C), (char *)(A), (int)(C), (char *)(B)); \
+    libtest::create_core(); \
+    return TEST_FAILURE; \
+  } \
+} while (0)
+
+#define test_return_if(__test_return_t) \
+do \
+{ \
+  if ((__test_return_t) != TEST_SUCCESS) \
+  { \
+    return __test_return_t; \
+  } \
+} while (0)
+
diff --git a/src/libtest/test.hpp b/src/libtest/test.hpp
new file mode 100644 (file)
index 0000000..d904070
--- /dev/null
@@ -0,0 +1,102 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+  Structures for generic tests.
+*/
+
+#pragma once
+
+#ifndef YATL_FULL
+# define YATL_FULL 1
+#endif
+
+#ifndef __PRETTY_FUNCTION__
+# define __PRETTY_FUNCTION__ __func__
+#endif
+
+#define YATL_STRINGIFY(x) #x
+#define YATL_TOSTRING(x) YATL_STRINGIFY(x)
+#define YATL_AT __FILE__ ":" YATL_TOSTRING(__LINE__)
+#define YATL_AT_PARAM __func__, AT
+#define YATL_UNIQUE __FILE__ ":" YATL_TOSTRING(__LINE__) "_unique"
+#define YATL_UNIQUE_FUNC_NAME __FILE__ ":" YATL_TOSTRING(__LINE__) "_unique_func"
+
+#define LIBYATL_DEFAULT_PARAM __FILE__, __LINE__, __PRETTY_FUNCTION__
+
+#include <cstdio>
+#include <cstdlib>
+#include <arpa/inet.h>
+
+#include <libtest/visibility.h>
+#include <libtest/version.h>
+
+#include <libtest/vchar.hpp>
+#include <libtest/error.h>
+#include <libtest/exception.hpp>
+#include <libtest/exception/disconnected.hpp>
+#include <libtest/exception/fatal.hpp>
+#include <libtest/result.hpp>
+
+#include <libtest/has.hpp>
+#include <libtest/error.h>
+#include <libtest/strerror.h>
+#include <libtest/timer.hpp>
+#include <libtest/alarm.h>
+#include <libtest/stream.h>
+#include <libtest/comparison.hpp>
+#include <libtest/server.h>
+#include <libtest/server_container.h>
+#include <libtest/wait.h>
+#include <libtest/callbacks.h>
+#include <libtest/test.h>
+#include <libtest/dream.h>
+#include <libtest/core.h>
+#include <libtest/runner.h>
+#include <libtest/port.h>
+#include <libtest/is_local.hpp>
+#include <libtest/socket.hpp>
+#include <libtest/collection.h>
+#include <libtest/framework.h>
+#include <libtest/get.h>
+#include <libtest/cmdline.h>
+#include <libtest/string.hpp>
+#include <libtest/binaries.h>
+#include <libtest/http.hpp>
+#include <libtest/cpu.hpp>
+#include <libtest/tmpfile.hpp>
+#include <libtest/client.hpp>
+#include <libtest/thread.hpp>
diff --git a/src/libtest/thread.hpp b/src/libtest/thread.hpp
new file mode 100644 (file)
index 0000000..640cb66
--- /dev/null
@@ -0,0 +1,329 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <pthread.h>
+
+#if __cplusplus < 201103L
+# define noexcept(a)
+#endif
+
+namespace libtest
+{
+namespace thread
+{
+
+class Mutex
+{
+public:
+  Mutex() :
+    _err(0)
+  {
+    _err= pthread_mutex_init(&_mutex, NULL);
+  }
+
+  ~Mutex() noexcept(false)
+  {
+    if ((_err= pthread_mutex_destroy(&_mutex)))
+    {
+      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_cond_destroy: %s", strerror(_err));
+    }
+  }
+
+  pthread_mutex_t* handle()
+  {
+    if (_err != 0)
+    {
+      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_mutex_init: %s", strerror(_err));
+    }
+
+    return &_mutex;
+  }
+
+private:
+  int _err;
+  pthread_mutex_t _mutex;
+};
+
+class ScopedLock
+{
+public:
+  ScopedLock(Mutex& mutex_) :
+    _mutex(mutex_)
+  {
+    init();
+  }
+
+  ~ScopedLock() noexcept(false)
+  {
+    int err;
+    if ((err= pthread_mutex_unlock(_mutex.handle())))
+    {
+      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_mutex_unlock: %s", strerror(err));
+    }
+  }
+
+  Mutex* handle()
+  {
+    return &_mutex;
+  }
+
+private:
+  void init()
+  {
+    int err;
+    if ((err= pthread_mutex_lock(_mutex.handle())))
+    {
+      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_mutex_lock: %s", strerror(err));
+    }
+  }
+
+private:
+  Mutex& _mutex;
+};
+
+class Condition
+{
+public:
+  Condition()
+  {
+    int err;
+    if ((err= pthread_cond_init(&_cond, NULL)))
+    {
+      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_mutex_init: %s", strerror(err));
+    }
+  }
+
+  ~Condition() noexcept(false)
+  {
+    int err;
+    if ((err= pthread_cond_destroy(&_cond)))
+    {
+      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_cond_destroy: %s", strerror(err));
+    }
+  }
+
+  void broadcast()
+  {
+    int err;
+    if ((err= pthread_cond_broadcast(&_cond)))
+    {
+      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_cond_broadcast: %s", strerror(err));
+    }
+  }
+
+  void signal()
+  {
+    int err;
+    if ((err= pthread_cond_signal(&_cond)))
+    {
+      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_cond_broadcast: %s", strerror(err));
+    }
+  }
+
+  void wait(ScopedLock& lock_)
+  {
+    int err;
+    if ((err= pthread_cond_wait(&_cond, lock_.handle()->handle())))
+    {
+      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_cond_wait: %s", strerror(err));
+    }
+  }
+
+private:
+  pthread_cond_t _cond;
+};
+
+class Barrier
+{
+public:
+  explicit Barrier(uint32_t count): 
+    _threshold(count),
+    _count(count),
+    _generation(0)
+  {   
+    if (_count == 0)
+    {
+      fatal_assert("Zero is an invalid value");
+    }
+  }
+
+  ~Barrier()
+  {
+  }
+
+  bool wait()
+  {   
+    ScopedLock l(_mutex);
+    uint32_t gen = _generation;
+
+    if (--_count == 0)
+    {   
+      _generation++;
+      _count = _threshold;
+      _cond.broadcast();
+
+      return true;
+    }
+
+    while (gen == _generation)
+    {
+      _cond.wait(l);
+    }
+
+    return false;
+  }
+
+private:
+  Mutex _mutex;
+  Condition _cond;
+  uint32_t _threshold;
+  uint32_t _count;
+  uint32_t _generation;
+};
+
+class Thread 
+{
+private:
+  typedef void *(*start_routine_fn) (void *);
+
+public:
+  template <class Function,class Arg1>
+    Thread(Function func, Arg1 arg):
+      _joined(false),
+      _func((start_routine_fn)func),
+      _context(arg)
+    {
+      int err;
+      if ((err= pthread_create(&_thread, NULL, entry_func, (void*)this)))
+      {
+        throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_create: %s", strerror(err));
+      }
+      _owner= pthread_self();
+    }
+
+  bool running() const
+  {
+    return (pthread_kill(_thread, 0) == 0);
+  }
+
+  bool detached()
+  {
+    if (EDEADLK == pthread_join(_thread, NULL))
+    {
+      return true;
+    }
+
+    /* Result of pthread_join was EINVAL == detached thread */
+    return false;
+  } 
+
+  bool join()
+  {
+    if (_thread == pthread_self())
+    {
+      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "Thread cannot join on itself");
+    }
+
+    if (_owner != pthread_self())
+    {
+      throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "Attempt made by a non-owner thead to join on thread");
+    }
+
+    bool ret= false;
+    {
+      ScopedLock l(_join_mutex);
+      if (_joined == false)
+      {
+        int err;
+        if ((err= pthread_join(_thread, NULL)))
+        {
+          switch(err)
+          {
+          case EINVAL:
+            break;
+
+          case ESRCH:
+            ret= true;
+            break;
+
+          case EDEADLK:
+          default:
+            throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "pthread_join: %s", strerror(err));
+          }
+        }
+        else
+        {
+          ret= true;
+        }
+
+        _joined= true;
+      }
+    }
+
+    return ret;
+  }
+
+  ~Thread()
+  {
+    join();
+  }
+
+protected:
+  void run()
+  {
+    _func(_context);
+  }
+
+private:
+  static void * entry_func(void* This)
+  {
+    ((Thread *)This)->run();
+    return NULL;
+  }
+
+private:
+  bool _joined;
+  pthread_t _thread;
+  pthread_t _owner;
+  start_routine_fn _func;
+  void* _context;
+  Mutex _join_mutex;
+};
+
+} // namespace thread
+} // namespace libtest
diff --git a/src/libtest/timer.cc b/src/libtest/timer.cc
new file mode 100644 (file)
index 0000000..fae814c
--- /dev/null
@@ -0,0 +1,150 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include <libtest/timer.hpp>
+
+#include <ctime>
+#include <iomanip>
+
+#ifdef __MACH__
+# include <mach/clock.h>
+# include <mach/mach.h>
+#else
+# include <sys/time.h>
+#endif
+
+namespace libtest {
+
+Timer::Timer()
+{
+  _begin.tv_sec= 0;
+  _begin.tv_nsec= 0;
+  _end.tv_sec= 0;
+  _end.tv_nsec= 0;
+}
+
+void Timer::reset()
+{
+  _end.tv_sec= 0;
+  _end.tv_nsec= 0;
+  _time(_begin);
+}
+
+void Timer::sample()
+{
+  _time(_end);
+}
+
+void Timer::offset(int64_t minutes_arg, int64_t seconds_arg, int64_t nanoseconds)
+{
+  reset();
+  _end= _begin;
+  _end.tv_sec+= (minutes_arg * 60) +seconds_arg;
+  _end.tv_nsec+= nanoseconds;
+}
+
+int64_t Timer::minutes()
+{
+  struct timespec result;
+  difference(result);
+  return int64_t(result.tv_sec / 60);
+}
+
+uint64_t Timer::elapsed_milliseconds() const
+{
+  struct timespec temp;
+  difference(temp);
+
+  return temp.tv_sec*1000 +temp.tv_nsec/1000000;
+}
+
+void Timer::difference(struct timespec& arg) const
+{
+  if ((_end.tv_nsec -_begin.tv_nsec) < 0)
+  {
+    arg.tv_sec= _end.tv_sec -_begin.tv_sec -1;
+    arg.tv_nsec= 1000000000 +_end.tv_nsec -_begin.tv_nsec;
+
+  }
+  else
+  {
+    arg.tv_sec= _end.tv_sec -_begin.tv_sec;
+    arg.tv_nsec= _end.tv_nsec -_begin.tv_nsec;
+  }
+}
+
+void Timer::_time(struct timespec& ts)
+{
+#ifdef __MACH__ // OSX lacks clock_gettime()
+  clock_serv_t _clock_serv;
+  mach_timespec_t _mach_timespec;
+  host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &_clock_serv);
+  clock_get_time(_clock_serv, &_mach_timespec);
+  mach_port_deallocate(mach_task_self(), _clock_serv);
+  ts.tv_sec= _mach_timespec.tv_sec;
+  ts.tv_nsec= _mach_timespec.tv_nsec;
+#elif defined(_WIN32)
+  ts.tv_sec= time(NULL);
+  ts.tv_nsec= 0;
+#else
+  clock_gettime(CLOCK_REALTIME, &ts);
+#endif
+}
+
+std::ostream& operator<<(std::ostream& output, const libtest::Timer& arg)
+{
+  struct timespec temp;
+  arg.difference(temp);
+
+  if (temp.tv_sec > 60)
+  {
+    output << temp.tv_sec / 60;
+    output << "." << temp.tv_sec % 60;
+  }
+  else
+  {
+    output << temp.tv_sec;
+  }
+
+  output << ":";
+  output << std::setfill('0') << std::setw(9) << temp.tv_nsec;
+
+  return output;
+}
+
+} // namespace libtest
diff --git a/src/libtest/timer.hpp b/src/libtest/timer.hpp
new file mode 100644 (file)
index 0000000..18ed3e8
--- /dev/null
@@ -0,0 +1,73 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <cstdlib>
+#include <ctime>
+#include <iostream>
+
+
+namespace libtest {
+
+class Timer {
+public:
+
+  Timer();
+
+  void reset();
+
+  void sample();
+
+  void offset(int64_t minutes_arg, int64_t seconds_arg, int64_t nanoseconds);
+
+  int64_t minutes();
+
+  uint64_t elapsed_milliseconds() const;
+
+  void difference(struct timespec& arg) const;
+
+private:
+  void _time(struct timespec& ts);
+
+private:
+  struct timespec _begin;
+  struct timespec _end;
+};
+
+std::ostream& operator<<(std::ostream& output, const libtest::Timer& arg);
+
+} // namespace libtest
diff --git a/src/libtest/tmpfile.cc b/src/libtest/tmpfile.cc
new file mode 100644 (file)
index 0000000..425a21e
--- /dev/null
@@ -0,0 +1,70 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include <libtest/common.h>
+
+namespace libtest {
+
+std::string create_tmpfile(const std::string& name, int& fd)
+{
+  libtest::vchar_t file_buffer;
+  file_buffer.resize(FILENAME_MAX);
+  file_buffer[0]= 0;
+
+  int length= snprintf(&file_buffer[0], file_buffer.size(), "var/tmp/%s.XXXXXX", name.c_str());
+  fatal_assert(length > 0);
+
+  if ((fd= mkstemp(&file_buffer[0])) == -1)
+  {
+    throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "mkstemp() failed on %s with %s", &file_buffer[0], strerror(errno));
+  }
+
+  return &file_buffer[0];
+}
+
+std::string create_tmpfile(const std::string& name)
+{
+  int fd;
+  std::string ret_file= create_tmpfile(name, fd);
+  close(fd);
+  unlink(ret_file.c_str());
+
+  return ret_file.c_str();
+}
+
+} // namespace libtest
diff --git a/src/libtest/tmpfile.hpp b/src/libtest/tmpfile.hpp
new file mode 100644 (file)
index 0000000..9283b84
--- /dev/null
@@ -0,0 +1,47 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <libtest/common.h>
+
+namespace libtest {
+
+std::string create_tmpfile(const std::string&, int&);
+std::string create_tmpfile(const std::string&);
+
+} // namespace libtest
+
diff --git a/src/libtest/unittest.cc b/src/libtest/unittest.cc
new file mode 100644 (file)
index 0000000..fafe032
--- /dev/null
@@ -0,0 +1,1233 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include <libtest/yatl.h>
+
+#if defined(HAVE_LIBMEMCACHED_1_0_TYPES_RETURN_H) && HAVE_LIBMEMCACHED_1_0_TYPES_RETURN_H
+# include <libmemcached-1.0/types/return.h>
+#endif
+
+#if defined(HAVE_LIBGEARMAN_1_0_RETURN_H) && HAVE_LIBGEARMAN_1_0_RETURN_H
+# include <libgearman-1.0/return.h>
+#endif
+
+#include <cstdlib>
+#include <unistd.h>
+
+using namespace libtest;
+
+static std::string testing_service;
+
+// Used to track setups where we see if failure is happening
+static uint32_t fatal_calls= 0;
+
+static test_return_t getenv_TEST(void *)
+{
+#if 0
+  for (char **ptr= environ; *ptr; ptr++)
+  {
+    Error << *ptr;
+  }
+#endif
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t LIBTOOL_COMMAND_test(void *)
+{
+  test_true(getenv("LIBTOOL_COMMAND"));
+  return TEST_SUCCESS;
+}
+
+static test_return_t VALGRIND_COMMAND_test(void *)
+{
+  test_true(getenv("VALGRIND_COMMAND"));
+  return TEST_SUCCESS;
+}
+
+static test_return_t HELGRIND_COMMAND_test(void *)
+{
+  test_true(getenv("HELGRIND_COMMAND"));
+  return TEST_SUCCESS;
+}
+
+static test_return_t GDB_COMMAND_test(void *)
+{
+  test_true(getenv("GDB_COMMAND"));
+  return TEST_SUCCESS;
+}
+
+static test_return_t test_success_equals_one_test(void *)
+{
+  test_skip(HAVE_LIBMEMCACHED, 1);
+#if defined(HAVE_LIBMEMCACHED_1_0_TYPES_RETURN_H) && HAVE_LIBMEMCACHED_1_0_TYPES_RETURN_H
+  test_zero(MEMCACHED_SUCCESS);
+#endif
+  return TEST_SUCCESS;
+}
+
+static test_return_t test_success_test(void *)
+{
+  return TEST_SUCCESS;
+}
+
+static test_return_t test_throw_success_TEST(void *)
+{
+  try {
+    _SUCCESS;
+  }
+  catch (const libtest::__success&)
+  {
+    return TEST_SUCCESS;
+  }
+  catch (...)
+  {
+    return TEST_FAILURE;
+  }
+
+  return TEST_FAILURE;
+}
+
+static test_return_t test_throw_skip_macro_TEST(void *)
+{
+  try {
+    SKIP_IF(true);
+  }
+  catch (const libtest::__skipped&)
+  {
+    return TEST_SUCCESS;
+  }
+  catch (...)
+  {
+    FAIL("SLIP_IF() failed to throw libtest::_skipped");
+  }
+
+  FAIL("SLIP_IF() failed to throw");
+
+  return TEST_FAILURE;
+}
+
+static test_return_t test_throw_skip_unless_macro_TEST(void *)
+{
+  try {
+    SKIP_UNLESS(false);
+  }
+  catch (const libtest::__skipped&)
+  {
+    return TEST_SUCCESS;
+  }
+  catch (...)
+  {
+    FAIL("SLIP_UNLESS() failed to throw libtest::_skipped");
+  }
+
+  FAIL("SLIP_UNLESS() failed to throw");
+
+  return TEST_FAILURE;
+}
+
+static test_return_t test_throw_skip_TEST(void *)
+{
+  try {
+    throw libtest::__skipped(LIBYATL_DEFAULT_PARAM, "basic test");
+  }
+  catch (const libtest::__skipped&)
+  {
+    return TEST_SUCCESS;
+  }
+  catch (...)
+  {
+    FAIL("SLIP_IF() failed to throw libtest::_skipped");
+  }
+
+  FAIL("SLIP_IF() failed to throw");
+
+  return TEST_FAILURE;
+}
+
+static test_return_t test_throw_fail_TEST(void *)
+{
+  try {
+    FAIL("test message!");
+  }
+  catch (const libtest::__failure& e)
+  {
+    std::string compare_message("test message!");
+    test_zero(compare_message.compare(e.what()));
+    return TEST_SUCCESS;
+  }
+  catch (...)
+  {
+    return TEST_FAILURE;
+  }
+
+  return TEST_FAILURE;
+}
+#pragma GCC diagnostic ignored "-Wstack-protector"
+
+#ifdef __clang__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wformat-security"
+#endif
+
+static test_return_t ASSERT_FALSE__TEST(void *)
+{
+  try {
+    ASSERT_FALSE(true);
+  }
+  catch (const libtest::__failure& e)
+  {
+    ASSERT_STREQ(e.what(), "Assertion '!true'");
+    return TEST_SUCCESS;
+  }
+  catch (...)
+  {
+    return TEST_FAILURE;
+  }
+
+  return TEST_FAILURE;
+}
+
+#ifdef __clang__
+# pragma GCC diagnostic pop
+#endif
+
+static test_return_t ASSERT_NEQ_FAIL_TEST(void *)
+{
+  try {
+    ASSERT_NEQ(1,1);
+  }
+  catch (const libtest::__failure& e)
+  {
+    ASSERT_STREQ(e.what(), "Assertion '1' == '1'");
+    return TEST_SUCCESS;
+  }
+  catch (...)
+  {
+    return TEST_FAILURE;
+  }
+
+  return TEST_FAILURE;
+}
+
+static test_return_t ASSERT_NEQ_TEST(void *)
+{
+  ASSERT_NEQ(1,0);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t ASSERT_FALSE_TEST(void *)
+{
+  try {
+    FAIL(__func__);
+  }
+  catch (const libtest::__failure& e)
+  {
+    ASSERT_STREQ(e.what(), __func__);
+    return TEST_SUCCESS;
+  }
+  catch (...)
+  {
+    return TEST_FAILURE;
+  }
+
+  return TEST_FAILURE;
+}
+
+static test_return_t test_failure_test(void *)
+{
+  return TEST_SKIPPED; // Only run this when debugging
+
+  ASSERT_EQ(1, 2);
+  return TEST_SUCCESS;
+}
+
+static test_return_t local_test(void *)
+{
+  if (getenv("LIBTEST_LOCAL"))
+  {
+    test_true(test_is_local());
+  }
+  else
+  {
+    test_false(test_is_local());
+  }
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t local_not_test(void *)
+{
+  return TEST_SKIPPED;
+
+  std::string temp;
+
+  const char *ptr;
+  if ((ptr= getenv("LIBTEST_LOCAL")) == NULL)
+  {
+    temp.append(ptr);
+  }
+
+  // unsetenv() will cause issues with valgrind
+  _compare(__FILE__, __LINE__, __func__, 0, unsetenv("LIBTEST_LOCAL"), true);
+  ASSERT_EQ(0, unsetenv("LIBTEST_LOCAL"));
+  test_false(test_is_local());
+
+  ASSERT_EQ(0, setenv("LIBTEST_LOCAL", "1", 1));
+  test_true(test_is_local());
+
+  if (temp.empty())
+  {
+    ASSERT_EQ(0, unsetenv("LIBTEST_LOCAL"));
+  }
+  else
+  {
+    char *old_string= strdup(temp.c_str());
+    ASSERT_EQ(0, setenv("LIBTEST_LOCAL", old_string, 1));
+  }
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_exists_test(void *)
+{
+  ASSERT_EQ(0, access("var", R_OK | W_OK | X_OK));
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_tmp_exists_test(void *)
+{
+  ASSERT_EQ(0, access("var/tmp", R_OK | W_OK | X_OK));
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_run_exists_test(void *)
+{
+  ASSERT_EQ(0, access("var/run", R_OK | W_OK | X_OK));
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_log_exists_test(void *)
+{
+  ASSERT_EQ(0, access("var/log", R_OK | W_OK | X_OK));
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_drizzle_exists_test(void *)
+{
+  ASSERT_EQ(0, access("var/drizzle", R_OK | W_OK | X_OK));
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_tmp_test(void *)
+{
+  FILE *file= fopen("var/tmp/junk", "w+");
+  test_true(file);
+  fclose(file);
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_run_test(void *)
+{
+  FILE *file= fopen("var/run/junk", "w+");
+  test_true(file);
+  fclose(file);
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_log_test(void *)
+{
+  FILE *file= fopen("var/log/junk", "w+");
+  test_true(file);
+  fclose(file);
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_drizzle_test(void *)
+{
+  FILE *file= fopen("var/drizzle/junk", "w+");
+  test_true(file);
+  fclose(file);
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_tmp_rm_test(void *)
+{
+  test_true(unlink("var/tmp/junk") == 0);
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_run_rm_test(void *)
+{
+  test_true(unlink("var/run/junk") == 0);
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_log_rm_test(void *)
+{
+  test_true(unlink("var/log/junk") == 0);
+  return TEST_SUCCESS;
+}
+
+static test_return_t var_drizzle_rm_test(void *)
+{
+  test_true(unlink("var/drizzle/junk") == 0);
+  return TEST_SUCCESS;
+}
+
+static test_return_t _compare_test_return_t_test(void *)
+{
+  ASSERT_EQ(TEST_SUCCESS, TEST_SUCCESS);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t _compare_memcached_return_t_test(void *)
+{
+  test_skip(HAVE_LIBMEMCACHED, true);
+#if defined(HAVE_LIBMEMCACHED_1_0_TYPES_RETURN_H) && HAVE_LIBMEMCACHED_1_0_TYPES_RETURN_H
+  ASSERT_EQ(MEMCACHED_SUCCESS, MEMCACHED_SUCCESS);
+#endif
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t _compare_gearman_return_t_test(void *)
+{
+  test_skip(HAVE_LIBGEARMAN, true);
+#if defined(HAVE_LIBGEARMAN_1_0_RETURN_H) && HAVE_LIBGEARMAN_1_0_RETURN_H
+  ASSERT_EQ(GEARMAN_SUCCESS, GEARMAN_SUCCESS);
+#endif
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t drizzled_cycle_test(void *object)
+{
+  server_startup_st *servers= (server_startup_st*)object;
+  test_true(servers and servers->validate());
+
+#if defined(HAVE_GEARMAND_BINARY) && HAVE_GEARMAND_BINARY
+  test_true(has_drizzled());
+#endif
+
+  test_skip(true, has_drizzled());
+
+  test_skip(true, server_startup(*servers, "drizzled", get_free_port(), NULL));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t gearmand_cycle_test(void *object)
+{
+  server_startup_st *servers= (server_startup_st*)object;
+  test_true(servers and servers->validate());
+
+  test_skip(true, has_gearmand());
+  test_skip(true, server_startup(*servers, "gearmand", get_free_port(), NULL));
+  servers->clear();
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t skip_shim(bool a, bool b)
+{
+  test_skip(a, b);
+  return TEST_SUCCESS;
+}
+
+static test_return_t test_skip_true_TEST(void*)
+{
+  ASSERT_EQ(true, true);
+  ASSERT_EQ(false, false);
+  ASSERT_EQ(TEST_SUCCESS, skip_shim(true, true));
+  ASSERT_EQ(TEST_SUCCESS, skip_shim(false, false));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t test_skip_false_TEST(void*)
+{
+  ASSERT_EQ(TEST_SKIPPED, skip_shim(true, false));
+  ASSERT_EQ(TEST_SKIPPED, skip_shim(false, true));
+  return TEST_SUCCESS;
+}
+
+static test_return_t server_startup_fail_TEST(void *object)
+{
+  server_startup_st *servers= (server_startup_st*)object;
+  test_true(servers);
+
+  fatal::disable();
+  ASSERT_EQ(servers->start_server(testing_service, LIBTEST_FAIL_PORT, NULL), true);
+  fatal::enable();
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t server_startup_TEST(void *object)
+{
+  server_startup_st *servers= (server_startup_st*)object;
+  test_true(servers);
+
+  ASSERT_EQ(servers->start_server(testing_service, get_free_port(), NULL), true);
+
+  test_true(servers->last());
+  pid_t last_pid= servers->last()->pid();
+
+  ASSERT_EQ(servers->last()->pid(), last_pid);
+  test_true(last_pid > 1);
+  ASSERT_EQ(kill(last_pid, 0), 0);
+
+  test_true(servers->shutdown());
+#if 0
+  ASSERT_EQ(servers->last()->pid(), -1);
+  ASSERT_EQ(kill(last_pid, 0), -1);
+#endif
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t socket_server_startup_TEST(void *object)
+{
+  server_startup_st *servers= (server_startup_st*)object;
+  test_true(servers);
+
+  test_true(servers->start_socket_server(testing_service, get_free_port(), NULL));
+
+  return TEST_SUCCESS;
+}
+
+#if 0
+static test_return_t memcached_sasl_test(void *object)
+{
+  server_startup_st *servers= (server_startup_st*)object;
+  test_true(servers);
+
+  test_skip(false, bool(getenv("LOG_COMPILER")));
+
+  if (MEMCACHED_SASL_BINARY)
+  {
+    if (HAVE_LIBMEMCACHED)
+    {
+      test_true(has_memcached_sasl());
+      test_true(server_startup(*servers, "memcached-sasl", get_free_port(), NULL));
+
+      return TEST_SUCCESS;
+    }
+  }
+
+  return TEST_SKIPPED;
+}
+#endif
+
+static test_return_t application_true_BINARY(void *)
+{
+  test_skip(0, access("/usr/bin/true", X_OK ));
+  Application true_app("/usr/bin/true");
+
+  ASSERT_EQ(Application::SUCCESS, true_app.run());
+  ASSERT_EQ(Application::SUCCESS, true_app.join());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t application_gdb_true_BINARY2(void *)
+{
+  test_skip(0, access("/usr/bin/gdb", X_OK ));
+  test_skip(0, access("/usr/bin/true", X_OK ));
+
+  Application true_app("/usr/bin/true");
+  true_app.use_gdb(true);
+
+  ASSERT_EQ(Application::SUCCESS, true_app.run());
+  ASSERT_EQ(Application::SUCCESS, true_app.join());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t application_gdb_true_BINARY(void *)
+{
+  test_skip(0, access("/usr/bin/gdb", X_OK ));
+  test_skip(0, access("/usr/bin/true", X_OK ));
+
+  Application true_app("/usr/bin/true");
+  true_app.use_gdb(true);
+
+  const char *args[]= { "--fubar", 0 };
+  ASSERT_EQ(Application::SUCCESS, true_app.run(args));
+  ASSERT_EQ(Application::SUCCESS, true_app.join());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t application_true_fubar_BINARY(void *)
+{
+  test_skip(0, access("/usr/bin/true", X_OK ));
+  Application true_app("/usr/bin/true");
+
+  const char *args[]= { "--fubar", 0 };
+  ASSERT_EQ(Application::SUCCESS, true_app.run(args));
+  ASSERT_EQ(Application::SUCCESS, true_app.join());
+  test_zero(true_app.stdout_result().size());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t application_doesnotexist_BINARY(void *)
+{
+
+  test_skip_valgrind();
+  Application true_app("doesnotexist");
+  true_app.will_fail();
+
+  const char *args[]= { "--fubar", 0 };
+#if defined(__APPLE__) && __APPLE__
+  ASSERT_EQ(Application::INVALID_POSIX_SPAWN, true_app.run(args));
+#elif defined(__FreeBSD__) && __FreeBSD__
+  ASSERT_EQ(Application::INVALID_POSIX_SPAWN, true_app.run(args));
+#else
+  Application::error_t rc = true_app.run(args);
+  if (Application::SUCCESS == rc) {
+    ASSERT_EQ(Application::INVALID_POSIX_SPAWN, true_app.join());
+  } else {
+    ASSERT_EQ(Application::INVALID_POSIX_SPAWN, rc);
+  }
+#endif
+
+  test_zero(true_app.stdout_result().size());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t GET_TEST(void *)
+{
+  libtest::http::GET get("http://foo.example.com/");
+
+  ASSERT_EQ(false, get.execute());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t POST_TEST(void *)
+{
+  libtest::vchar_t body;
+  libtest::http::POST post("http://foo.example.com/", body);
+
+  ASSERT_EQ(false, post.execute());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t TRACE_TEST(void *)
+{
+  libtest::vchar_t body;
+  libtest::http::TRACE trace("http://foo.example.com/", body);
+
+  ASSERT_EQ(false, trace.execute());
+
+  return TEST_SUCCESS;
+}
+
+
+static test_return_t vchar_t_TEST(void *)
+{
+  libtest::vchar_t response;
+  libtest::make_vector(response, test_literal_param("fubar\n"));
+  ASSERT_EQ(response, response);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t vchar_t_make_append_TEST(void *)
+{
+  libtest::vchar_t hostname;
+  libtest::vchar::make(hostname, 23);
+  libtest::vchar::append(hostname, ".com");
+  ASSERT_EQ(28, hostname.size());
+  ASSERT_EQ(0, hostname[27]);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t vchar_t_compare_neg_TEST(void *)
+{
+  libtest::vchar_t response;
+  libtest::vchar_t response2;
+  libtest::make_vector(response, test_literal_param("fubar\n"));
+  libtest::make_vector(response2, test_literal_param(__func__));
+  test_true(response != response2);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t application_echo_fubar_BINARY(void *)
+{
+  if (0)
+  {
+    test_skip(0, access("/bin/echo", X_OK ));
+    Application true_app("/bin/echo");
+
+    const char *args[]= { "fubar", 0 };
+    ASSERT_EQ(Application::SUCCESS, true_app.run(args));
+
+    while (true_app.slurp() == false) {} ;
+
+    libtest::vchar_t response;
+    make_vector(response, test_literal_param("fubar\n"));
+    ASSERT_EQ(response, true_app.stdout_result());
+  }
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t application_echo_fubar_BINARY2(void *)
+{
+  if (0)
+  {
+    test_skip(0, access("/bin/echo", X_OK ));
+    Application true_app("/bin/echo");
+
+    true_app.add_option("fubar");
+
+    ASSERT_EQ(Application::SUCCESS, true_app.run());
+    ASSERT_EQ(Application::SUCCESS, true_app.join());
+
+    libtest::vchar_t response;
+    make_vector(response, test_literal_param("fubar\n"));
+    ASSERT_EQ(response, true_app.stdout_result());
+  }
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t echo_fubar_BINARY(void *)
+{
+  const char *args[]= { "fubar", 0 };
+  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("/bin/echo", args));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t core_count_BINARY(void *)
+{
+  const char *args[]= { 0 };
+
+  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("libtest/core-count", args, true));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t wait_BINARY(void *)
+{
+  const char *args[]= { "--quiet", 0 };
+
+  ASSERT_EQ(EXIT_FAILURE, exec_cmdline("libtest/wait", args, true));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t wait_help_BINARY(void *)
+{
+  const char *args[]= { "--quiet", "--help", 0 };
+
+  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t wait_version_BINARY(void *)
+{
+  const char *args[]= { "--quiet", "--version", 0 };
+
+  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t wait_services_BINARY(void *)
+{
+  test_skip(0, access("/etc/services", R_OK ));
+
+  const char *args[]= { "--quiet", "/etc/services", 0 };
+
+  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t wait_services_BINARY2(void *)
+{
+  test_skip(0, access("/etc/services", R_OK ));
+
+  const char *args[]= { "/etc/services", 0 };
+
+  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("libtest/wait", args, true));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t wait_services_appliction_TEST(void *)
+{
+  test_skip(0, access("/etc/services", R_OK ));
+  test_skip(0, access("/usr/bin/gdb", X_OK ));
+  test_skip(0, access("libtest/wait", X_OK ));
+
+  libtest::Application wait_app("libtest/wait", true);
+  wait_app.use_gdb(true);
+
+  const char *args[]= { "/etc/services", 0 };
+  ASSERT_EQ(Application::SUCCESS, wait_app.run(args));
+  ASSERT_EQ(Application::SUCCESS, wait_app.join());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t gdb_wait_services_appliction_TEST(void *)
+{
+  test_skip(true, false);
+#if defined(__APPLE__) && __APPLE__
+  test_skip(0, __APPLE__);
+#endif
+
+  test_skip(0, access("/etc/services", R_OK ));
+  test_skip(0, access("/usr/bin/gdb", X_OK ));
+  test_skip(0, access("libtest/wait", X_OK ));
+
+  libtest::Application wait_app("libtest/wait", true);
+  wait_app.use_gdb(true);
+
+  const char *args[]= { "/etc/services", 0 };
+  ASSERT_EQ(Application::SUCCESS, wait_app.run(args));
+  ASSERT_EQ(Application::SUCCESS, wait_app.join());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t gdb_abort_services_appliction_TEST(void *)
+{
+  test_skip(0, access("/usr/bin/gdb", X_OK ));
+  test_skip(0, access("libtest/abort", X_OK ));
+  test_skip(true, false);
+
+#if defined(__APPLE__) && __APPLE__
+  test_skip(0, __APPLE__);
+#endif
+
+  libtest::Application abort_app("libtest/abort", true);
+  abort_app.use_gdb(true);
+
+  ASSERT_EQ(Application::SUCCESS, abort_app.run());
+  ASSERT_EQ(Application::SUCCESS, abort_app.join());
+
+  std::string gdb_filename= abort_app.gdb_filename();
+  test_skip(0, access(gdb_filename.c_str(), R_OK ));
+  const char *args[]= { "SIGABRT", gdb_filename.c_str(), 0 };
+  ASSERT_EQ(EXIT_SUCCESS, exec_cmdline("grep", args));
+
+  // Sanity test
+  args[0]= "THIS_WILL_NOT_BE_FOUND";
+  ASSERT_EQ(EXIT_FAILURE, exec_cmdline("grep", args));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t get_free_port_TEST(void *)
+{
+  in_port_t ret_port;
+  test_true((ret_port= get_free_port()));
+  test_true(get_free_port() != default_port());
+  test_true(get_free_port() != get_free_port());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t fatal_TEST(void *)
+{
+  ASSERT_EQ(fatal_calls++, fatal::disabled_counter());
+  throw libtest::fatal(LIBYATL_DEFAULT_PARAM, "Testing va_args based fatal(): %d", 10); 
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t number_of_cpus_TEST(void *)
+{
+  test_true(number_of_cpus() >= 1);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t check_dns_TEST(void *)
+{
+  test_warn(libtest::check_dns(), "Broken DNS server/no DNS server found");
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t Timer_TEST(void *)
+{
+  int64_t minutes= random() % 50;
+  minutes++;
+
+  Timer check;
+
+  check.reset();
+  check.offset(minutes, 2, 200);
+
+  ASSERT_EQ(check.minutes(), minutes);
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t lookup_true_TEST(void *)
+{
+  test_warn(libtest::lookup("exist.gearman.info"), "dns is not currently working");
+  return TEST_SUCCESS;
+}
+
+static test_return_t lookup_false_TEST(void *)
+{
+  SKIP_IF_(libtest::lookup("does_not_exist.gearman.info"),
+           "Broken DNS server detected");
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t create_tmpfile_TEST(void *)
+{
+  test_skip(0, access("/usr/bin/touch", X_OK ));
+  std::string tmp= create_tmpfile(__func__);
+  ASSERT_EQ(-1, access(tmp.c_str(), R_OK));
+  ASSERT_EQ(-1, access(tmp.c_str(), F_OK));
+
+  Application touch_app("/usr/bin/touch");
+  const char *args[]= { tmp.c_str(), 0 };
+  ASSERT_EQ(Application::SUCCESS, touch_app.run(args));
+  ASSERT_EQ(Application::SUCCESS, touch_app.join());
+
+  ASSERT_EQ(0, access(tmp.c_str(), R_OK));
+  ASSERT_EQ(0, unlink(tmp.c_str()));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t fatal_message_TEST(void *)
+{
+  ASSERT_EQ(fatal_calls++, fatal::disabled_counter());
+  FATAL("Fatal test");
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t default_port_TEST(void *)
+{
+  in_port_t ret_port= default_port();
+  ASSERT_EQ(ret_port, libtest::default_port());
+  ASSERT_EQ(ret_port, libtest::default_port());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t check_for_VALGRIND(void *)
+{
+  test_skip_valgrind();
+  return TEST_SUCCESS;
+}
+
+static test_return_t check_for_gearman(void *)
+{
+  test_skip(true, HAVE_LIBGEARMAN);
+  test_skip(true, has_gearmand());
+#if defined(HAVE_GEARMAND_BINARY) && HAVE_GEARMAND_BINARY
+  if (GEARMAND_BINARY)
+  {
+    if (strcmp(GEARMAND_BINARY, "./gearmand/gearmand"))
+    {
+      test_zero(access(GEARMAND_BINARY, X_OK ));
+    }
+  }
+  else
+  {
+    return TEST_SKIPPED;
+  }
+#endif
+
+  testing_service= "gearmand";
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t check_for_drizzle(void *)
+{
+  test_skip(true, has_drizzled());
+
+  testing_service= "drizzled";
+
+  return TEST_SUCCESS;
+}
+
+
+test_st drizzled_tests[] ={
+  {"drizzled startup-shutdown", 0, drizzled_cycle_test },
+  {0, 0, 0}
+};
+
+test_st gearmand_tests[] ={
+#if 0
+  {"pause", 0, pause_test },
+#endif
+  {"gearmand startup-shutdown", 0, gearmand_cycle_test },
+  {"_compare(gearman_return_t)", 0, _compare_gearman_return_t_test },
+  {"server_startup(fail)", 0, server_startup_fail_TEST },
+  {0, 0, 0}
+};
+
+static test_return_t clear_servers(void* object)
+{
+  server_startup_st *servers= (server_startup_st*)object;
+  test_true(servers);
+  servers->clear();
+
+  testing_service.clear();
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t check_for_memcached(void* object)
+{
+  test_skip(true, has_memcached());
+
+  server_startup_st *servers= (server_startup_st*)object;
+  test_true(servers);
+  servers->clear();
+
+  testing_service= "memcached";
+
+  return TEST_SUCCESS;
+}
+
+test_st memcached_TESTS[] ={
+  {"memcached startup-shutdown", 0, server_startup_TEST },
+  {"memcached(socket file) startup-shutdown", 0, socket_server_startup_TEST },
+  {"_compare(memcached_return_t)", 0, _compare_memcached_return_t_test },
+  {"server_startup(fail)", 0, server_startup_fail_TEST },
+  {0, 0, 0}
+};
+
+test_st test_skip_TESTS[] ={
+  {"true, true", 0, test_skip_true_TEST },
+  {"true, false", 0, test_skip_false_TEST },
+  {0, 0, 0}
+};
+
+test_st environment_tests[] ={
+  {"getenv()", 0, getenv_TEST },
+  {"LIBTOOL_COMMAND", 0, LIBTOOL_COMMAND_test },
+  {"VALGRIND_COMMAND", 0, VALGRIND_COMMAND_test },
+  {"HELGRIND_COMMAND", 0, HELGRIND_COMMAND_test },
+  {"GDB_COMMAND", 0, GDB_COMMAND_test },
+  {0, 0, 0}
+};
+
+test_st tests_log[] ={
+  {"TEST_SUCCESS", false, test_success_test },
+  {"TEST_FAILURE", false, test_failure_test },
+  {"TEST_SUCCESS == 0", false, test_success_equals_one_test },
+  {"SUCCESS", false, test_throw_success_TEST },
+  {"libtest::__skipped", false, test_throw_skip_TEST },
+  {"SKIP_IF", false, test_throw_skip_macro_TEST },
+  {"SKIP_UNLESS", false, test_throw_skip_unless_macro_TEST },
+  {"FAIL", false, test_throw_fail_TEST },
+  {"ASSERT_FALSE_", false, ASSERT_FALSE__TEST },
+  {"ASSERT_FALSE", false, ASSERT_FALSE_TEST },
+  {"ASSERT_NEQ", false, ASSERT_NEQ_TEST },
+  {"ASSERT_NEQ FAIL", false, ASSERT_NEQ_FAIL_TEST },
+  {0, 0, 0}
+};
+
+test_st local_log[] ={
+  {"test_is_local()", 0, local_test },
+  {"test_is_local(NOT)", 0, local_not_test },
+  {0, 0, 0}
+};
+
+test_st directories_tests[] ={
+  {"var exists", 0, var_exists_test },
+  {"var/tmp exists", 0, var_tmp_exists_test },
+  {"var/run exists", 0, var_run_exists_test },
+  {"var/log exists", 0, var_log_exists_test },
+  {"var/drizzle exists", 0, var_drizzle_exists_test },
+  {"var/tmp", 0, var_tmp_test },
+  {"var/run", 0, var_run_test },
+  {"var/log", 0, var_log_test },
+  {"var/drizzle", 0, var_drizzle_test },
+  {"var/tmp rm", 0, var_tmp_rm_test },
+  {"var/run rm", 0, var_run_rm_test },
+  {"var/log rm", 0, var_log_rm_test },
+  {"var/drizzle rm", 0, var_drizzle_rm_test },
+  {0, 0, 0}
+};
+
+test_st comparison_tests[] ={
+  {"_compare(test_return_t)", 0, _compare_test_return_t_test },
+  {0, 0, 0}
+};
+
+test_st cmdline_tests[] ={
+  {"echo fubar", 0, echo_fubar_BINARY },
+  {"core-count", 0, core_count_BINARY },
+  {"wait --quiet", 0, wait_BINARY },
+  {"wait --quiet --help", 0, wait_help_BINARY },
+  {"wait --quiet --version", 0, wait_version_BINARY },
+  {"wait --quiet /etc/services", 0, wait_services_BINARY },
+  {"wait /etc/services", 0, wait_services_BINARY2 },
+  {"wait /etc/services", 0, wait_services_appliction_TEST },
+  {"gdb wait /etc/services", 0, gdb_wait_services_appliction_TEST },
+  {"gdb abort", 0, gdb_abort_services_appliction_TEST },
+  {0, 0, 0}
+};
+
+test_st get_free_port_TESTS[] ={
+  {"get_free_port()", 0, get_free_port_TEST },
+  {"default_port()", 0, default_port_TEST },
+  {0, 0, 0}
+};
+
+test_st fatal_message_TESTS[] ={
+  {"libtest::fatal", 0, fatal_TEST },
+  {"fatal_message()", 0, fatal_message_TEST },
+  {0, 0, 0}
+};
+
+test_st number_of_cpus_TESTS[] ={
+  {"libtest::number_of_cpus()", 0, number_of_cpus_TEST },
+  {0, 0, 0}
+};
+
+test_st create_tmpfile_TESTS[] ={
+  {"libtest::create_tmpfile()", 0, create_tmpfile_TEST },
+  {0, 0, 0}
+};
+
+test_st timer_TESTS[] ={
+  {"libtest::Timer", 0, Timer_TEST },
+  {0, 0, 0}
+};
+
+test_st dns_TESTS[] ={
+  {"libtest::lookup(true)", 0, lookup_true_TEST },
+  {"libtest::lookup(false)", 0, lookup_false_TEST },
+  {"libtest::check_dns()", 0, check_dns_TEST },
+  {0, 0, 0}
+};
+
+test_st application_tests[] ={
+  {"vchar_t", 0, vchar_t_TEST },
+  {"vchar_t make() append()", 0, vchar_t_make_append_TEST },
+  {"vchar_t compare()", 0, vchar_t_compare_neg_TEST },
+  {"true", 0, application_true_BINARY },
+  {"gbd true --fubar", 0, application_gdb_true_BINARY },
+  {"gbd true", 0, application_gdb_true_BINARY2 },
+  {"true --fubar", 0, application_true_fubar_BINARY },
+  {"doesnotexist --fubar", 0, application_doesnotexist_BINARY },
+  {"echo fubar", 0, application_echo_fubar_BINARY },
+  {"echo fubar (as option)", 0, application_echo_fubar_BINARY2 },
+  {0, 0, 0}
+};
+
+static test_return_t check_for_curl(void *)
+{
+  test_skip_valgrind();
+  test_skip(true, HAVE_LIBCURL);
+  return TEST_SUCCESS;
+}
+
+static test_return_t disable_fatal_exception(void *)
+{
+  fatal_calls= 0;
+  fatal::disable();
+  return TEST_SUCCESS;
+}
+
+static test_return_t enable_fatal_exception(void *)
+{
+  fatal::enable();
+  return TEST_SUCCESS;
+}
+
+test_st http_tests[] ={
+  {"GET", 0, GET_TEST },
+  {"POST", 0, POST_TEST },
+  {"TRACE", 0, TRACE_TEST },
+  {0, 0, 0}
+};
+
+collection_st collection[] ={
+  {"environment", 0, 0, environment_tests},
+  {"return values", 0, 0, tests_log},
+  {"test_skip()", 0, 0, test_skip_TESTS },
+  {"local", 0, 0, local_log},
+  {"directories", 0, 0, directories_tests},
+  {"comparison", 0, 0, comparison_tests},
+  {"gearmand", check_for_gearman, clear_servers, gearmand_tests},
+  {"memcached", check_for_memcached, clear_servers, memcached_TESTS },
+  {"drizzled", check_for_drizzle, clear_servers, drizzled_tests},
+  {"cmdline", 0, 0, cmdline_tests},
+  {"application", 0, 0, application_tests},
+  {"http", check_for_curl, 0, http_tests},
+  {"http", check_for_curl, 0, http_tests},
+  {"get_free_port()", 0, 0, get_free_port_TESTS },
+  {"fatal", disable_fatal_exception, enable_fatal_exception, fatal_message_TESTS },
+  {"number_of_cpus()", 0, 0, number_of_cpus_TESTS },
+  {"create_tmpfile()", 0, 0, create_tmpfile_TESTS },
+  {"dns", check_for_VALGRIND, 0, dns_TESTS },
+  {"libtest::Timer", 0, 0, timer_TESTS },
+  {0, 0, 0, 0}
+};
+
+static void *world_create(server_startup_st& servers, test_return_t&)
+{
+  return &servers;
+}
+
+void get_world(libtest::Framework *world)
+{
+  world->collections(collection);
+  world->create(world_create);
+}
diff --git a/src/libtest/valgrind.h b/src/libtest/valgrind.h
new file mode 100644 (file)
index 0000000..effeddc
--- /dev/null
@@ -0,0 +1,55 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012-2013 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+static inline bool valgrind_is_caller(void)
+{
+  if (getenv("LOG_COMPILER")  && strstr(getenv("LOG_COMPILER"), "valgrind"))
+  {
+    if (strstr(getenv("LOG_COMPILER"), "--tool") == NULL)
+    {
+      return true;
+    }
+
+    if (strstr(getenv("LOG_COMPILER"), "--tool=memcheck"))
+    {
+      return true;
+    }
+  }
+
+  return false;
+}
diff --git a/src/libtest/vchar.cc b/src/libtest/vchar.cc
new file mode 100644 (file)
index 0000000..a4bddfd
--- /dev/null
@@ -0,0 +1,169 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+#include <libtest/common.h>
+
+/* Use this for string generation */
+static const char ALPHANUMERICS[]=
+  "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
+
+#define ALPHANUMERICS_SIZE (sizeof(ALPHANUMERICS)-1)
+
+static size_t get_alpha_num(void)
+{
+  return (size_t)random() % ALPHANUMERICS_SIZE;
+}
+
+namespace libtest {
+
+int random_alpha_num(void)
+{
+  return ALPHANUMERICS[get_alpha_num()];
+}
+
+static std::string printer(const char *str, size_t length)
+{
+  std::ostringstream buf;
+  for (size_t x= 0; x < length; x++)
+  {
+    if (isprint(str[x]))
+    {
+      buf << str[x];
+    }
+    else
+    {
+      buf << "(" << int(str[x]) << ")";
+    }
+  }
+
+  return buf.str();
+}
+
+namespace vchar {
+
+int compare(libtest::vchar_t& arg, const char *str, size_t length)
+{
+  if (arg.size() == length and (memcmp(&arg[0], str, length) == 0))
+  {
+    return 0;
+  }
+  else if (arg.size() > length)
+  {
+    return 1;
+  }
+
+  return -1;
+}
+
+void make(libtest::vchar_t& arg)
+{
+  size_t length= rand() % 1024;
+  make(arg, length);
+}
+
+void make(libtest::vchar_t& arg, size_t length)
+{
+  arg.reserve(length);
+  for (uint32_t x= 0; x < length; ++x)
+  {
+    arg.push_back(ALPHANUMERICS[get_alpha_num()]);
+  }
+}
+
+void chomp(libtest::vchar_t& arg)
+{
+  while(arg.size())
+  {
+    if (arg.back() == 0)
+    {
+      arg.pop_back();
+    }
+    else
+    {
+      break;
+    }
+  }
+}
+
+void append(libtest::vchar_ptr_t& arg, const char* ptr)
+{
+  if (ptr)
+  {
+    char* new_ptr= strdup(ptr);
+    if (new_ptr == NULL)
+    {
+      FATAL("UNABLE to allocate %s(%p)", ptr, ptr);
+    }
+
+    arg.push_back(new_ptr);
+  }
+}
+
+void append(libtest::vchar_t& arg, const char* ptr)
+{
+  if (ptr)
+  {
+    size_t length= strlen(ptr);
+    ASSERT_TRUE(length);
+    arg.reserve(length);
+    do
+    {
+      arg.push_back(*ptr);
+      ++ptr;
+    } while (*ptr);
+
+    arg.push_back(0);
+  }
+}
+
+} // namespace vchar
+
+void make_vector(libtest::vchar_t& arg, const char *str, size_t length)
+{
+  arg.resize(length);
+  memcpy(&arg[0], str, length);
+}
+
+std::ostream& operator<<(std::ostream& output, const libtest::vchar_t& arg)
+{
+  std::string tmp= libtest::printer(arg.data(), arg.size());
+  output << tmp <<  "[" << arg.size() << "]";
+
+  return output;
+}
+
+} // namespace libtest
diff --git a/src/libtest/vchar.hpp b/src/libtest/vchar.hpp
new file mode 100644 (file)
index 0000000..541bb92
--- /dev/null
@@ -0,0 +1,71 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <cstring>
+#include <iostream>
+#include <ostream>
+#include <sstream>
+#include <vector>
+
+namespace libtest {
+
+int random_alpha_num(void);
+
+typedef std::vector<char*> vchar_ptr_t;
+typedef std::vector<char> vchar_t;
+
+void make_vector(libtest::vchar_t& arg, const char *str, size_t length);
+
+namespace vchar {
+
+int compare(libtest::vchar_t& arg, const char *str, size_t length);
+void chomp(libtest::vchar_t& arg);
+void make(libtest::vchar_t& arg);
+void make(libtest::vchar_t& arg, size_t length);
+void append(libtest::vchar_ptr_t& arg, const char*);
+void append(libtest::vchar_t& arg, const char*);
+
+} // namespace vchar
+
+#define vchar_param(__arg) (&__arg[0]), (__arg.size())
+#define vchar_printf(__arg) int(__arg.size()), (&__arg[0])
+
+std::ostream& operator<<(std::ostream& output, const libtest::vchar_t& arg);
+
+} // namespace libtest
+
diff --git a/src/libtest/version.h.in b/src/libtest/version.h.in
new file mode 100644 (file)
index 0000000..1bec2a8
--- /dev/null
@@ -0,0 +1,42 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Data Differential YATL (i.e. libtest) library
+ *
+ *  Copyright (C) 2011-2012 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#define LIBTEST_VERSION @LIBTEST_VERSION@
+#define LIBTEST_VERSION_STRING "@LIBTEST_VERSION@"
diff --git a/src/libtest/visibility.h b/src/libtest/visibility.h
new file mode 100644 (file)
index 0000000..72a15c1
--- /dev/null
@@ -0,0 +1,77 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#if defined(BUILDING_LIBTEST)
+# if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
+#  define LIBTEST_API __attribute__ ((visibility("default")))
+#  define LIBTEST_LOCAL  __attribute__ ((visibility("default")))
+# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+#  define LIBTEST_API __global
+#  define LIBTEST_LOCAL __global
+# elif defined(_MSC_VER)
+#  define LIBTEST_API extern __declspec(dllexport) 
+#  define LIBTEST_LOCAL extern __declspec(dllexport)
+# else
+#  define LIBTEST_API
+#  define LIBTEST_LOCAL
+# endif
+#else
+# if defined(BUILDING_LIBTEST)
+#  if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY
+#   define LIBTEST_API __attribute__ ((visibility("default")))
+#   define LIBTEST_LOCAL  __attribute__ ((visibility("hidden")))
+#  elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+#   define LIBTEST_API __global
+#   define LIBTEST_LOCAL __hidden
+#  elif defined(_MSC_VER)
+#   define LIBTEST_API extern __declspec(dllexport) 
+#   define LIBTEST_LOCAL
+#  else
+#   define LIBTEST_API
+#   define LIBTEST_LOCAL
+#  endif /* defined(HAVE_VISIBILITY) */
+# else  /* defined(BUILDING_LIBTEST) */
+#  if defined(_MSC_VER)
+#   define LIBTEST_API extern __declspec(dllimport) 
+#   define LIBTEST_LOCAL
+#  else
+#   define LIBTEST_API
+#   define LIBTEST_LOCAL
+#  endif /* defined(_MSC_VER) */
+# endif /* defined(BUILDING_LIBTEST) */
+#endif /* defined(BUILDING_LIBTESTINTERNAL) */
diff --git a/src/libtest/wait.cc b/src/libtest/wait.cc
new file mode 100644 (file)
index 0000000..d1292e1
--- /dev/null
@@ -0,0 +1,194 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "libtest/yatlcon.h"
+
+#include <cstdlib>
+#include <fcntl.h>
+#include <getopt.h>
+#include <iostream>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <libtest/wait.h>
+
+static void version_command(const char *command_name, int major_version, int minor_version)
+{
+  std::cout << command_name << " " << major_version << "." << minor_version << std::endl;
+}
+
+static void help_command(const char *command_name,
+                         int major_version, int minor_version,
+                         const struct option *long_options)
+{
+  std::cout << command_name << " " << major_version << "." << minor_version << std::endl;
+  std::cout << "Current options. A '=' means the option takes a value." << std::endl << std::endl;
+
+  for (uint32_t x= 0; long_options[x].name; x++)
+  {
+    std::cout << "\t --" << long_options[x].name << char(long_options[x].has_arg ? '=' : ' ') << std::endl;
+  }
+
+  std::cout << std::endl;
+}
+
+static void close_stdio(void)
+{
+  int fd;
+  if ((fd = open("/dev/null", O_RDWR, 0)) < 0)
+  {
+    return;
+  }
+  else
+  {
+    if (dup2(fd, STDIN_FILENO) < 0)
+    {
+      return;
+    }
+
+    if (dup2(fd, STDOUT_FILENO) < 0)
+    {
+      return;
+    }
+
+    if (dup2(fd, STDERR_FILENO) < 0)
+    {
+      return;
+    }
+
+    if (fd > STDERR_FILENO)
+    {
+      close(fd);
+    }
+  }
+}
+
+enum {
+  OPT_HELP,
+  OPT_QUIET,
+  OPT_VERSION
+};
+
+static void options_parse(int argc, char *argv[])
+{
+  static struct option long_options[]=
+  {
+    { "version", no_argument, NULL, OPT_VERSION},
+    { "help", no_argument, NULL, OPT_HELP},
+    { "quiet", no_argument, NULL, OPT_QUIET},
+    {0, 0, 0, 0},
+  };
+
+  bool opt_version= false;
+  bool opt_help= false;
+  bool opt_quiet= false;
+  int option_index= 0;
+
+  while (1)
+  {
+    int option_rv= getopt_long(argc, argv, "", long_options, &option_index);
+    if (option_rv == -1) 
+    {
+      break;
+    }
+
+    switch (option_rv)
+    {
+    case OPT_HELP: /* --help or -h */
+      opt_help= true;
+      break;
+
+    case OPT_VERSION: /* --version or -v */
+      opt_version= true;
+      break;
+
+    case OPT_QUIET:
+      opt_quiet= true;
+      break;
+
+    case '?':
+      /* getopt_long already printed an error message. */
+      exit(EXIT_FAILURE);
+
+    default:
+      help_command(argv[0], 1, 0, long_options);
+      exit(EXIT_FAILURE);
+    }
+  }
+
+  if (opt_quiet)
+  {
+    close_stdio();
+  }
+
+  if (opt_version)
+  {
+    version_command(argv[0], 1, 0);
+    exit(EXIT_SUCCESS);
+  }
+
+  if (opt_help)
+  {
+    help_command(argv[0], 1, 0, long_options);
+    exit(EXIT_SUCCESS);
+  }
+}
+
+int main(int argc, char *argv[])
+{
+  if (argc == 1)
+  {
+    return EXIT_FAILURE;
+  }
+
+  options_parse(argc, argv);
+
+  int ret= EXIT_FAILURE;
+  while (optind < argc)
+  {
+    libtest::Wait wait(argv[optind++]);
+
+    if (wait.successful() == false)
+    {
+      return EXIT_FAILURE;
+    }
+
+    ret= EXIT_SUCCESS;
+  }
+
+  return ret;
+}
diff --git a/src/libtest/wait.h b/src/libtest/wait.h
new file mode 100644 (file)
index 0000000..e5cdcb3
--- /dev/null
@@ -0,0 +1,114 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <unistd.h>
+#include <string>
+#include <signal.h>
+
+#include <libtest/dream.h>
+
+namespace libtest {
+
+class Wait 
+{
+public:
+
+  Wait(const std::string &filename, uint32_t timeout= 6) :
+    _successful(false)
+  {
+    uint32_t waited;
+    uint32_t this_wait;
+    uint32_t retry;
+
+    if (filename.empty())
+    {
+      _successful= false;
+      return;
+    }
+
+    for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
+    {
+      if (access(filename.c_str(), R_OK) == 0)
+      {
+        _successful= true;
+        break;
+      }
+      else if (waited >= timeout)
+      {
+        break;
+      }
+
+      this_wait= retry * retry / 3 + 1;
+      libtest::dream(0, this_wait * 10000000);
+    }
+  }
+
+  Wait(const pid_t &_pid_arg, uint32_t timeout= 6) :
+    _successful(false)
+  {
+    uint32_t waited;
+    uint32_t this_wait;
+    uint32_t retry;
+
+    for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
+    {
+      if (kill(_pid_arg, 0) == 0)
+      {
+        _successful= true;
+        break;
+      }
+      else if (waited >= timeout)
+      {
+        break;
+      }
+
+      this_wait= retry * retry / 3 + 1;
+      libtest::dream(0, this_wait * 10000000);
+    }
+  }
+
+  bool successful() const
+  {
+    return _successful;
+  }
+
+private:
+  bool _successful;
+};
+
+} // namespace libtest
diff --git a/src/libtest/yatl.h b/src/libtest/yatl.h
new file mode 100644 (file)
index 0000000..6da02a3
--- /dev/null
@@ -0,0 +1,43 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential YATL (i.e. libtest)  library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#ifndef YATL_FULL
+# define YATL_FULL 1
+#endif
+
+#include <libtest/test.hpp>
diff --git a/src/libtest/yatlcon.h.in b/src/libtest/yatlcon.h.in
new file mode 100644 (file)
index 0000000..e5adefb
--- /dev/null
@@ -0,0 +1,47 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Data Differential YATL (i.e. libtest) library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#pragma once
+
+#include "@AUTOHEADER_FILE@"
+
+#ifndef LIBTEST_TEMP
+# define LIBTEST_TEMP "/tmp"
+#endif
+
+#define HAVE_LIBMEMCACHED 1
diff --git a/src/mem_config.h.in b/src/mem_config.h.in
new file mode 100644 (file)
index 0000000..de2cdb7
--- /dev/null
@@ -0,0 +1,70 @@
+#pragma once
+
+#cmakedefine01 LIBMEMCACHED_WITH_SASL_SUPPORT
+
+#define LIBMEMCACHED_WITH_SASL_PWDB "@LIBMEMCACHED_WITH_SASL_PWDB@"
+#define LIBMEMCACHED_WITH_SASL_CONF "@LIBMEMCACHED_WITH_SASL_CONF@"
+
+#cmakedefine HAVE_C_STDATOMIC 1
+#cmakedefine HAVE_CXX_STDATOMIC 1
+
+#cmakedefine HAVE_ARPA_INET_H 1
+#cmakedefine HAVE_DLFCN_H 1
+#cmakedefine HAVE_DTRACE 1
+#cmakedefine HAVE_ERRNO_H 1
+#cmakedefine HAVE_EXECINFO_H 1
+#cmakedefine HAVE_FCNTL 1
+#cmakedefine HAVE_FCNTL_H 1
+#cmakedefine HAVE_FNV64_HASH 1
+#cmakedefine HAVE_GETLINE
+#cmakedefine HAVE_HSIEH_HASH 1
+#cmakedefine HAVE_HTONLL 1
+#cmakedefine HAVE_IN_PORT_T 1
+#cmakedefine HAVE_IO_H 1
+#cmakedefine HAVE_LIBEVENT 1
+#cmakedefine HAVE_LIBSASL 1
+#cmakedefine HAVE_LIBUUID 1
+#cmakedefine HAVE_LIMITS_H 1
+#cmakedefine HAVE_MSG_DONTWAIT 1
+#cmakedefine HAVE_MSG_MORE 1
+#cmakedefine HAVE_MSG_NOSIGNAL 1
+#cmakedefine HAVE_MURMUR_HASH 1
+#cmakedefine HAVE_NETDB_H 1
+#cmakedefine HAVE_POLL_H 1
+#cmakedefine HAVE_RCVTIMEO 1
+#cmakedefine HAVE_SASL_SASL_H 1
+#cmakedefine HAVE_SHARED_ENABLED 1
+#cmakedefine HAVE_SNDTIMEO 1
+#cmakedefine HAVE_STDDEF_H 1
+#cmakedefine HAVE_STDLIB_H 1
+#cmakedefine HAVE_STRERROR 1
+#cmakedefine HAVE_STRERROR_R 1
+#cmakedefine HAVE_STRINGS_H 1
+#cmakedefine HAVE_SYS_SOCKET_H 1
+#cmakedefine HAVE_SYS_TIME_H 1
+#cmakedefine HAVE_SYS_TYPES_H 1
+#cmakedefine HAVE_SYS_WAIT_H 1
+#cmakedefine HAVE_SYS_UN_H 1
+#cmakedefine HAVE_TIME_H 1
+#cmakedefine HAVE_UMEM_H 1
+#cmakedefine HAVE_UNISTD_H 1
+#cmakedefine HAVE_VISIBILITY 1
+#cmakedefine HAVE_WINSOCK2_H 1
+#cmakedefine HAVE_WS2TCPIP_H 1
+
+#cmakedefine HAVE_ABI____CXA_DEMANGLE 1
+#cmakedefine HAVE_GCC_ABI_DEMANGLE 1
+
+#cmakedefine HAVE_CINTTYPES 1
+#cmakedefine HAVE_CSTDINT 1
+#if defined(__cplusplus)
+# if defined HAVE_CINTTYPES
+#  include <cinttypes>
+# elif defined HAVE_CSTDINT
+#  include <cstdint>
+# endif
+#else
+#  include <inttypes.h>
+#endif
+
+#define HAVE_LIBMEMCACHED 1
diff --git a/src/util/daemon.cc b/src/util/daemon.cc
new file mode 100644 (file)
index 0000000..90e29ef
--- /dev/null
@@ -0,0 +1,194 @@
+/*    $Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $    */
+/*    $NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $    */
+/*-
+ * Copyright (c) 1990, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2010
+ *    Stewart Smith
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <mem_config.h>
+
+#if defined __SUNPRO_C || defined __DECC || defined __HP_cc
+# pragma ident "@(#)$Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $"
+# pragma ident "$NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $"
+#endif
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/select.h>
+
+#include <util/daemon.hpp>
+
+#include <iostream>
+
+namespace datadifferential {
+namespace util {
+
+pid_t parent_pid;
+
+extern "C"
+{
+
+static void sigusr1_handler(int sig)
+{
+  if (sig == SIGUSR1)
+  {
+    _exit(EXIT_SUCCESS);
+  }
+}
+
+}
+
+bool daemon_is_ready(bool close_io)
+{
+  if (kill(parent_pid, SIGUSR1) == -1)
+  {
+    perror("kill");
+    return false;
+  }
+
+  if (close_io == false)
+  {
+    return true;;
+  }
+
+  int fd;
+  if ((fd = open("/dev/null", O_RDWR, 0)) < 0)
+  {
+    perror("open");
+    return false;
+  }
+  else
+  {
+    if (dup2(fd, STDIN_FILENO) < 0)
+    {
+      perror("dup2 stdin");
+      return false;
+    }
+
+    if (dup2(fd, STDOUT_FILENO) < 0)
+    {
+      perror("dup2 stdout");
+      return false;
+    }
+
+    if (dup2(fd, STDERR_FILENO) < 0)
+    {
+      perror("dup2 stderr");
+      return false;
+    }
+
+    if (fd > STDERR_FILENO)
+    {
+      if (close(fd) < 0)
+      {
+        perror("close");
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+bool daemonize(bool is_chdir, bool wait_sigusr1)
+{
+  struct sigaction new_action;
+
+  new_action.sa_handler= sigusr1_handler;
+  sigemptyset(&new_action.sa_mask);
+  new_action.sa_flags= 0;
+  sigaction(SIGUSR1, &new_action, NULL);
+
+  parent_pid= getpid();
+
+  pid_t child= fork();
+
+  switch (child)
+  {
+  case -1:
+    return false;
+
+  case 0:
+    break;
+
+  default:
+    if (wait_sigusr1)
+    {
+      /* parent */
+      int exit_code= EXIT_FAILURE;
+      int status;
+      while (waitpid(child, &status, 0) != child)
+      { }
+
+      if (WIFEXITED(status))
+      {
+        exit_code= WEXITSTATUS(status);
+      }
+      if (WIFSIGNALED(status))
+      {
+        exit_code= EXIT_FAILURE;
+      }
+      _exit(exit_code);
+    }
+    else
+    {
+      _exit(EXIT_SUCCESS);
+    }
+  }
+
+  /* child */
+  if (setsid() == -1)
+  {
+    perror("setsid");
+    return false;
+  }
+
+  if (is_chdir)
+  {
+    if (chdir("/") < 0)
+    {
+      perror("chdir");
+      return false;
+    }
+  }
+
+  return true; 
+}
+
+} /* namespace util */
+} /* namespace datadifferential */
diff --git a/src/util/daemon.hpp b/src/util/daemon.hpp
new file mode 100644 (file)
index 0000000..170f52d
--- /dev/null
@@ -0,0 +1,43 @@
+/*    $Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $    */
+/*    $NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $    */
+/*-
+ * Copyright (c) 1990, 1993
+ *    The Regents of the University of California.  All rights reserved.
+ * Copyright (c) 2010
+ *    Stewart Smith
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+namespace datadifferential {
+namespace util {
+
+bool daemon_is_ready(bool close_io);
+bool daemonize(bool is_chdir= true, bool wait_sigusr1= true);
+
+} /* namespace util */
+} /* namespace datadifferential */
diff --git a/src/util/instance.cc b/src/util/instance.cc
new file mode 100644 (file)
index 0000000..8f5d173
--- /dev/null
@@ -0,0 +1,338 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  DataDifferential Utility Library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include "mem_config.h"
+
+#include "util/instance.hpp"
+
+#include <cstdio>
+#include <iostream>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <poll.h>
+#include <sstream>
+#include <sys/socket.h>
+#include <sys/types.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#ifndef INVALID_SOCKET
+# define INVALID_SOCKET -1
+#endif
+
+#ifndef SOCKET_ERROR
+# define SOCKET_ERROR -1
+#endif
+
+#ifndef get_socket_errno
+# define get_socket_errno() errno
+#endif
+
+#ifndef closesocket
+# define closesocket(a) close(a)
+#endif
+
+
+namespace datadifferential {
+namespace util {
+
+Instance::Instance(const std::string& hostname_arg, const std::string& service_arg) :
+  _host(hostname_arg),
+  _service(service_arg),
+  _sockfd(INVALID_SOCKET),
+  state(NOT_WRITING),
+  _addrinfo(0),
+  _addrinfo_next(0),
+  _finish_fn(NULL),
+  _operations()
+  {
+  }
+
+Instance::Instance(const std::string& hostname_arg, const in_port_t port_arg) :
+  _host(hostname_arg),
+  _sockfd(INVALID_SOCKET),
+  state(NOT_WRITING),
+  _addrinfo(0),
+  _addrinfo_next(0),
+  _finish_fn(NULL),
+  _operations()
+  {
+    char tmp[BUFSIZ];
+    snprintf(tmp, sizeof(tmp), "%u", static_cast<unsigned int>(port_arg));
+    _service= tmp;
+  }
+
+Instance::~Instance()
+{
+  close_socket();
+  free_addrinfo();
+  for (Operation::vector::iterator iter= _operations.begin(); iter != _operations.end(); ++iter)
+  {
+    delete *iter;
+  }
+  _operations.clear();
+
+  delete _finish_fn;
+}
+
+bool Instance::run()
+{
+  while (not _operations.empty())
+  {
+    Operation::vector::value_type operation= _operations.back();
+
+    switch (state)
+    {
+    case NOT_WRITING:
+      {
+        free_addrinfo();
+
+        struct addrinfo ai;
+        memset(&ai, 0, sizeof(struct addrinfo));
+        ai.ai_socktype= SOCK_STREAM;
+        ai.ai_protocol= IPPROTO_TCP;
+
+        int ret= getaddrinfo(_host.c_str(), _service.c_str(), &ai, &_addrinfo);
+        if (ret)
+        {
+          std::stringstream message;
+          message << "Failed to connect on " << _host.c_str() << ":" << _service.c_str() << " with "  << gai_strerror(ret);
+          _last_error= message.str();
+          return false;
+        }
+      }
+      _addrinfo_next= _addrinfo;
+      state= CONNECT;
+      break;
+
+    case NEXT_CONNECT_ADDRINFO:
+      if (_addrinfo_next->ai_next == NULL)
+      {
+        std::stringstream message;
+        message << "Error connecting to " << _host.c_str() << "." << std::endl;
+        _last_error= message.str();
+        return false;
+      }
+      _addrinfo_next= _addrinfo_next->ai_next;
+      /* fall through */
+
+    case CONNECT:
+      close_socket();
+
+      _sockfd= socket(_addrinfo_next->ai_family,
+                      _addrinfo_next->ai_socktype,
+                      _addrinfo_next->ai_protocol);
+      if (_sockfd == INVALID_SOCKET)
+      {
+        perror("socket");
+        continue;
+      }
+
+      if (connect(_sockfd, _addrinfo_next->ai_addr, _addrinfo_next->ai_addrlen) < 0)
+      {
+        switch(errno)
+        {
+        case EAGAIN:
+        case EINTR:
+          state= CONNECT;
+          break;
+
+        case EINPROGRESS:
+          state= CONNECTING;
+          break;
+
+        case ECONNREFUSED:
+        case ENETUNREACH:
+        case ETIMEDOUT:
+        default:
+          state= NEXT_CONNECT_ADDRINFO;
+          break;
+        }
+      }
+      else
+      {
+        state= CONNECTING;
+      }
+      break;
+
+    case CONNECTING:
+      // Add logic for poll() for nonblocking.
+      state= CONNECTED;
+      break;
+
+    case CONNECTED:
+    case WRITING:
+      {
+        size_t packet_length= operation->size();
+        const char *packet= operation->ptr();
+
+        while(packet_length)
+        {
+          ssize_t write_size= send(_sockfd, packet, packet_length, 0);
+
+          if (write_size < 0)
+          {
+            switch(errno)
+            {
+            default:
+              std::cerr << "Failed dureng send(" << strerror(errno) << ")" << std::endl;
+              break;
+            }
+          }
+
+          packet_length-= static_cast<size_t>(write_size);
+          packet+= static_cast<size_t>(write_size);
+        }
+      }
+      state= READING;
+      break;
+
+    case READING:
+      if (operation->has_response())
+      {
+        ssize_t read_length;
+
+        do
+        {
+          char buffer[BUFSIZ];
+          read_length= ::recv(_sockfd, buffer, sizeof(buffer), 0);
+
+          if (read_length < 0)
+          {
+            switch(errno)
+            {
+            default:
+              _last_error.clear();
+              _last_error+= "Error occured while reading data from ";
+              _last_error+= _host;
+              return false;
+            }
+          }
+          else if (read_length == 0)
+          {
+            _last_error.clear();
+            _last_error+= "Socket was shutdown while reading from ";
+            _last_error+= _host;
+
+            return false;
+          }
+
+          operation->push(buffer, static_cast<size_t>(read_length));
+
+        } while (more_to_read());
+      } // end has_response
+
+      state= FINISHED;
+      break;
+
+    case FINISHED:
+      std::string response;
+      bool success= operation->response(response);
+      if (_finish_fn)
+      {
+        if (not _finish_fn->call(success, response))
+        {
+          // Error was sent from _finish_fn 
+          return false;
+        }
+      }
+
+      if (operation->reconnect())
+      {
+      }
+      _operations.pop_back();
+      delete operation;
+
+      state= CONNECTED;
+      break;
+    } // end switch
+  }
+
+  return true;
+} // end run()
+
+bool Instance::more_to_read() const
+{
+  struct pollfd fds;
+  fds.fd= _sockfd;
+  fds.events = POLLIN;
+
+  if (poll(&fds, 1, 5) < 1) // Default timeout is 5
+  {
+    return false;
+  }
+
+  return true;
+}
+
+void Instance::close_socket()
+{
+  if (_sockfd == INVALID_SOCKET)
+  {
+    return;
+  }
+
+  /* in case of death shutdown to avoid blocking at close() */
+  if (shutdown(_sockfd, SHUT_RDWR) == SOCKET_ERROR && get_socket_errno() != ENOTCONN)
+  {
+    perror("shutdown");
+  }
+  else if (closesocket(_sockfd) == SOCKET_ERROR)
+  {
+    perror("close");
+  }
+
+  _sockfd= INVALID_SOCKET;
+}
+
+void Instance::free_addrinfo()
+{
+  if (_addrinfo == NULL)
+  {
+    return;
+  }
+
+  freeaddrinfo(_addrinfo);
+  _addrinfo= NULL;
+  _addrinfo_next= NULL;
+}
+
+} /* namespace util */
+} /* namespace datadifferential */
diff --git a/src/util/instance.hpp b/src/util/instance.hpp
new file mode 100644 (file)
index 0000000..853cc00
--- /dev/null
@@ -0,0 +1,117 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  DataDifferential Utility Library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <cassert>
+#include <cerrno>
+#include <cstddef>
+#include <cstdio>
+#include <netinet/in.h>
+#include <string>
+#include <sys/socket.h>
+
+#include "util/operation.hpp"
+
+struct addrinfo;
+
+namespace datadifferential {
+namespace util {
+
+class Instance
+{
+private:
+  enum connection_state_t {
+    NOT_WRITING,
+    NEXT_CONNECT_ADDRINFO,
+    CONNECT,
+    CONNECTING,
+    CONNECTED,
+    WRITING,
+    READING,
+    FINISHED
+  };
+  std::string _last_error;
+
+public: // Callbacks
+  class Finish {
+
+  public:
+    virtual ~Finish() { }
+
+    virtual bool call(const bool, const std::string &)= 0;
+  };
+
+
+public:
+  Instance(const std::string& hostname_arg, const std::string& service_arg);
+
+  Instance(const std::string& hostname_arg, const in_port_t port_arg);
+
+  ~Instance();
+
+  bool run();
+
+  void set_finish(Finish *arg)
+  {
+    _finish_fn= arg;
+  }
+
+  void push(util::Operation *next)
+  {
+    _operations.push_back(next);
+  }
+
+private:
+  void close_socket();
+
+  void free_addrinfo();
+
+  bool more_to_read() const;
+
+  std::string _host;
+  std::string _service;
+  int _sockfd;
+  connection_state_t state;
+  struct addrinfo *_addrinfo;
+  struct addrinfo *_addrinfo_next;
+  Finish *_finish_fn;
+  Operation::vector _operations;
+};
+
+} /* namespace util */
+} /* namespace datadifferential */
diff --git a/src/util/log.hpp b/src/util/log.hpp
new file mode 100644 (file)
index 0000000..662ef5f
--- /dev/null
@@ -0,0 +1,226 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential Utility library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <cerrno>
+#include <cstdarg>
+#include <cstdio>
+#include <fcntl.h>
+#include <iostream>
+#include <string>
+#include <syslog.h>
+
+#define UTIL_MAX_ERROR_SIZE 2048
+
+namespace datadifferential {
+namespace util {
+
+/** Verbosity levels.
+ */
+enum verbose_t
+{
+  // Logging this will cause shutdown
+  VERBOSE_FATAL= LOG_EMERG, // syslog:LOG_EMERG
+
+  VERBOSE_ALERT= LOG_ALERT, // syslog:LOG_ALERT
+  VERBOSE_CRITICAL= LOG_CRIT, //  syslog:LOG_CRIT
+
+  VERBOSE_ERROR= LOG_ERR, // syslog:LOG_ERR
+
+  VERBOSE_WARN= LOG_WARNING, // syslog:LOG_WARNING
+
+  VERBOSE_NOTICE= LOG_NOTICE, // syslog:LOG_NOTICE
+
+  VERBOSE_INFO= LOG_INFO, // syslog:LOG_INFO
+
+  VERBOSE_DEBUG= LOG_DEBUG // syslog:LOG_DEBUG
+};
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#endif
+
+struct log_info_st
+{
+  std::string name;
+  std::string filename;
+  int fd;
+  bool opt_syslog;
+  bool opt_file;
+  bool init_success;
+
+  log_info_st(const std::string& name_arg, const std::string &filename_arg, bool syslog_arg) :
+    name(name_arg),
+    filename(filename_arg),
+    fd(-1),
+    opt_syslog(syslog_arg),
+    opt_file(false),
+    init_success(false)
+  {
+    if (opt_syslog)
+    {
+      openlog(name.c_str(), LOG_PID | LOG_NDELAY, LOG_USER);
+    }
+
+    init();
+  }
+
+  void init()
+  {
+    if (filename.size())
+    {
+      if (filename.compare("stderr") == 0)
+      {
+        fd= STDERR_FILENO;
+      }
+      else
+      {
+        fd= open(filename.c_str(), O_CREAT | O_WRONLY | O_APPEND, 0644);
+        if (fd == -1)
+        {
+          if (opt_syslog)
+          {
+            char buffer[1024];
+            char *getcwd_ret= getcwd(buffer, sizeof(buffer));
+            syslog(LOG_ERR, "Could not open log file \"%.*s\", from \"%s\", open failed with (%s)", 
+                   int(filename.size()), filename.c_str(), 
+                   getcwd_ret,
+                   strerror(errno));
+          }
+          std::cerr << "Could not open log file for writing, switching to stderr." << std::endl;
+
+          fd= STDERR_FILENO;
+        }
+      }
+
+      opt_file= true;
+    }
+
+    init_success= true;
+  }
+
+  bool initialized() const
+  {
+    return init_success;
+  }
+
+  int file() const
+  {
+    return fd;
+  }
+
+  void write(verbose_t verbose, const char *format, ...)
+  {
+    if (opt_file or opt_syslog)
+    {
+      va_list args;
+      va_start(args, format);
+      char mesg[BUFSIZ];
+      int mesg_length= vsnprintf(mesg, sizeof(mesg), format, args);
+      va_end(args);
+
+      if (opt_file)
+      {
+        char buffer[UTIL_MAX_ERROR_SIZE];
+        int buffer_length= snprintf(buffer, sizeof(buffer), "%7s %.*s\n", verbose_name(verbose), mesg_length, mesg);
+        if (::write(file(), buffer, buffer_length) == -1)
+        {
+          std::cerr << "Could not write to log file." << std::endl;
+          syslog(LOG_EMERG, "gearmand could not open log file %s, got error %s", filename.c_str(), strerror(errno));
+        }
+
+      }
+
+      if (opt_syslog)
+      {
+        syslog(int(verbose), "%7s %.*s", verbose_name(verbose), mesg_length, mesg);
+      }
+    }
+  }
+
+  ~log_info_st()
+  {
+    if (fd != -1 and fd != STDERR_FILENO)
+    {
+      close(fd);
+    }
+
+    if (opt_syslog)
+    {
+      closelog();
+    }
+  }
+
+private:
+  const char *verbose_name(verbose_t verbose)
+  {
+    switch (verbose)
+    {
+    case VERBOSE_FATAL:
+      return "FATAL";
+
+    case VERBOSE_ALERT:
+      return "ALERT";
+
+    case VERBOSE_CRITICAL:
+      return "CRITICAL";
+
+    case VERBOSE_ERROR:
+      return "ERROR";
+
+    case VERBOSE_WARN:
+      return "WARNING";
+
+    case VERBOSE_NOTICE:
+      return "NOTICE";
+
+    case VERBOSE_INFO:
+      return "INFO";
+
+    case VERBOSE_DEBUG:
+      return "DEBUG";
+
+    default:
+      break;
+    }
+
+    return "UNKNOWN";
+  }
+};
+
+} // namespace util
+} // namespace datadifferential
diff --git a/src/util/logfile.cc b/src/util/logfile.cc
new file mode 100644 (file)
index 0000000..810424d
--- /dev/null
@@ -0,0 +1,97 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  DataDifferential Utility Library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "mem_config.h"
+
+#include "util/logfile.hpp"
+
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <fcntl.h>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace datadifferential {
+namespace util {
+
+Logfile::Logfile(const std::string &arg) :
+  _filename(arg)
+{
+  time_t tmp= time(NULL);
+  _log_file << "shutdown: " << ctime(&tmp) << std::endl;
+}
+
+Logfile::~Logfile()
+{
+  if (not _filename.empty())
+  {
+    _log_file.close();
+    if (access(_filename.c_str(), F_OK) == -1)
+    { }
+    else if (unlink(_filename.c_str()) == -1)
+    { }
+  }
+}
+
+bool Logfile::open()
+{
+  if (_filename.empty())
+  {
+    _log_file.open("/dev/stderr");
+    return true;
+  }
+
+  _log_file.open(_filename.c_str());
+  if (not _log_file.good())
+  {
+    return false;
+  }
+
+  time_t tmp= time(NULL);
+  _log_file << "startup: " << ctime(&tmp) << std::endl;
+
+  return true;
+}
+
+} /* namespace util */
+} /* namespace datadifferential */
diff --git a/src/util/logfile.hpp b/src/util/logfile.hpp
new file mode 100644 (file)
index 0000000..1d2c75a
--- /dev/null
@@ -0,0 +1,66 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  DataDifferential Utility Library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <string>
+#include <fstream>
+
+namespace datadifferential {
+namespace util {
+
+class Logfile
+{
+public:
+  Logfile(const std::string &arg);
+
+  ~Logfile();
+
+  std::ofstream &log()
+  {
+    return _log_file;
+  }
+
+  bool open();
+
+private:
+  const std::string _filename;
+  std::ofstream _log_file;
+};
+
+} /* namespace util */
+} /* namespace datadifferential */
diff --git a/src/util/operation.cc b/src/util/operation.cc
new file mode 100644 (file)
index 0000000..3b84a27
--- /dev/null
@@ -0,0 +1,74 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  DataDifferential Utility Library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include <mem_config.h>
+
+#include "util/operation.hpp"
+#include <string>
+
+namespace datadifferential {
+namespace util {
+
+bool Operation::response(std::string &arg)
+{
+  if (_response.empty())
+  {
+    return false;
+  }
+
+  if (not memcmp("OK\r\n", &_response[0], 3))
+  { }
+  else if (not memcmp("OK ", &_response[0], 3))
+  {
+    arg.append(&_response[3], _response.size() -3);
+  }
+  else if (not memcmp("ERR ", &_response[0], 4))
+  {
+    arg.append(&_response[4], _response.size() -4);
+    return false;
+  }
+  else 
+  {
+    arg.append(&_response[0], _response.size());
+  }
+
+  return true;
+}
+
+} /* namespace util */
+} /* namespace datadifferential */
diff --git a/src/util/operation.hpp b/src/util/operation.hpp
new file mode 100644 (file)
index 0000000..13aeeb1
--- /dev/null
@@ -0,0 +1,103 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  DataDifferential Utility Library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+
+#include <cstring>
+#include <iosfwd>
+#include <vector>
+
+namespace datadifferential {
+namespace util {
+
+class Operation {
+  typedef std::vector<char> Packet;
+
+public:
+  typedef std::vector<Operation *> vector;
+
+  Operation(const char *command, size_t command_length, bool expect_response= true) :
+    _expect_response(expect_response),
+    packet(),
+    _response()
+  {
+    packet.resize(command_length);
+    memcpy(&packet[0], command, command_length);
+  }
+
+  ~Operation()
+  { }
+
+  size_t size() const
+  {
+    return packet.size();
+  }
+
+  const char* ptr() const
+  {
+    return &(packet)[0];
+  }
+
+  bool has_response() const
+  {
+    return _expect_response;
+  }
+
+  void push(const char *buffer, size_t buffer_size)
+  {
+    size_t response_size= _response.size();
+    _response.resize(response_size +buffer_size);
+    memcpy(&_response[0] +response_size, buffer, buffer_size);
+  }
+
+  // Return false on error
+  bool response(std::string &);
+
+  bool reconnect() const
+  {
+    return false;
+  }
+
+private:
+  bool _expect_response;
+  Packet packet;
+  Packet _response;
+};
+
+} /* namespace util */
+} /* namespace datadifferential */
diff --git a/src/util/pidfile.cc b/src/util/pidfile.cc
new file mode 100644 (file)
index 0000000..90a6d17
--- /dev/null
@@ -0,0 +1,162 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  DataDifferential Utility Library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "mem_config.h"
+
+#include "util/pidfile.hpp"
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+#include <fcntl.h>
+#include <iostream>
+#include <sstream>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+extern "C" {
+
+  char pid_file[1024 * 4]= { 0 };
+
+  static void remove_pidfile(void)
+  {
+    if (pid_file[0])
+    {
+      if (unlink(pid_file) == -1)
+      {
+        std::cerr << "Could not remove pidfile: " << pid_file << "(" << strerror(errno) << ")" << std::endl;
+      }
+
+      pid_file[0]= 0;
+    }
+  }
+
+}
+
+namespace datadifferential {
+namespace util {
+
+Pidfile::Pidfile(const std::string &arg) :
+  _last_errno(0),
+  _filename(arg)
+{
+}
+
+
+Pidfile::~Pidfile()
+{
+  if (not _filename.empty())
+  {
+    if (access(_filename.c_str(), F_OK) == -1)
+    {
+      std::stringstream error_stream;
+      error_stream << "Could not access the pid file: " << _filename << "(" << strerror(errno) << ")";
+      _error_message= error_stream.str();
+    }
+    else if (unlink(_filename.c_str()) == -1)
+    {
+      std::stringstream error_stream;
+      error_stream << "Could not remove the pid file: " << _filename << "(" << strerror(errno) << ")";
+      _error_message= error_stream.str();
+    }
+  }
+  pid_file[0]= 0;
+}
+
+bool Pidfile::create()
+{
+  if (_filename.empty())
+  {
+    return true;
+  }
+
+  if (access(_filename.c_str(), F_OK) == 0)
+  {
+    if (unlink(_filename.c_str()) == -1)
+    {
+      std::stringstream error_stream;
+      error_stream << "Unable to remove exisiting file:" << _filename << "(" << strerror(errno) << ")";
+      _error_message= error_stream.str();
+
+      return false;
+    }
+  }
+
+  int oflags= O_CREAT|O_WRONLY|O_TRUNC;
+#ifdef HAVE_O_CLOEXEC
+  oflags= oflags | O_CLOEXEC;
+#endif
+
+  int file;
+  if ((file = open(_filename.c_str(), oflags, S_IRWXU|S_IRGRP|S_IROTH)) < 0)
+  {
+    std::stringstream error_stream;
+    error_stream << "Could not open pid file for writing: " << _filename << "(" << strerror(errno) << ")";
+    _error_message= error_stream.str();
+    
+    return false;
+  }
+
+  char buffer[BUFSIZ];
+  unsigned long temp= static_cast<unsigned long>(getpid());
+  int length= snprintf(buffer, sizeof(buffer), "%lu\n", temp);
+  if (write(file, buffer, length) != length)
+  { 
+    std::stringstream error_stream;
+    error_stream << "Could not write pid to file: " << _filename << "(" << strerror(errno) << ")";
+    _error_message= error_stream.str();
+    close(file);
+
+    return false;
+  }
+
+  if (close(file) < 0)
+  {
+    _error_message+= "Could not close() file after writing pid to it: "; 
+    _error_message+= _filename;
+    return false;
+  }
+  snprintf(pid_file, sizeof(pid_file), "%s", _filename.c_str());
+  atexit(remove_pidfile);
+
+  return true;
+}
+
+} /* namespace util */
+} /* namespace datadifferential */
diff --git a/src/util/pidfile.hpp b/src/util/pidfile.hpp
new file mode 100644 (file)
index 0000000..73ba49c
--- /dev/null
@@ -0,0 +1,66 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  DataDifferential Utility Library
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <string>
+
+namespace datadifferential {
+namespace util {
+
+class Pidfile
+{
+public:
+  Pidfile(const std::string &arg);
+
+  ~Pidfile();
+
+  const std::string &error_message()
+  {
+    return _error_message;
+  }
+
+  bool create();
+
+private:
+  int _last_errno;
+  const std::string _filename;
+  std::string _error_message;
+};
+
+} /* namespace util */
+} /* namespace datadifferential */
diff --git a/src/util/signal.cc b/src/util/signal.cc
new file mode 100644 (file)
index 0000000..8e63016
--- /dev/null
@@ -0,0 +1,232 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential Utility library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <mem_config.h>
+
+#include <cassert>
+#include <cerrno>
+#include <csignal>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+
+#include <util/signal.hpp>
+
+namespace datadifferential {
+namespace util {
+
+#define MAGIC_MEMORY 123569
+
+bool SignalThread::is_shutdown()
+{
+  bool ret;
+  pthread_mutex_lock(&shutdown_mutex);
+  ret= bool(__shutdown != SHUTDOWN_RUNNING);
+  pthread_mutex_unlock(&shutdown_mutex);
+
+  return ret;
+}
+
+void SignalThread::set_shutdown(shutdown_t arg)
+{
+  pthread_mutex_lock(&shutdown_mutex);
+  __shutdown= arg;
+  pthread_mutex_unlock(&shutdown_mutex);
+
+  if (arg == SHUTDOWN_GRACEFUL)
+  {
+    if (pthread_kill(thread, SIGUSR2) == 0)
+    {
+      void *retval;
+      pthread_join(thread, &retval);
+    }
+  }
+}
+
+shutdown_t SignalThread::get_shutdown()
+{
+  shutdown_t local;
+  pthread_mutex_lock(&shutdown_mutex);
+  local= __shutdown;
+  pthread_mutex_unlock(&shutdown_mutex);
+
+  return local;
+}
+
+void SignalThread::post()
+{
+  sem_post(&lock);
+}
+
+void SignalThread::test()
+{
+  assert(magic_memory == MAGIC_MEMORY);
+  assert(sigismember(&set, SIGABRT));
+  assert(sigismember(&set, SIGINT));
+  assert(sigismember(&set, SIGQUIT));
+  assert(sigismember(&set, SIGTERM));
+  assert(sigismember(&set, SIGUSR2));
+}
+
+void SignalThread::sighup(signal_callback_fn* arg)
+{
+  _sighup= arg;
+}
+
+void SignalThread::sighup()
+{
+  if (_sighup)
+  {
+    _sighup();
+  }
+}
+
+SignalThread::~SignalThread()
+{
+  if (not is_shutdown())
+  {
+    set_shutdown(SHUTDOWN_GRACEFUL);
+  }
+
+#if 0
+  if (pthread_equal(thread, pthread_self()) != 0 and (pthread_kill(thread, 0) == ESRCH) == true)
+  {
+    void *retval;
+    pthread_join(thread, &retval);
+  }
+#endif
+  sem_destroy(&lock);
+}
+
+extern "C" {
+
+static void *sig_thread(void *arg)
+{   
+  SignalThread *context= (SignalThread*)arg;
+
+  context->test();
+  context->post();
+
+  while (context->get_shutdown() == SHUTDOWN_RUNNING)
+  {
+    int sig;
+
+    if (context->wait(sig) == -1)
+    {
+      std::cerr << "sigwait() returned errno:" << strerror(errno) << std::endl;
+      continue;
+    }
+
+    switch (sig)
+    {
+    case SIGUSR2:
+      break;
+
+    case SIGHUP:
+      context->sighup();
+      break;
+
+    case SIGABRT:
+    case SIGINT:
+    case SIGQUIT:
+    case SIGTERM:
+      if (context->is_shutdown() == false)
+      {
+        context->set_shutdown(SHUTDOWN_FORCED);
+      }
+
+      if (context->exit_on_signal())
+      {
+        exit(EXIT_SUCCESS);
+      }
+
+      break;
+
+    default:
+      std::cerr << "Signal handling thread got unexpected signal " <<  strsignal(sig) << std::endl;
+      break;
+    }
+  }
+
+  return NULL;
+}
+
+}
+
+SignalThread::SignalThread(bool exit_on_signal_arg) :
+  _exit_on_signal(exit_on_signal_arg),
+  magic_memory(MAGIC_MEMORY),
+  __shutdown(SHUTDOWN_RUNNING),
+  thread(pthread_self()),
+  _sighup(NULL)
+{
+  pthread_mutex_init(&shutdown_mutex, NULL);
+  sigemptyset(&set);
+
+  sigaddset(&set, SIGABRT);
+  sigaddset(&set, SIGINT);
+  sigaddset(&set, SIGQUIT);
+  sigaddset(&set, SIGTERM);
+  sigaddset(&set, SIGUSR2);
+
+  sem_init(&lock, 0, 0);
+}
+
+
+bool SignalThread::setup()
+{
+  set_shutdown(SHUTDOWN_RUNNING);
+
+  int error;
+  if ((error= pthread_sigmask(SIG_BLOCK, &set, NULL)) != 0)
+  {
+    std::cerr << "pthread_sigmask() died during pthread_sigmask(" << strerror(error) << ")" << std::endl;
+    return false;
+  }
+
+  if ((error= pthread_create(&thread, NULL, &sig_thread, this)) != 0)
+  {
+    std::cerr << "pthread_create() died during pthread_create(" << strerror(error) << ")" << std::endl;
+    return false;
+  }
+
+  sem_wait(&lock);
+
+  return true;
+}
+
+} /* namespace util */
+} /* namespace datadifferential */
diff --git a/src/util/signal.hpp b/src/util/signal.hpp
new file mode 100644 (file)
index 0000000..fab67be
--- /dev/null
@@ -0,0 +1,106 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ *
+ *  Data Differential Utility library
+ *
+ *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once 
+
+#include <pthread.h>
+#include <semaphore.h>
+
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void (signal_callback_fn)();
+
+#ifdef __cplusplus
+}
+#endif
+
+namespace datadifferential {
+namespace util {
+
+enum shutdown_t {
+  SHUTDOWN_RUNNING,
+  SHUTDOWN_GRACEFUL,
+  SHUTDOWN_FORCED
+};
+
+class SignalThread {
+  bool _exit_on_signal;
+  sigset_t set;
+  sem_t lock;
+  uint64_t magic_memory;
+  volatile shutdown_t __shutdown;
+  pthread_mutex_t shutdown_mutex;
+
+public:
+
+  SignalThread(bool exit_on_signal_arg= false);
+
+  void test();
+  void post();
+  bool setup();
+
+  bool exit_on_signal()
+  {
+    return _exit_on_signal;
+  }
+
+  int wait(int& sig)
+  {
+    return sigwait(&set, &sig);
+  }
+
+  ~SignalThread();
+
+  void set_shutdown(shutdown_t arg);
+  bool is_shutdown();
+  shutdown_t get_shutdown();
+
+  void sighup();
+  void sighup(signal_callback_fn* arg);
+
+private:
+  pthread_t thread;
+  signal_callback_fn* _sighup;
+};
+
+} /* namespace util */
+} /* namespace datadifferential */
diff --git a/src/util/string.hpp b/src/util/string.hpp
new file mode 100644 (file)
index 0000000..bf87eab
--- /dev/null
@@ -0,0 +1,57 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  DataDifferential Utility Library
+ *
+ *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+/*
+  Simple defines
+*/
+
+#include <cstring>
+#include <cstddef>
+
+#pragma once
+
+#define util_literal_param(X) (X), (static_cast<size_t>((sizeof(X) - 1)))
+#define util_literal_param_size(X) static_cast<size_t>(sizeof(X) - 1)
+
+#define util_literal_compare_param(X) (static_cast<size_t>((sizeof(X) - 1))), (X)
+
+#define util_string_make_from_cstr(X) (X), ((X) ? strlen(X) : 0)
+
+#define util_string_make_from_array(__array) (__array), (strlen(__array))
+
+#define util_array_length(__array) sizeof(__array)/sizeof(&__array)
+
diff --git a/src/win32/wrappers.h b/src/win32/wrappers.h
new file mode 100644 (file)
index 0000000..5bf325e
--- /dev/null
@@ -0,0 +1,77 @@
+/* LibMemcached
+ * Copyright (C) 2010 Brian Aker, Trond Norbye
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: "Implementation" of the function we don't have on windows
+ *          to avoid a bunch of ifdefs in the rest of the code
+ *
+ */
+#pragma once 
+
+#include <inttypes.h>
+
+/*
+ * One of the Windows headers define interface as a macro, but that
+ * is causing problems with the member named "interface" in some of the
+ * structs.
+ */
+#undef interface
+
+#undef malloc
+#undef realloc
+
+
+/*
+ * WinSock use a separate range for error codes. Let's just map to the
+ * WinSock ones.
+ */
+#ifndef EADDRINUSE
+# define EADDRINUSE WSAEADDRINUSE
+#endif
+
+#ifndef EWOULDBLOCK
+# define EWOULDBLOCK WSAEWOULDBLOCK
+#endif
+
+#ifndef EINPROGRESS
+# define EINPROGRESS WSAEINPROGRESS
+#endif
+
+#ifndef EALREADY
+# define EALREADY WSAEALREADY
+#endif
+
+#ifndef EISCONN
+# define EISCONN WSAEISCONN
+#endif
+
+#ifndef ENOTCONN
+# define ENOTCONN WSAENOTCONN
+#endif
+
+#ifndef ENOBUFS
+# define ENOBUFS WSAENOBUFS
+#endif
+
+#ifndef SHUT_RDWR
+# define SHUT_RDWR SD_BOTH
+#endif
+
+/* EAI_SYSTEM isn't defined anywhere... just set it to... 11? */
+#ifndef EAI_SYSTEM
+# define EAI_SYSTEM 11
+#endif
+
+/* Best effort mapping of functions to alternative functions */
+#define index(a,b) strchr(a,b)
+#define rindex(a,b) strrchr(a,b)
+#define random() rand()
+#define srandom(a) while (false) {}
+#define kill(a, b) while (false) {}
+#define fork() (-1)
+#define waitpid(a,b,c) (-1)
+#define fnmatch(a,b,c) (-1)
+#define sleep(a) Sleep(a*1000)
index f73dacdb62b314658f7ade3fac2b93ff8e8c3213..bfb02143728791d6a2c1231ff31a8a3709bf05b5 100644 (file)
@@ -3,12 +3,10 @@ add_subdirectory(libmemcached-1.0)
 
 add_executable(cycle cycle.cc)
 target_link_libraries(cycle PRIVATE libtest Threads::Threads)
-target_include_directories(cycle PRIVATE ..)
 add_test(cycle cycle)
 
 add_executable(parser parser.cc)
 target_link_libraries(parser PRIVATE libtest libmemcached)
-target_include_directories(parser PRIVATE ..)
 add_test(parser parser)
 
 add_executable(failure failure.cc)
@@ -33,12 +31,10 @@ endforeach()
 
 add_executable(testhashkit hashkit_functions.cc)
 target_link_libraries(testhashkit PRIVATE libtest libhashkit)
-target_include_directories(testhashkit PRIVATE ..)
 add_test(testhashkit testhashkit)
 
 add_executable(hash_plus hash_plus.cc)
 target_link_libraries(hash_plus PRIVATE libtest libhashkit)
-target_include_directories(hash_plus PRIVATE ..)
 add_test(testhashplus hash_plus)
 
 foreach(CLIENT IN LISTS CLIENTS)
@@ -49,7 +45,6 @@ foreach(CLIENT IN LISTS CLIENTS)
                 libmemcachedutil
                 libtest
                 )
-        target_include_directories(test${CLIENT} PRIVATE ..)
         add_test(test${CLIENT} test${CLIENT})
     endif()
 endforeach()
diff --git a/tests/cli.am b/tests/cli.am
deleted file mode 100644 (file)
index 1bb9a6a..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-# vim:ft=automake
-# Copyright (C) 2012 Data Differential
-# All rights reserved.
-#
-# Use and distribution licensed under the BSD license.  See
-# the COPYING file in the parent directory for full text.
-#
-# included from Top Level Makefile.am
-# All paths should be given relative to the root
-
-
-tests_memcapable_SOURCES= tests/memcapable.cc
-tests_memcapable_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-EXTRA_tests_memcapable_DEPENDENCIES= clients/memcapable
-tests_memcapable_LDADD=  libtest/libtest.la $(TESTS_LDADDS)
-check_PROGRAMS+= tests/memcapable
-noinst_PROGRAMS+= tests/memcapable
-
-tests_memstat_SOURCES= tests/memstat.cc
-tests_memstat_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-EXTRA_tests_memstat_DEPENDENCIES= clients/memstat
-tests_memstat_LDADD=  libtest/libtest.la $(TESTS_LDADDS)
-check_PROGRAMS+= tests/memstat
-noinst_PROGRAMS+= tests/memstat
-
-tests_memcp_SOURCES= tests/memcp.cc
-tests_memcp_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-EXTRA_tests_memcp_DEPENDENCIES= clients/memcp
-tests_memcp_LDADD=  libtest/libtest.la $(TESTS_LDADDS)
-check_PROGRAMS+= tests/memcp
-noinst_PROGRAMS+= tests/memcp
-
-tests_memflush_SOURCES= tests/memflush.cc
-tests_memflush_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-EXTRA_tests_memflush_DEPENDENCIES= clients/memflush
-tests_memflush_LDADD= libtest/libtest.la $(TESTS_LDADDS)
-check_PROGRAMS+= tests/memflush
-noinst_PROGRAMS+= tests/memflush
-
-tests_memrm_SOURCES= tests/memrm.cc
-tests_memrm_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-EXTRA_tests_memrm_DEPENDENCIES= clients/memrm
-tests_memrm_LDADD= libtest/libtest.la $(TESTS_LDADDS)
-check_PROGRAMS+= tests/memrm
-noinst_PROGRAMS+= tests/memrm
-
-tests_memexist_SOURCES= tests/memexist.cc
-tests_memexist_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-EXTRA_tests_memexist_DEPENDENCIES= clients/memexist
-tests_memexist_LDADD= libtest/libtest.la $(TESTS_LDADDS)
-check_PROGRAMS+= tests/memexist
-noinst_PROGRAMS+= tests/memexist
-
-tests_memtouch_SOURCES= tests/memtouch.cc
-tests_memtouch_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-EXTRA_tests_memtouch_DEPENDENCIES= clients/memtouch
-tests_memtouch_LDADD=  libtest/libtest.la $(TESTS_LDADDS)
-check_PROGRAMS+= tests/memtouch
-noinst_PROGRAMS+= tests/memtouch
-
-tests_memcat_SOURCES= tests/memcat.cc
-tests_memcat_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-EXTRA_tests_memcat_DEPENDENCIES= clients/memcat
-tests_memcat_LDADD= libtest/libtest.la $(TESTS_LDADDS)
-check_PROGRAMS+= tests/memcat
-noinst_PROGRAMS+= tests/memcat
-
-tests_memping_SOURCES= tests/memping.cc
-tests_memping_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-EXTRA_tests_memping_DEPENDENCIES= clients/memping
-tests_memping_LDADD= libtest/libtest.la $(TESTS_LDADDS)
-check_PROGRAMS+= tests/memping
-noinst_PROGRAMS+= tests/memping
-
-tests_memerror_SOURCES= tests/memerror.cc
-tests_memerror_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-EXTRA_tests_memerror_DEPENDENCIES= clients/memerror
-tests_memerror_LDADD= libtest/libtest.la $(TESTS_LDADDS)
-check_PROGRAMS+= tests/memerror
-noinst_PROGRAMS+= tests/memerror
-
-tests_memslap_SOURCES= tests/memslap.cc
-tests_memslap_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-EXTRA_tests_memslap_DEPENDENCIES= clients/memslap
-tests_memslap_LDADD= libtest/libtest.la $(TESTS_LDADDS)
-check_PROGRAMS+= tests/memslap
-noinst_PROGRAMS+= tests/memslap
-
-test-memslap: tests/memslap
-       @tests/memslap
-
-gdb-memslap: tests/memslap
-       @$(GDB_COMMAND) tests/memslap
-
-tests_memdump_SOURCES= tests/memdump.cc
-tests_memdump_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
-EXTRA_tests_memdump_DEPENDENCIES= clients/memdump
-tests_memdump_LDADD=  libtest/libtest.la $(TESTS_LDADDS)
-check_PROGRAMS+= tests/memdump
-noinst_PROGRAMS+= tests/memdump
-
-test-memcp: tests/memcp
-       tests/memcp
-
-gdb-memcp: tests/memcp
-       @$(GDB_COMMAND) tests/memcp
-
-test-memstat: tests/memstat
-       tests/memstat
-
-test-memerror: tests/memerror
-       tests/memerror
-
-test-memtouch: tests/memtouch
-       tests/memtouch
-
-test-memping: tests/memping
-       tests/memping
-
-valgrind-memerror: tests/memerror
-        @$(VALGRIND_COMMAND) tests/memerror
-
-valgrind-memtouch: tests/memtouch
-        @$(VALGRIND_COMMAND) tests/memtouch
-
-test-memdump: tests/memdump
-       tests/memdump
-
-gdb-memdump: tests/memdump
-       @$(GDB_COMMAND) tests/memdump
-
-valgrind-memdump: tests/memdump
-        @$(VALGRIND_COMMAND) tests/memdump
index 11e7b3097f0ff181767640cbebb6fc4dfdb95aea..a92b50fe3348724f856b4b7143b8220ec5c2a050 100644 (file)
@@ -1,7 +1,6 @@
 
 add_executable(internals internals.cc string.cc)
 target_link_libraries(internals PRIVATE libtest libmemcachedinternal Threads::Threads)
-target_include_directories(internals PRIVATE ../..)
 add_test(internals internals)
 
 add_executable(testsasl
@@ -29,7 +28,6 @@ target_link_libraries(testsasl PRIVATE
         libtest
         Threads::Threads
         )
-target_include_directories(testsasl PRIVATE ../..)
 add_test(testsasl testsasl)
 
 add_executable(atomsmasher atomsmasher.cc)
@@ -50,7 +48,6 @@ foreach(TEST IN ITEMS atomsmasher testplus)
             libmemcachedutil
             libtest
             )
-    target_include_directories(${TEST} PRIVATE ../..)
     add_test(${TEST} ${TEST})
 endforeach()
 
@@ -95,6 +92,6 @@ foreach(TEST IN ITEMS testapp testsocket)
             Threads::Threads
             ${LIBUUID_LIBRARIES}
             )
-    target_include_directories(${TEST} PRIVATE ../.. ${LIBUUID_INCLUDEDIR})
+    target_include_directories(${TEST} PRIVATE ${LIBUUID_INCLUDEDIR})
     add_test(${TEST} ${TEST})
 endforeach()
index 6dbd6d8cc3898c4cb2db089321ce26e3fef72300..3a87bd23728510d7c15443a06e77911f932c971f 100644 (file)
@@ -27,8 +27,8 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <ctime>
-#include <clients/generator.h>
-#include <clients/execute.h>
+#include <bin/generator.h>
+#include <bin/execute.h>
 
 #include <libtest/server.h>
 
index 4ebaa98b2d723deceedce870017d394489a88c85..8af302b02e0a2db24ea375254ef713edfa106797 100644 (file)
@@ -45,8 +45,8 @@
 #include <tests/libmemcached-1.0/fetch_all_results.h>
 #include "tests/libmemcached-1.0/callback_counter.h"
 
-#include "clients/generator.h"
-#include "clients/execute.h"
+#include "bin/generator.h"
+#include "bin/execute.h"
 
 #include "tests/memc.hpp"
 
index 8290e2687bb4ae24422a00245905fcd3dbc9c0a7..74921f707c738e30c8e7532a28dbaab0d3d322cd 100644 (file)
@@ -68,7 +68,7 @@
 
 #include <libtest/server.h>
 
-#include "clients/generator.h"
+#include "bin/generator.h"
 
 #define SMALL_STRING_LEN 1024
 
index 4e7c957da441a8648b941a1a833a7c7ac35c2526..6a9034399bddd2089f7bbddabe1b3b401aafae63 100644 (file)
@@ -119,7 +119,7 @@ static void *world_create(server_startup_st& servers, test_return_t&)
 
 void get_world(libtest::Framework* world)
 {
-  executable= "./clients/memcapable";
+  executable= "./src/bin/memcapable";
   world->collections(collection);
   world->create(world_create);
 }
index 3b3b021fd1fa7453012b3c82da603f655d20ace5..1108b92f9871110025bbe841220ecfcf58c2bbea 100644 (file)
@@ -50,7 +50,7 @@ using namespace libtest;
 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif
 
-static std::string executable("clients/memcat");
+static std::string executable("src/bin/memcat");
 
 static test_return_t help_test(void *)
 {
index 7ce5a493e9f3287b56033488b5aaf1fb86b839ac..547d568cd3f8e08597585c16307e8b1423e2ace1 100644 (file)
@@ -52,7 +52,7 @@ using namespace libtest;
 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif
 
-static std::string executable("./clients/memcp");
+static std::string executable("./src/bin/memcp");
 
 static test_return_t help_test(void *)
 {
index ab59c3ce245a594a535fb83dd44e7ae22e0216ca..2d9937b30fe125e2914a562e4a92037535881d29 100644 (file)
@@ -50,7 +50,7 @@ using namespace libtest;
 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif
 
-static std::string executable("./clients/memdump");
+static std::string executable("./src/bin/memdump");
 
 static test_return_t help_test(void *)
 {
index 423340179adcb4763789aa5689ebb7aa6ba84e28..6920a169d29fb3bfafc77c1f990a486bd2743cea 100644 (file)
@@ -50,7 +50,7 @@ using namespace libtest;
 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif
 
-static std::string executable("./clients/memerror");
+static std::string executable("./src/bin/memerror");
 
 static test_return_t help_TEST(void *)
 {
index 41a4648dc36bdc8e629abda2b63f4a99a156c66b..f2dd2f7a150bb9f25eb2b86914671038029c34cc 100644 (file)
@@ -51,7 +51,7 @@ using namespace libtest;
 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif
 
-static std::string executable("./clients/memexist");
+static std::string executable("./src/bin/memexist");
 
 static test_return_t help_test(void *)
 {
index c197b4903956c8ada4969e9c0229e68145af0c3d..e7caf606d6ef82ef15dcc215f5c3255221accc34 100644 (file)
@@ -112,7 +112,7 @@ static void *world_create(server_startup_st& servers, test_return_t& error)
 
 void get_world(libtest::Framework* world)
 {
-  executable= "./clients/memflush";
+  executable= "./src/bin/memflush";
   world->collections(collection);
   world->create(world_create);
 }
index af057defa7ad9e587f5055f4071c51d60870d83c..75c7687f2bb1c41f62e8b1c933ec98a0b7b74915 100644 (file)
@@ -50,7 +50,7 @@ using namespace libtest;
 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif
 
-static std::string executable("clients/memping");
+static std::string executable("src/bin/memping");
 
 static test_return_t help_test(void *)
 {
index 6955f1fa391003a72a9f470ef7bb596ed6b1d46d..bc342b1a9c6ed2daa2c212053e7e5862cca8b2c7 100644 (file)
@@ -50,7 +50,7 @@ using namespace libtest;
 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif
 
-static std::string executable("./clients/memrm");
+static std::string executable("./src/bin/memrm");
 
 static test_return_t quiet_test(void *)
 {
index 8a1a5cba74a23c5f468284ecede35f9ac1c1a32c..352c43bb31d6110bffaa7e2c49df34ae673e4118 100644 (file)
@@ -185,7 +185,7 @@ static void *world_create(server_startup_st& servers, test_return_t& error)
 
 void get_world(libtest::Framework* world)
 {
-  executable= "./clients/memslap";
+  executable= "./src/bin/memslap";
   world->collections(collection);
   world->create(world_create);
 }
index 7bbab3633cc00ba8a1bc1bfdc5bcdbf05be3bde0..168b5cd1ca42293d0b7caf8450f378a3e1b4a466 100644 (file)
@@ -50,7 +50,7 @@ using namespace libtest;
 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif
 
-static std::string executable("./clients/memstat");
+static std::string executable("./src/bin/memstat");
 
 static test_return_t help_test(void *)
 {
index 761a70723c4b2e34145f7374a7e20906167c02ca..d7c798cd605b86601503d7cf7946bf870e071b89 100644 (file)
@@ -156,7 +156,7 @@ static void *world_create(server_startup_st& servers, test_return_t& error)
 
 void get_world(libtest::Framework* world)
 {
-  executable= "./clients/memtouch";
+  executable= "./src/bin/memtouch";
   world->collections(collection);
   world->create(world_create);
 }
diff --git a/util/daemon.cc b/util/daemon.cc
deleted file mode 100644 (file)
index 90e29ef..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/*    $Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $    */
-/*    $NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $    */
-/*-
- * Copyright (c) 1990, 1993
- *    The Regents of the University of California.  All rights reserved.
- * Copyright (c) 2010
- *    Stewart Smith
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <mem_config.h>
-
-#if defined __SUNPRO_C || defined __DECC || defined __HP_cc
-# pragma ident "@(#)$Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $"
-# pragma ident "$NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $"
-#endif
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <unistd.h>
-#include <sys/select.h>
-
-#include <util/daemon.hpp>
-
-#include <iostream>
-
-namespace datadifferential {
-namespace util {
-
-pid_t parent_pid;
-
-extern "C"
-{
-
-static void sigusr1_handler(int sig)
-{
-  if (sig == SIGUSR1)
-  {
-    _exit(EXIT_SUCCESS);
-  }
-}
-
-}
-
-bool daemon_is_ready(bool close_io)
-{
-  if (kill(parent_pid, SIGUSR1) == -1)
-  {
-    perror("kill");
-    return false;
-  }
-
-  if (close_io == false)
-  {
-    return true;;
-  }
-
-  int fd;
-  if ((fd = open("/dev/null", O_RDWR, 0)) < 0)
-  {
-    perror("open");
-    return false;
-  }
-  else
-  {
-    if (dup2(fd, STDIN_FILENO) < 0)
-    {
-      perror("dup2 stdin");
-      return false;
-    }
-
-    if (dup2(fd, STDOUT_FILENO) < 0)
-    {
-      perror("dup2 stdout");
-      return false;
-    }
-
-    if (dup2(fd, STDERR_FILENO) < 0)
-    {
-      perror("dup2 stderr");
-      return false;
-    }
-
-    if (fd > STDERR_FILENO)
-    {
-      if (close(fd) < 0)
-      {
-        perror("close");
-        return false;
-      }
-    }
-  }
-
-  return true;
-}
-
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
-
-bool daemonize(bool is_chdir, bool wait_sigusr1)
-{
-  struct sigaction new_action;
-
-  new_action.sa_handler= sigusr1_handler;
-  sigemptyset(&new_action.sa_mask);
-  new_action.sa_flags= 0;
-  sigaction(SIGUSR1, &new_action, NULL);
-
-  parent_pid= getpid();
-
-  pid_t child= fork();
-
-  switch (child)
-  {
-  case -1:
-    return false;
-
-  case 0:
-    break;
-
-  default:
-    if (wait_sigusr1)
-    {
-      /* parent */
-      int exit_code= EXIT_FAILURE;
-      int status;
-      while (waitpid(child, &status, 0) != child)
-      { }
-
-      if (WIFEXITED(status))
-      {
-        exit_code= WEXITSTATUS(status);
-      }
-      if (WIFSIGNALED(status))
-      {
-        exit_code= EXIT_FAILURE;
-      }
-      _exit(exit_code);
-    }
-    else
-    {
-      _exit(EXIT_SUCCESS);
-    }
-  }
-
-  /* child */
-  if (setsid() == -1)
-  {
-    perror("setsid");
-    return false;
-  }
-
-  if (is_chdir)
-  {
-    if (chdir("/") < 0)
-    {
-      perror("chdir");
-      return false;
-    }
-  }
-
-  return true; 
-}
-
-} /* namespace util */
-} /* namespace datadifferential */
diff --git a/util/daemon.hpp b/util/daemon.hpp
deleted file mode 100644 (file)
index 170f52d..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*    $Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $    */
-/*    $NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $    */
-/*-
- * Copyright (c) 1990, 1993
- *    The Regents of the University of California.  All rights reserved.
- * Copyright (c) 2010
- *    Stewart Smith
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#pragma once
-
-namespace datadifferential {
-namespace util {
-
-bool daemon_is_ready(bool close_io);
-bool daemonize(bool is_chdir= true, bool wait_sigusr1= true);
-
-} /* namespace util */
-} /* namespace datadifferential */
diff --git a/util/instance.cc b/util/instance.cc
deleted file mode 100644 (file)
index 8f5d173..0000000
+++ /dev/null
@@ -1,338 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  DataDifferential Utility Library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include "mem_config.h"
-
-#include "util/instance.hpp"
-
-#include <cstdio>
-#include <iostream>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <poll.h>
-#include <sstream>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#ifndef INVALID_SOCKET
-# define INVALID_SOCKET -1
-#endif
-
-#ifndef SOCKET_ERROR
-# define SOCKET_ERROR -1
-#endif
-
-#ifndef get_socket_errno
-# define get_socket_errno() errno
-#endif
-
-#ifndef closesocket
-# define closesocket(a) close(a)
-#endif
-
-
-namespace datadifferential {
-namespace util {
-
-Instance::Instance(const std::string& hostname_arg, const std::string& service_arg) :
-  _host(hostname_arg),
-  _service(service_arg),
-  _sockfd(INVALID_SOCKET),
-  state(NOT_WRITING),
-  _addrinfo(0),
-  _addrinfo_next(0),
-  _finish_fn(NULL),
-  _operations()
-  {
-  }
-
-Instance::Instance(const std::string& hostname_arg, const in_port_t port_arg) :
-  _host(hostname_arg),
-  _sockfd(INVALID_SOCKET),
-  state(NOT_WRITING),
-  _addrinfo(0),
-  _addrinfo_next(0),
-  _finish_fn(NULL),
-  _operations()
-  {
-    char tmp[BUFSIZ];
-    snprintf(tmp, sizeof(tmp), "%u", static_cast<unsigned int>(port_arg));
-    _service= tmp;
-  }
-
-Instance::~Instance()
-{
-  close_socket();
-  free_addrinfo();
-  for (Operation::vector::iterator iter= _operations.begin(); iter != _operations.end(); ++iter)
-  {
-    delete *iter;
-  }
-  _operations.clear();
-
-  delete _finish_fn;
-}
-
-bool Instance::run()
-{
-  while (not _operations.empty())
-  {
-    Operation::vector::value_type operation= _operations.back();
-
-    switch (state)
-    {
-    case NOT_WRITING:
-      {
-        free_addrinfo();
-
-        struct addrinfo ai;
-        memset(&ai, 0, sizeof(struct addrinfo));
-        ai.ai_socktype= SOCK_STREAM;
-        ai.ai_protocol= IPPROTO_TCP;
-
-        int ret= getaddrinfo(_host.c_str(), _service.c_str(), &ai, &_addrinfo);
-        if (ret)
-        {
-          std::stringstream message;
-          message << "Failed to connect on " << _host.c_str() << ":" << _service.c_str() << " with "  << gai_strerror(ret);
-          _last_error= message.str();
-          return false;
-        }
-      }
-      _addrinfo_next= _addrinfo;
-      state= CONNECT;
-      break;
-
-    case NEXT_CONNECT_ADDRINFO:
-      if (_addrinfo_next->ai_next == NULL)
-      {
-        std::stringstream message;
-        message << "Error connecting to " << _host.c_str() << "." << std::endl;
-        _last_error= message.str();
-        return false;
-      }
-      _addrinfo_next= _addrinfo_next->ai_next;
-      /* fall through */
-
-    case CONNECT:
-      close_socket();
-
-      _sockfd= socket(_addrinfo_next->ai_family,
-                      _addrinfo_next->ai_socktype,
-                      _addrinfo_next->ai_protocol);
-      if (_sockfd == INVALID_SOCKET)
-      {
-        perror("socket");
-        continue;
-      }
-
-      if (connect(_sockfd, _addrinfo_next->ai_addr, _addrinfo_next->ai_addrlen) < 0)
-      {
-        switch(errno)
-        {
-        case EAGAIN:
-        case EINTR:
-          state= CONNECT;
-          break;
-
-        case EINPROGRESS:
-          state= CONNECTING;
-          break;
-
-        case ECONNREFUSED:
-        case ENETUNREACH:
-        case ETIMEDOUT:
-        default:
-          state= NEXT_CONNECT_ADDRINFO;
-          break;
-        }
-      }
-      else
-      {
-        state= CONNECTING;
-      }
-      break;
-
-    case CONNECTING:
-      // Add logic for poll() for nonblocking.
-      state= CONNECTED;
-      break;
-
-    case CONNECTED:
-    case WRITING:
-      {
-        size_t packet_length= operation->size();
-        const char *packet= operation->ptr();
-
-        while(packet_length)
-        {
-          ssize_t write_size= send(_sockfd, packet, packet_length, 0);
-
-          if (write_size < 0)
-          {
-            switch(errno)
-            {
-            default:
-              std::cerr << "Failed dureng send(" << strerror(errno) << ")" << std::endl;
-              break;
-            }
-          }
-
-          packet_length-= static_cast<size_t>(write_size);
-          packet+= static_cast<size_t>(write_size);
-        }
-      }
-      state= READING;
-      break;
-
-    case READING:
-      if (operation->has_response())
-      {
-        ssize_t read_length;
-
-        do
-        {
-          char buffer[BUFSIZ];
-          read_length= ::recv(_sockfd, buffer, sizeof(buffer), 0);
-
-          if (read_length < 0)
-          {
-            switch(errno)
-            {
-            default:
-              _last_error.clear();
-              _last_error+= "Error occured while reading data from ";
-              _last_error+= _host;
-              return false;
-            }
-          }
-          else if (read_length == 0)
-          {
-            _last_error.clear();
-            _last_error+= "Socket was shutdown while reading from ";
-            _last_error+= _host;
-
-            return false;
-          }
-
-          operation->push(buffer, static_cast<size_t>(read_length));
-
-        } while (more_to_read());
-      } // end has_response
-
-      state= FINISHED;
-      break;
-
-    case FINISHED:
-      std::string response;
-      bool success= operation->response(response);
-      if (_finish_fn)
-      {
-        if (not _finish_fn->call(success, response))
-        {
-          // Error was sent from _finish_fn 
-          return false;
-        }
-      }
-
-      if (operation->reconnect())
-      {
-      }
-      _operations.pop_back();
-      delete operation;
-
-      state= CONNECTED;
-      break;
-    } // end switch
-  }
-
-  return true;
-} // end run()
-
-bool Instance::more_to_read() const
-{
-  struct pollfd fds;
-  fds.fd= _sockfd;
-  fds.events = POLLIN;
-
-  if (poll(&fds, 1, 5) < 1) // Default timeout is 5
-  {
-    return false;
-  }
-
-  return true;
-}
-
-void Instance::close_socket()
-{
-  if (_sockfd == INVALID_SOCKET)
-  {
-    return;
-  }
-
-  /* in case of death shutdown to avoid blocking at close() */
-  if (shutdown(_sockfd, SHUT_RDWR) == SOCKET_ERROR && get_socket_errno() != ENOTCONN)
-  {
-    perror("shutdown");
-  }
-  else if (closesocket(_sockfd) == SOCKET_ERROR)
-  {
-    perror("close");
-  }
-
-  _sockfd= INVALID_SOCKET;
-}
-
-void Instance::free_addrinfo()
-{
-  if (_addrinfo == NULL)
-  {
-    return;
-  }
-
-  freeaddrinfo(_addrinfo);
-  _addrinfo= NULL;
-  _addrinfo_next= NULL;
-}
-
-} /* namespace util */
-} /* namespace datadifferential */
diff --git a/util/instance.hpp b/util/instance.hpp
deleted file mode 100644 (file)
index 853cc00..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  DataDifferential Utility Library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <cassert>
-#include <cerrno>
-#include <cstddef>
-#include <cstdio>
-#include <netinet/in.h>
-#include <string>
-#include <sys/socket.h>
-
-#include "util/operation.hpp"
-
-struct addrinfo;
-
-namespace datadifferential {
-namespace util {
-
-class Instance
-{
-private:
-  enum connection_state_t {
-    NOT_WRITING,
-    NEXT_CONNECT_ADDRINFO,
-    CONNECT,
-    CONNECTING,
-    CONNECTED,
-    WRITING,
-    READING,
-    FINISHED
-  };
-  std::string _last_error;
-
-public: // Callbacks
-  class Finish {
-
-  public:
-    virtual ~Finish() { }
-
-    virtual bool call(const bool, const std::string &)= 0;
-  };
-
-
-public:
-  Instance(const std::string& hostname_arg, const std::string& service_arg);
-
-  Instance(const std::string& hostname_arg, const in_port_t port_arg);
-
-  ~Instance();
-
-  bool run();
-
-  void set_finish(Finish *arg)
-  {
-    _finish_fn= arg;
-  }
-
-  void push(util::Operation *next)
-  {
-    _operations.push_back(next);
-  }
-
-private:
-  void close_socket();
-
-  void free_addrinfo();
-
-  bool more_to_read() const;
-
-  std::string _host;
-  std::string _service;
-  int _sockfd;
-  connection_state_t state;
-  struct addrinfo *_addrinfo;
-  struct addrinfo *_addrinfo_next;
-  Finish *_finish_fn;
-  Operation::vector _operations;
-};
-
-} /* namespace util */
-} /* namespace datadifferential */
diff --git a/util/log.hpp b/util/log.hpp
deleted file mode 100644 (file)
index 662ef5f..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential Utility library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <cerrno>
-#include <cstdarg>
-#include <cstdio>
-#include <fcntl.h>
-#include <iostream>
-#include <string>
-#include <syslog.h>
-
-#define UTIL_MAX_ERROR_SIZE 2048
-
-namespace datadifferential {
-namespace util {
-
-/** Verbosity levels.
- */
-enum verbose_t
-{
-  // Logging this will cause shutdown
-  VERBOSE_FATAL= LOG_EMERG, // syslog:LOG_EMERG
-
-  VERBOSE_ALERT= LOG_ALERT, // syslog:LOG_ALERT
-  VERBOSE_CRITICAL= LOG_CRIT, //  syslog:LOG_CRIT
-
-  VERBOSE_ERROR= LOG_ERR, // syslog:LOG_ERR
-
-  VERBOSE_WARN= LOG_WARNING, // syslog:LOG_WARNING
-
-  VERBOSE_NOTICE= LOG_NOTICE, // syslog:LOG_NOTICE
-
-  VERBOSE_INFO= LOG_INFO, // syslog:LOG_INFO
-
-  VERBOSE_DEBUG= LOG_DEBUG // syslog:LOG_DEBUG
-};
-
-#ifndef __INTEL_COMPILER
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
-#endif
-
-struct log_info_st
-{
-  std::string name;
-  std::string filename;
-  int fd;
-  bool opt_syslog;
-  bool opt_file;
-  bool init_success;
-
-  log_info_st(const std::string& name_arg, const std::string &filename_arg, bool syslog_arg) :
-    name(name_arg),
-    filename(filename_arg),
-    fd(-1),
-    opt_syslog(syslog_arg),
-    opt_file(false),
-    init_success(false)
-  {
-    if (opt_syslog)
-    {
-      openlog(name.c_str(), LOG_PID | LOG_NDELAY, LOG_USER);
-    }
-
-    init();
-  }
-
-  void init()
-  {
-    if (filename.size())
-    {
-      if (filename.compare("stderr") == 0)
-      {
-        fd= STDERR_FILENO;
-      }
-      else
-      {
-        fd= open(filename.c_str(), O_CREAT | O_WRONLY | O_APPEND, 0644);
-        if (fd == -1)
-        {
-          if (opt_syslog)
-          {
-            char buffer[1024];
-            char *getcwd_ret= getcwd(buffer, sizeof(buffer));
-            syslog(LOG_ERR, "Could not open log file \"%.*s\", from \"%s\", open failed with (%s)", 
-                   int(filename.size()), filename.c_str(), 
-                   getcwd_ret,
-                   strerror(errno));
-          }
-          std::cerr << "Could not open log file for writing, switching to stderr." << std::endl;
-
-          fd= STDERR_FILENO;
-        }
-      }
-
-      opt_file= true;
-    }
-
-    init_success= true;
-  }
-
-  bool initialized() const
-  {
-    return init_success;
-  }
-
-  int file() const
-  {
-    return fd;
-  }
-
-  void write(verbose_t verbose, const char *format, ...)
-  {
-    if (opt_file or opt_syslog)
-    {
-      va_list args;
-      va_start(args, format);
-      char mesg[BUFSIZ];
-      int mesg_length= vsnprintf(mesg, sizeof(mesg), format, args);
-      va_end(args);
-
-      if (opt_file)
-      {
-        char buffer[UTIL_MAX_ERROR_SIZE];
-        int buffer_length= snprintf(buffer, sizeof(buffer), "%7s %.*s\n", verbose_name(verbose), mesg_length, mesg);
-        if (::write(file(), buffer, buffer_length) == -1)
-        {
-          std::cerr << "Could not write to log file." << std::endl;
-          syslog(LOG_EMERG, "gearmand could not open log file %s, got error %s", filename.c_str(), strerror(errno));
-        }
-
-      }
-
-      if (opt_syslog)
-      {
-        syslog(int(verbose), "%7s %.*s", verbose_name(verbose), mesg_length, mesg);
-      }
-    }
-  }
-
-  ~log_info_st()
-  {
-    if (fd != -1 and fd != STDERR_FILENO)
-    {
-      close(fd);
-    }
-
-    if (opt_syslog)
-    {
-      closelog();
-    }
-  }
-
-private:
-  const char *verbose_name(verbose_t verbose)
-  {
-    switch (verbose)
-    {
-    case VERBOSE_FATAL:
-      return "FATAL";
-
-    case VERBOSE_ALERT:
-      return "ALERT";
-
-    case VERBOSE_CRITICAL:
-      return "CRITICAL";
-
-    case VERBOSE_ERROR:
-      return "ERROR";
-
-    case VERBOSE_WARN:
-      return "WARNING";
-
-    case VERBOSE_NOTICE:
-      return "NOTICE";
-
-    case VERBOSE_INFO:
-      return "INFO";
-
-    case VERBOSE_DEBUG:
-      return "DEBUG";
-
-    default:
-      break;
-    }
-
-    return "UNKNOWN";
-  }
-};
-
-} // namespace util
-} // namespace datadifferential
diff --git a/util/logfile.cc b/util/logfile.cc
deleted file mode 100644 (file)
index 810424d..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  DataDifferential Utility Library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "mem_config.h"
-
-#include "util/logfile.hpp"
-
-#include <cerrno>
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <fcntl.h>
-#include <fstream>
-#include <iostream>
-#include <sstream>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-namespace datadifferential {
-namespace util {
-
-Logfile::Logfile(const std::string &arg) :
-  _filename(arg)
-{
-  time_t tmp= time(NULL);
-  _log_file << "shutdown: " << ctime(&tmp) << std::endl;
-}
-
-Logfile::~Logfile()
-{
-  if (not _filename.empty())
-  {
-    _log_file.close();
-    if (access(_filename.c_str(), F_OK) == -1)
-    { }
-    else if (unlink(_filename.c_str()) == -1)
-    { }
-  }
-}
-
-bool Logfile::open()
-{
-  if (_filename.empty())
-  {
-    _log_file.open("/dev/stderr");
-    return true;
-  }
-
-  _log_file.open(_filename.c_str());
-  if (not _log_file.good())
-  {
-    return false;
-  }
-
-  time_t tmp= time(NULL);
-  _log_file << "startup: " << ctime(&tmp) << std::endl;
-
-  return true;
-}
-
-} /* namespace util */
-} /* namespace datadifferential */
diff --git a/util/logfile.hpp b/util/logfile.hpp
deleted file mode 100644 (file)
index 1d2c75a..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  DataDifferential Utility Library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <string>
-#include <fstream>
-
-namespace datadifferential {
-namespace util {
-
-class Logfile
-{
-public:
-  Logfile(const std::string &arg);
-
-  ~Logfile();
-
-  std::ofstream &log()
-  {
-    return _log_file;
-  }
-
-  bool open();
-
-private:
-  const std::string _filename;
-  std::ofstream _log_file;
-};
-
-} /* namespace util */
-} /* namespace datadifferential */
diff --git a/util/operation.cc b/util/operation.cc
deleted file mode 100644 (file)
index 3b84a27..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  DataDifferential Utility Library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-#include <mem_config.h>
-
-#include "util/operation.hpp"
-#include <string>
-
-namespace datadifferential {
-namespace util {
-
-bool Operation::response(std::string &arg)
-{
-  if (_response.empty())
-  {
-    return false;
-  }
-
-  if (not memcmp("OK\r\n", &_response[0], 3))
-  { }
-  else if (not memcmp("OK ", &_response[0], 3))
-  {
-    arg.append(&_response[3], _response.size() -3);
-  }
-  else if (not memcmp("ERR ", &_response[0], 4))
-  {
-    arg.append(&_response[4], _response.size() -4);
-    return false;
-  }
-  else 
-  {
-    arg.append(&_response[0], _response.size());
-  }
-
-  return true;
-}
-
-} /* namespace util */
-} /* namespace datadifferential */
diff --git a/util/operation.hpp b/util/operation.hpp
deleted file mode 100644 (file)
index 13aeeb1..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  DataDifferential Utility Library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-
-#include <cstring>
-#include <iosfwd>
-#include <vector>
-
-namespace datadifferential {
-namespace util {
-
-class Operation {
-  typedef std::vector<char> Packet;
-
-public:
-  typedef std::vector<Operation *> vector;
-
-  Operation(const char *command, size_t command_length, bool expect_response= true) :
-    _expect_response(expect_response),
-    packet(),
-    _response()
-  {
-    packet.resize(command_length);
-    memcpy(&packet[0], command, command_length);
-  }
-
-  ~Operation()
-  { }
-
-  size_t size() const
-  {
-    return packet.size();
-  }
-
-  const char* ptr() const
-  {
-    return &(packet)[0];
-  }
-
-  bool has_response() const
-  {
-    return _expect_response;
-  }
-
-  void push(const char *buffer, size_t buffer_size)
-  {
-    size_t response_size= _response.size();
-    _response.resize(response_size +buffer_size);
-    memcpy(&_response[0] +response_size, buffer, buffer_size);
-  }
-
-  // Return false on error
-  bool response(std::string &);
-
-  bool reconnect() const
-  {
-    return false;
-  }
-
-private:
-  bool _expect_response;
-  Packet packet;
-  Packet _response;
-};
-
-} /* namespace util */
-} /* namespace datadifferential */
diff --git a/util/pidfile.cc b/util/pidfile.cc
deleted file mode 100644 (file)
index 90a6d17..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  DataDifferential Utility Library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include "mem_config.h"
-
-#include "util/pidfile.hpp"
-
-#include <cstdio>
-#include <cstdlib>
-#include <cstring>
-#include <cerrno>
-#include <fcntl.h>
-#include <iostream>
-#include <sstream>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-extern "C" {
-
-  char pid_file[1024 * 4]= { 0 };
-
-  static void remove_pidfile(void)
-  {
-    if (pid_file[0])
-    {
-      if (unlink(pid_file) == -1)
-      {
-        std::cerr << "Could not remove pidfile: " << pid_file << "(" << strerror(errno) << ")" << std::endl;
-      }
-
-      pid_file[0]= 0;
-    }
-  }
-
-}
-
-namespace datadifferential {
-namespace util {
-
-Pidfile::Pidfile(const std::string &arg) :
-  _last_errno(0),
-  _filename(arg)
-{
-}
-
-
-Pidfile::~Pidfile()
-{
-  if (not _filename.empty())
-  {
-    if (access(_filename.c_str(), F_OK) == -1)
-    {
-      std::stringstream error_stream;
-      error_stream << "Could not access the pid file: " << _filename << "(" << strerror(errno) << ")";
-      _error_message= error_stream.str();
-    }
-    else if (unlink(_filename.c_str()) == -1)
-    {
-      std::stringstream error_stream;
-      error_stream << "Could not remove the pid file: " << _filename << "(" << strerror(errno) << ")";
-      _error_message= error_stream.str();
-    }
-  }
-  pid_file[0]= 0;
-}
-
-bool Pidfile::create()
-{
-  if (_filename.empty())
-  {
-    return true;
-  }
-
-  if (access(_filename.c_str(), F_OK) == 0)
-  {
-    if (unlink(_filename.c_str()) == -1)
-    {
-      std::stringstream error_stream;
-      error_stream << "Unable to remove exisiting file:" << _filename << "(" << strerror(errno) << ")";
-      _error_message= error_stream.str();
-
-      return false;
-    }
-  }
-
-  int oflags= O_CREAT|O_WRONLY|O_TRUNC;
-#ifdef HAVE_O_CLOEXEC
-  oflags= oflags | O_CLOEXEC;
-#endif
-
-  int file;
-  if ((file = open(_filename.c_str(), oflags, S_IRWXU|S_IRGRP|S_IROTH)) < 0)
-  {
-    std::stringstream error_stream;
-    error_stream << "Could not open pid file for writing: " << _filename << "(" << strerror(errno) << ")";
-    _error_message= error_stream.str();
-    
-    return false;
-  }
-
-  char buffer[BUFSIZ];
-  unsigned long temp= static_cast<unsigned long>(getpid());
-  int length= snprintf(buffer, sizeof(buffer), "%lu\n", temp);
-  if (write(file, buffer, length) != length)
-  { 
-    std::stringstream error_stream;
-    error_stream << "Could not write pid to file: " << _filename << "(" << strerror(errno) << ")";
-    _error_message= error_stream.str();
-    close(file);
-
-    return false;
-  }
-
-  if (close(file) < 0)
-  {
-    _error_message+= "Could not close() file after writing pid to it: "; 
-    _error_message+= _filename;
-    return false;
-  }
-  snprintf(pid_file, sizeof(pid_file), "%s", _filename.c_str());
-  atexit(remove_pidfile);
-
-  return true;
-}
-
-} /* namespace util */
-} /* namespace datadifferential */
diff --git a/util/pidfile.hpp b/util/pidfile.hpp
deleted file mode 100644 (file)
index 73ba49c..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  DataDifferential Utility Library
- *
- *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once
-
-#include <string>
-
-namespace datadifferential {
-namespace util {
-
-class Pidfile
-{
-public:
-  Pidfile(const std::string &arg);
-
-  ~Pidfile();
-
-  const std::string &error_message()
-  {
-    return _error_message;
-  }
-
-  bool create();
-
-private:
-  int _last_errno;
-  const std::string _filename;
-  std::string _error_message;
-};
-
-} /* namespace util */
-} /* namespace datadifferential */
diff --git a/util/signal.cc b/util/signal.cc
deleted file mode 100644 (file)
index 8e63016..0000000
+++ /dev/null
@@ -1,232 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential Utility library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <mem_config.h>
-
-#include <cassert>
-#include <cerrno>
-#include <csignal>
-#include <cstdlib>
-#include <cstring>
-#include <iostream>
-
-#include <util/signal.hpp>
-
-namespace datadifferential {
-namespace util {
-
-#define MAGIC_MEMORY 123569
-
-bool SignalThread::is_shutdown()
-{
-  bool ret;
-  pthread_mutex_lock(&shutdown_mutex);
-  ret= bool(__shutdown != SHUTDOWN_RUNNING);
-  pthread_mutex_unlock(&shutdown_mutex);
-
-  return ret;
-}
-
-void SignalThread::set_shutdown(shutdown_t arg)
-{
-  pthread_mutex_lock(&shutdown_mutex);
-  __shutdown= arg;
-  pthread_mutex_unlock(&shutdown_mutex);
-
-  if (arg == SHUTDOWN_GRACEFUL)
-  {
-    if (pthread_kill(thread, SIGUSR2) == 0)
-    {
-      void *retval;
-      pthread_join(thread, &retval);
-    }
-  }
-}
-
-shutdown_t SignalThread::get_shutdown()
-{
-  shutdown_t local;
-  pthread_mutex_lock(&shutdown_mutex);
-  local= __shutdown;
-  pthread_mutex_unlock(&shutdown_mutex);
-
-  return local;
-}
-
-void SignalThread::post()
-{
-  sem_post(&lock);
-}
-
-void SignalThread::test()
-{
-  assert(magic_memory == MAGIC_MEMORY);
-  assert(sigismember(&set, SIGABRT));
-  assert(sigismember(&set, SIGINT));
-  assert(sigismember(&set, SIGQUIT));
-  assert(sigismember(&set, SIGTERM));
-  assert(sigismember(&set, SIGUSR2));
-}
-
-void SignalThread::sighup(signal_callback_fn* arg)
-{
-  _sighup= arg;
-}
-
-void SignalThread::sighup()
-{
-  if (_sighup)
-  {
-    _sighup();
-  }
-}
-
-SignalThread::~SignalThread()
-{
-  if (not is_shutdown())
-  {
-    set_shutdown(SHUTDOWN_GRACEFUL);
-  }
-
-#if 0
-  if (pthread_equal(thread, pthread_self()) != 0 and (pthread_kill(thread, 0) == ESRCH) == true)
-  {
-    void *retval;
-    pthread_join(thread, &retval);
-  }
-#endif
-  sem_destroy(&lock);
-}
-
-extern "C" {
-
-static void *sig_thread(void *arg)
-{   
-  SignalThread *context= (SignalThread*)arg;
-
-  context->test();
-  context->post();
-
-  while (context->get_shutdown() == SHUTDOWN_RUNNING)
-  {
-    int sig;
-
-    if (context->wait(sig) == -1)
-    {
-      std::cerr << "sigwait() returned errno:" << strerror(errno) << std::endl;
-      continue;
-    }
-
-    switch (sig)
-    {
-    case SIGUSR2:
-      break;
-
-    case SIGHUP:
-      context->sighup();
-      break;
-
-    case SIGABRT:
-    case SIGINT:
-    case SIGQUIT:
-    case SIGTERM:
-      if (context->is_shutdown() == false)
-      {
-        context->set_shutdown(SHUTDOWN_FORCED);
-      }
-
-      if (context->exit_on_signal())
-      {
-        exit(EXIT_SUCCESS);
-      }
-
-      break;
-
-    default:
-      std::cerr << "Signal handling thread got unexpected signal " <<  strsignal(sig) << std::endl;
-      break;
-    }
-  }
-
-  return NULL;
-}
-
-}
-
-SignalThread::SignalThread(bool exit_on_signal_arg) :
-  _exit_on_signal(exit_on_signal_arg),
-  magic_memory(MAGIC_MEMORY),
-  __shutdown(SHUTDOWN_RUNNING),
-  thread(pthread_self()),
-  _sighup(NULL)
-{
-  pthread_mutex_init(&shutdown_mutex, NULL);
-  sigemptyset(&set);
-
-  sigaddset(&set, SIGABRT);
-  sigaddset(&set, SIGINT);
-  sigaddset(&set, SIGQUIT);
-  sigaddset(&set, SIGTERM);
-  sigaddset(&set, SIGUSR2);
-
-  sem_init(&lock, 0, 0);
-}
-
-
-bool SignalThread::setup()
-{
-  set_shutdown(SHUTDOWN_RUNNING);
-
-  int error;
-  if ((error= pthread_sigmask(SIG_BLOCK, &set, NULL)) != 0)
-  {
-    std::cerr << "pthread_sigmask() died during pthread_sigmask(" << strerror(error) << ")" << std::endl;
-    return false;
-  }
-
-  if ((error= pthread_create(&thread, NULL, &sig_thread, this)) != 0)
-  {
-    std::cerr << "pthread_create() died during pthread_create(" << strerror(error) << ")" << std::endl;
-    return false;
-  }
-
-  sem_wait(&lock);
-
-  return true;
-}
-
-} /* namespace util */
-} /* namespace datadifferential */
diff --git a/util/signal.hpp b/util/signal.hpp
deleted file mode 100644 (file)
index fab67be..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- *
- *  Data Differential Utility library
- *
- *  Copyright (C) 2012 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#pragma once 
-
-#include <pthread.h>
-#include <semaphore.h>
-
-#ifdef HAVE_SIGNAL_H
-#include <signal.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void (signal_callback_fn)();
-
-#ifdef __cplusplus
-}
-#endif
-
-namespace datadifferential {
-namespace util {
-
-enum shutdown_t {
-  SHUTDOWN_RUNNING,
-  SHUTDOWN_GRACEFUL,
-  SHUTDOWN_FORCED
-};
-
-class SignalThread {
-  bool _exit_on_signal;
-  sigset_t set;
-  sem_t lock;
-  uint64_t magic_memory;
-  volatile shutdown_t __shutdown;
-  pthread_mutex_t shutdown_mutex;
-
-public:
-
-  SignalThread(bool exit_on_signal_arg= false);
-
-  void test();
-  void post();
-  bool setup();
-
-  bool exit_on_signal()
-  {
-    return _exit_on_signal;
-  }
-
-  int wait(int& sig)
-  {
-    return sigwait(&set, &sig);
-  }
-
-  ~SignalThread();
-
-  void set_shutdown(shutdown_t arg);
-  bool is_shutdown();
-  shutdown_t get_shutdown();
-
-  void sighup();
-  void sighup(signal_callback_fn* arg);
-
-private:
-  pthread_t thread;
-  signal_callback_fn* _sighup;
-};
-
-} /* namespace util */
-} /* namespace datadifferential */
diff --git a/util/string.hpp b/util/string.hpp
deleted file mode 100644 (file)
index bf87eab..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
- * 
- *  DataDifferential Utility Library
- *
- *  Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are
- *  met:
- *
- *      * Redistributions of source code must retain the above copyright
- *  notice, this list of conditions and the following disclaimer.
- *
- *      * Redistributions in binary form must reproduce the above
- *  copyright notice, this list of conditions and the following disclaimer
- *  in the documentation and/or other materials provided with the
- *  distribution.
- *
- *      * The names of its contributors may not be used to endorse or
- *  promote products derived from this software without specific prior
- *  written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-/*
-  Simple defines
-*/
-
-#include <cstring>
-#include <cstddef>
-
-#pragma once
-
-#define util_literal_param(X) (X), (static_cast<size_t>((sizeof(X) - 1)))
-#define util_literal_param_size(X) static_cast<size_t>(sizeof(X) - 1)
-
-#define util_literal_compare_param(X) (static_cast<size_t>((sizeof(X) - 1))), (X)
-
-#define util_string_make_from_cstr(X) (X), ((X) ? strlen(X) : 0)
-
-#define util_string_make_from_array(__array) (__array), (strlen(__array))
-
-#define util_array_length(__array) sizeof(__array)/sizeof(&__array)
-
diff --git a/win32/wrappers.h b/win32/wrappers.h
deleted file mode 100644 (file)
index 5bf325e..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2010 Brian Aker, Trond Norbye
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: "Implementation" of the function we don't have on windows
- *          to avoid a bunch of ifdefs in the rest of the code
- *
- */
-#pragma once 
-
-#include <inttypes.h>
-
-/*
- * One of the Windows headers define interface as a macro, but that
- * is causing problems with the member named "interface" in some of the
- * structs.
- */
-#undef interface
-
-#undef malloc
-#undef realloc
-
-
-/*
- * WinSock use a separate range for error codes. Let's just map to the
- * WinSock ones.
- */
-#ifndef EADDRINUSE
-# define EADDRINUSE WSAEADDRINUSE
-#endif
-
-#ifndef EWOULDBLOCK
-# define EWOULDBLOCK WSAEWOULDBLOCK
-#endif
-
-#ifndef EINPROGRESS
-# define EINPROGRESS WSAEINPROGRESS
-#endif
-
-#ifndef EALREADY
-# define EALREADY WSAEALREADY
-#endif
-
-#ifndef EISCONN
-# define EISCONN WSAEISCONN
-#endif
-
-#ifndef ENOTCONN
-# define ENOTCONN WSAENOTCONN
-#endif
-
-#ifndef ENOBUFS
-# define ENOBUFS WSAENOBUFS
-#endif
-
-#ifndef SHUT_RDWR
-# define SHUT_RDWR SD_BOTH
-#endif
-
-/* EAI_SYSTEM isn't defined anywhere... just set it to... 11? */
-#ifndef EAI_SYSTEM
-# define EAI_SYSTEM 11
-#endif
-
-/* Best effort mapping of functions to alternative functions */
-#define index(a,b) strchr(a,b)
-#define rindex(a,b) strrchr(a,b)
-#define random() rand()
-#define srandom(a) while (false) {}
-#define kill(a, b) while (false) {}
-#define fork() (-1)
-#define waitpid(a,b,c) (-1)
-#define fnmatch(a,b,c) (-1)
-#define sleep(a) Sleep(a*1000)