Merge trunk for LP
authorBrian Aker <brian@tangent.org>
Thu, 7 Jul 2011 02:40:01 +0000 (19:40 -0700)
committerBrian Aker <brian@tangent.org>
Thu, 7 Jul 2011 02:40:01 +0000 (19:40 -0700)
108 files changed:
.bzrignore
ChangeLog
clients/memcapable.cc
docs/bin/memaslap.rst
docs/hashkit_create.rst
docs/hashkit_functions.rst
docs/hashkit_value.rst
docs/include.am
docs/libhashkit.rst
docs/libmemcached.rst
docs/libmemcached_configuration.rst
docs/libmemcached_examples.rst
docs/libmemcachedutil.rst
docs/memcached_analyze.rst
docs/memcached_append.rst
docs/memcached_behavior.rst
docs/memcached_callback.rst
libmemcached/assert.hpp [new file with mode: 0644]
libmemcached/auto.cc
libmemcached/behavior.cc
libmemcached/callback.cc
libmemcached/callback.h
libmemcached/common.h
libmemcached/connect.cc
libmemcached/constants.h
libmemcached/delete.cc
libmemcached/error.cc
libmemcached/error.h
libmemcached/error.hpp
libmemcached/exception.hpp
libmemcached/fetch.cc
libmemcached/get.cc
libmemcached/hash.cc
libmemcached/hosts.cc
libmemcached/include.am
libmemcached/io.cc
libmemcached/key.cc
libmemcached/memcached.cc
libmemcached/memcached.h
libmemcached/memcached_util.h
libmemcached/namespace.cc [new file with mode: 0644]
libmemcached/namespace.h [new file with mode: 0644]
libmemcached/options/parser.cc
libmemcached/options/parser.h
libmemcached/options/scanner.cc
libmemcached/options/scanner.h
libmemcached/prefix_key.cc [deleted file]
libmemcached/prefix_key.h [deleted file]
libmemcached/response.cc
libmemcached/server.cc
libmemcached/server.h
libmemcached/server_list.cc
libmemcached/stats.cc
libmemcached/storage.cc
libmemcached/string.cc
libmemcached/util/include.am
libmemcached/util/pid.cc [new file with mode: 0644]
libmemcached/util/pid.h [new file with mode: 0644]
libmemcached/util/ping.cc
libtest/common.h
libtest/error.h
libtest/failed.cc
libtest/framework.cc
libtest/framework.h
libtest/include.am
libtest/killpid.cc [new file with mode: 0644]
libtest/killpid.h [new file with mode: 0644]
libtest/memcached.cc [new file with mode: 0644]
libtest/server.c [deleted file]
libtest/server.cc [new file with mode: 0644]
libtest/server.h
libtest/stream.h [new file with mode: 0644]
libtest/test.cc
libtest/test.h
libtest/test.hpp
libtest/unittest.cc [new file with mode: 0644]
libtest/wait.cc [new file with mode: 0644]
libtest/wait.h [new file with mode: 0644]
m4/pandora_have_libboost_date_time.m4 [deleted file]
m4/pandora_have_libboost_filesystem.m4 [deleted file]
m4/pandora_have_libboost_iostreams.m4 [deleted file]
m4/pandora_have_libboost_options.m4 [deleted file]
m4/pandora_have_libboost_regex.m4 [deleted file]
m4/pandora_have_libboost_test.m4 [deleted file]
m4/pandora_have_libboost_thread.m4 [deleted file]
tests/atomsmasher.cc
tests/basic.cc
tests/cpp_example.cc
tests/cycle.cc [new file with mode: 0644]
tests/deprecated.cc
tests/error_conditions.cc
tests/hash_plus.cc
tests/hashkit_functions.cc
tests/include.am
tests/libmemcached_world.h
tests/mem_functions.cc
tests/mem_udp.cc
tests/namespace.cc [new file with mode: 0644]
tests/namespace.h [new file with mode: 0644]
tests/parser.cc
tests/parser.h
tests/plus.cpp
tests/pool.cc
tests/print.cc
tests/replication.cc
tests/start.cc [deleted file]
tests/string.cc
tests/virtual_buckets.cc

index 1757c6a6be57d6eaf3419de7c9263a18a9db7115..4c52adb65793e8cad77582cc519ddbd5b1ec15b9 100644 (file)
@@ -99,3 +99,8 @@ tests/testplus
 tests/testudp
 tests/var/
 unittests/unittests
+libtest/wait
+docs/text
+docs/changes
+tests/cycle
+libtest/unittest
index 969eda068562df7b06fc7d7b5b9bec787a5a39a6..f522e4ce3b221bae924ac26fa3627c0a60b51739 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+0.51
+
+  * memcached_callback_set() now takes its data argument as const
+
+
 0.50 Mon Jun 20 10:36:57 PDT 2011
  * Updates to C++ interface 
  * Custom free allocators need to now check for value before calling free.
index 9c9feb52d5d46ffa7356ed4a55b9490f17602bc9..99ca5ea77c30cda16e953e6caa8a24a05ae1a9a9 100644 (file)
@@ -655,7 +655,7 @@ static enum test_return test_binary_set_impl(const char* key, uint8_t cc)
   command cmd;
   response rsp;
 
-  uint64_t value= 0xdeadbeefdeadcafe;
+  uint64_t value= 0xdeadbeefdeadcafeULL;
   storage_command(&cmd, cc, key, strlen(key), &value, sizeof (value), 0, 0);
 
   /* set should always work */
@@ -725,7 +725,7 @@ static enum test_return test_binary_add_impl(const char* key, uint8_t cc)
 {
   command cmd;
   response rsp;
-  uint64_t value= 0xdeadbeefdeadcafe;
+  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
@@ -784,7 +784,7 @@ static enum test_return test_binary_replace_impl(const char* key, uint8_t cc)
 {
   command cmd;
   response rsp;
-  uint64_t value= 0xdeadbeefdeadcafe;
+  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
index b69bb3f8c4759743ada38bd3737405f7986a5849..fa73b51f74fb4ca5bb5e7ab1dc2df3d0afe8bd2e 100644 (file)
@@ -18,12 +18,14 @@ DESCRIPTION
 -----------
 
 
-memaslap is a load generation and benchmark tool for :program:`memcached()`
-servers. It generates configurable workload such as threads, concurrencies, connections, run time, overwrite, miss rate, key size, value size, get/set proportion, expected throughput, and so on. Furthermore, it also testss data
+:program:`memaslap` is a load generation and benchmark tool for memcached
+servers. It generates configurable workload such as threads, concurrencies, 
+connections, run time, overwrite, miss rate, key size, value size, get/set 
+proportion, expected throughput, and so on. Furthermore, it also testss data
 verification, expire-time verification, UDP, binary protocol, facebook test,
 replication test, multi-get and reconnection, etc.
 
-Memslap manages network connections like memcached with
+Memaslap manages network connections like memcached with
 libevent. Each thread of memaslap is bound with a CPU core, all
 the threads don't communicate with each other, and there are several socket
 connections in each thread. Each connection keeps key size distribution,
@@ -194,9 +196,9 @@ ________________________________________________________________________________
 
 Because each thread is self-governed, memaslap can assign
 different threads to handle different memcached servers. This is just one of
-the ways in which memaslap testss multiple servers. The only
+the ways in which memaslap tests multiple servers. The only
 limitation is that the number of servers cannot be greater than the number
-of threads. The other way to tests multiple servers is for replication
+of threads. The other way to test multiple servers is for replication
 test. Each concurrency has one socket connection to each memcached server.
 For the implementation, memaslap can set some objects to one
 memcached server, and get these objects from the other servers.
@@ -208,7 +210,7 @@ pack and send the commands together.
 Memslap testss both the ASCII protocol and binary protocol,
 but it runs on the ASCII protocol by default. 
 Memslap by default runs on the TCP protocol, but it also
-testss UDP. Because UDP is unreliable, dropped packages and out-of-order
+tests UDP. Because UDP is unreliable, dropped packages and out-of-order
 packages may occur. Memslap creates a memory buffer to handle
 these problems. Memslap tries to read all the response data of
 one command from the server and reorders the response data. If some packages
@@ -314,7 +316,7 @@ number of them. The default number of threads is 1; the default number of
 concurrency is 16. The user can use “—threads” and “--concurrency” to
 specify these variables.
 
-If the system testss setting CPU affinity and the number of threads
+If the system tests setting CPU affinity and the number of threads
 specified by the user is greater than 1, memaslap will try to
 bind each thread to a different CPU core. So if you want to get the best
 performance memaslap, it is better to specify the number of
index 8935b2d096f9d1c8eaca73bc58117604e0542ab8..bf96da751716277eeed2b283336bf181393468cd 100644 (file)
@@ -48,12 +48,12 @@ RETURN VALUE
 ------------
 
 
-:c:func:`hashkit_create()` and :c:func:`hashkit_clone()` will return NULL on failure or
-non-NULL on success.
+:c:func:`hashkit_create()` and :c:func:`hashkit_clone()` will return NULL on 
+failure or non-NULL on success.
 
 :c:func:`hashkit_is_allocated()` returns true if the memory for the hashkit
-object was allocated inside of :c:func:`hashkit_create()` or :c:func:`hashkit_clone()`,
-otherwise it is false and was user-supplied memory.
+object was allocated inside of :c:func:`hashkit_create()` or 
+:c:func:`hashkit_clone()`, otherwise it is false and was user-supplied memory.
 
 
 ----
@@ -63,3 +63,13 @@ HOME
 
 To find out more information please check:
 `http://libmemcached.org/ <http://libmemcached.org/>`_
+
+
+
+--------
+SEE ALSO
+--------
+
+
+:manpage:`hashkit_create(3)` :manpage:`hashkit_value(3)` :manpage:`hashkit_set_hash_fn(3)`
+
index 9342a4d4e818511106ccf8f8b1f12c7057d7af5d..737171d4b54f10c3c5a40ea783cd8efcf48f86f5 100644 (file)
@@ -71,6 +71,5 @@ SEE ALSO
 --------
 
 
-hashkit_create(3) hashkit_value(3) hashkit_set_hash_fn(3)
-hashkit_set_continuum_hash_fn(3)
+:manpage:`hashkit_create(3)` :manpage:`hashkit_value(3)` :manpage:`hashkit_set_hash_fn(3)` :manpage:`hashkit_set_continuum_hash_fn(3)`
 
index f768f887c4cb1e121d0ebc4cc82d72d52fa9036a..f418a394f14d5085819d1f260d0c018612808964 100644 (file)
@@ -26,7 +26,7 @@ DESCRIPTION
 -----------
 
 
-The hashkit_value() function generates a 32-bit hash value from the
+The :c:func:`hashkit_value()` function generates a 32-bit hash value from the
 given key and key_length. The hash argument is an initialized hashkit
 object, and distribution type and hash function is used from this
 object while generating the value.
@@ -54,5 +54,5 @@ SEE ALSO
 --------
 
 
-hashkit_create(3) hashkit_set_distribution(3) hashkit_set_hash_fn(3)
+:manpage:`hashkit_create(3)` :manpage:`hashkit_set_distribution(3)` :manpage:`hashkit_set_hash_fn(3)`
 
index 022b218bf8315ccb334870c5c351c8175f4390c9..d8c036d73f3d181bcc6163a695d0345afa6773d4 100644 (file)
@@ -144,38 +144,38 @@ sphinx-help:
        @echo "  linkcheck  to check all external links for integrity"
        @echo "  doctest    to run all doctests embedded in the documentation (if enabled)"
 
-html-local:
+html-local: docs/conf.py changes
        PYTHONPATH=${top_srcdir}/docs $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/html
        @echo
        @echo "Build finished. The HTML pages are in $(SPHINX_BUILDDIR)/html."
 
-dirhtml:
+dirhtml: docs/conf.py changes
        PYTHONPATH=${top_srcdir}/docs $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/dirhtml
        @echo
        @echo "Build finished. The HTML pages are in $(SPHINX_BUILDDIR)/dirhtml."
 
-singlehtml:
+singlehtml: docs/conf.py changes
        PYTHONPATH=${top_srcdir}/docs  $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/singlehtml
        @echo
        @echo "Build finished. The HTML page is in $(SPHINX_BUILDDIR)/singlehtml."
 
-pickle:
+pickle: docs/conf.py changes
        PYTHONPATH=${top_srcdir}/docs  $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/pickle
        @echo
        @echo "Build finished; now you can process the pickle files."
 
-json:
+json: docs/conf.py changes
        PYTHONPATH=${top_srcdir}/docs  $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/json
        @echo
        @echo "Build finished; now you can process the JSON files."
 
-htmlhelp:
+htmlhelp: docs/conf.py changes
        PYTHONPATH=${top_srcdir}/docs  $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/htmlhelp
        @echo
        @echo "Build finished; now you can run HTML Help Workshop with the" \
              ".hhp project file in $(SPHINX_BUILDDIR)/htmlhelp."
 
-qthelp:
+qthelp: docs/conf.py changes
        PYTHONPATH=${top_srcdir}/docs  $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/qthelp
        @echo
        @echo "Build finished; now you can run "qcollectiongenerator" with the" \
@@ -184,7 +184,7 @@ qthelp:
        @echo "To view the help file:"
        @echo "# assistant -collectionFile $(SPHINX_BUILDDIR)/qthelp/Libmemcached.qhc"
 
-devhelp:
+devhelp: docs/conf.py changes
        PYTHONPATH=${top_srcdir}/docs  $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/devhelp
        @echo
        @echo "Build finished."
@@ -193,40 +193,40 @@ devhelp:
        @echo "# ln -s $(SPHINX_BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Libmemcached"
        @echo "# devhelp"
 
-epub:
+epub: docs/conf.py changes
        PYTHONPATH=${top_srcdir}/docs  $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/epub
        @echo
        @echo "Build finished. The epub file is in $(SPHINX_BUILDDIR)/epub."
 
-latex:
+latex: docs/conf.py changes
        PYTHONPATH=${top_srcdir}/docs  $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/latex
        @echo
        @echo "Build finished; the LaTeX files are in $(SPHINX_BUILDDIR)/latex."
        @echo "Run \`make' in that directory to run these through (pdf)latex" \
              "(use \`make latexpdf' here to do that automatically)."
 
-latexpdf: latex
+latexpdf: latex changes
        PYTHONPATH=${top_srcdir}/docs  $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/latex
        @echo "Running LaTeX files through pdflatex..."
        make -C $(SPHINX_BUILDDIR)/latex all-pdf
        @echo "pdflatex finished; the PDF files are in $(SPHINX_BUILDDIR)/latex."
 
-text:
+text: docs/conf.py changes
        PYTHONPATH=${top_srcdir}/docs  $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/text
        @echo
        @echo "Build finished. The text files are in $(SPHINX_BUILDDIR)/text."
 
-man:
+man: docs/conf.py changes
        PYTHONPATH=${top_srcdir}/docs  $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/man
        @echo
        @echo "Build finished. The manual pages are in $(SPHINX_BUILDDIR)/man."
 
-changes:
+changes: docs/conf.py linkcheck
        PYTHONPATH=${top_srcdir}/docs  $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/changes
        @echo
        @echo "The overview file is in $(SPHINX_BUILDDIR)/changes."
 
-linkcheck:
+linkcheck: docs/conf.py
        PYTHONPATH=${top_srcdir}/docs  $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(SPHINX_BUILDDIR)/linkcheck
        @echo
        @echo "Link check complete; look for any errors in the above output " \
index d13b875752406ca8ed2a121b1ed6571f56ac5321..8866737ae8f3d48ece3525e05642e45a85b3a2ba 100644 (file)
@@ -15,7 +15,8 @@ Introducing libhashkit
 DESCRIPTION
 -----------
 
-:program:'libhashkit'  is a small and thread-safe client library that provides a collection of useful hashing algorithm. libhashkit is distributed with libmemcached.
+
+libhashkit  is a small and thread-safe client library that provides a collection of useful hashing algorithm. libhashkit is distributed with libmemcached.
 
 
 ----
index 78af3e320feea0159212dc740c62081ea6cf9ffa..80da8fe882381fad51fcc5bbd731a86cdc3ace8d 100644 (file)
@@ -33,7 +33,7 @@ DESCRIPTION
 system, generic in nature, but intended for use in speeding up dynamic web
 applications by alleviating database load." `http://danga.com/memcached/ <http://danga.com/memcached/>`_
 
-\ **libmemcached**\  is a small, thread-safe client library for the
+:program:`libmemcached` is a small, thread-safe client library for the
 memcached protocol. The code has all been written to allow
 for both web and embedded usage. It handles the work behind routing
 individual keys to specific servers specified by the developer (and values are
@@ -41,16 +41,17 @@ matched based on server order as supplied by the user). It implements
 a modular and consistent method of object distribution.
 
 There are multiple implemented routing and hashing methods. See the
-memcached_behavior_set() manpage for more information.
+:c:func:`memcached_behavior_set()` manpage for more information.
 
-All operations are performed against a :c:type:`memcached_st`  structure.
+All operations are performed against a :c:type:`memcached_st` structure.
 These structures can either be dynamically allocated or statically
-allocated and then initialized by memcached_create(). Functions have been
-written in order to encapsulate the :c:type:`memcached_st` . It is not
+allocated and then initialized by :c:func:`memcached_create()`. Functions have 
+been written in order to encapsulate the :c:type:`memcached_st`. It is not
 recommended that you operate directly against the structure.
 
-Nearly all functions return a :c:type:`memcached_return_t`\  value.
-This value can be translated to a printable string with memcached_strerror(3).
+Nearly all functions return a :c:type:`memcached_return_t` value.
+This value can be translated to a printable string with 
+:c:type:`memcached_strerror()`.
 
 Objects are stored on servers by hashing keys. The hash value maps the key to a particular server. All clients understand how this hashing works, so it is possibly to reliably both push data to a server and retrieve data from a server.
 
@@ -58,7 +59,7 @@ Group keys can be optionally used to group sets of objects with servers.
 
 Namespaces are supported, and can be used to partition caches so that multiple applications can use the same memcached servers.
 
-:c:type:`memcached_st`  structures are thread-safe, but each thread must
+:c:type:`memcached_st` structures are thread-safe, but each thread must
 contain its own structure (that is, if you want to share these among
 threads you must provide your own locking). No global variables are
 used in this library.
@@ -70,7 +71,7 @@ PKG_CHECK_MODULES(DEPS, libmemcached >= 0.8.0)
 AC_SUBST(DEPS_CFLAGS)
 AC_SUBST(DEPS_LIBS)
 
-Some features of the library must be enabled through memcached_behavior_set().
+Some features of the library must be enabled through :c:func:`memcached_behavior_set()`.
 
 Hope you enjoy it!
 
@@ -131,10 +132,9 @@ THREADS AND PROCESSES
 
 
 When using threads or forked processes it is important to keep one instance
-of :c:type:`memcached_st`  per process or thread. Without creating your own locking
-structures you can not share a single :c:type:`memcached_st`. However, you can call
-memcached_quit(3) on a :c:type:`memcached_st`  and then use the resulting cloned
-structure.
+of :c:type:`memcached_st` per process or thread. Without creating your own 
+locking structures you can not share a single :c:type:`memcached_st`. However, 
+you can call :c:func:`memcached_quit()` on a :c:type:`memcached_st` and then use the resulting cloned structure.
 
 
 ----
index 4cfec4a820ef715e5b7c223861233249b87b21ff..71a2c5bb061b456ed2b74a97c606bfab3d255896 100644 (file)
@@ -29,6 +29,10 @@ that you can use in your application directly.
 
 Provide a servername to be used by the client. Providing a weight will cause weighting to occur with all hosts with each server getting a default weight of 1.
 
+.. describe:: --SOCKET=<filepath>/?<optional_weight>
+
+Provide a filepath to a UNIX socket file. Providing a weight will cause weighting to occur with all hosts with each server getting a default weight of 1.
+
 .. describe:: --VERIFY-KEY
 
 Verify that keys that are being used fit within the design of the protocol being used.
@@ -185,7 +189,7 @@ RETURN
 ------
 
 
-memcached() returns a pointer to the memcached_st that was
+:c:func:`memcached()` returns a pointer to the memcached_st that was
 created (or initialized).  On an allocation failure, it returns NULL.
 
 
index 81137e86353dc7e31a696932dc257bc89cf79ec5..a9e30b30f864e49bb8653f467d355aea59da62c2 100644 (file)
@@ -21,15 +21,16 @@ Connecting to servers
 
 .. code-block:: c
 
-   const char *config_string= "--SERVER=host10.example.com --SERVER=host11.example.com --SERVER=host10.example.com"
-   memcached_st *memc= memcached(config_string, strlen(config_string);
-   {
-    ...
-   }
+  const char *config_string= "--SERVER=host10.example.com --SERVER=host11.example.com --SERVER=host10.example.com"
+  memcached_st *memc= memcached(config_string, strlen(config_string);
+  {
+  ...
+  }
    memcached_free(memc);
 
 
-In the above code you create a \ ``memcached_st``\  object with three server by making use of :manpage:`memcached_create_with_options(3)`.
+In the above code you create a :c:type:`memcached_st` object with three server 
+by making use of :c:func:`memcached_create_with_options()`.
 
 
 --------------------------
@@ -40,6 +41,8 @@ Creating a pool of servers
 
 .. code-block:: c
 
+Creating a pool of Servers::
+
   const char *config_string= "--SERVER=host10.example.com --SERVER=host11.example.com --SERVER=host10.example.com"; 
   
   memcached_pool_st* pool= memcached_pool(config_string, strlen(config_string));
@@ -62,10 +65,10 @@ Creating a pool of servers
 
 
 
-In the above code you create a \ ``memcached_pool_st``\  object with three
-server by making use of :manpage:`memcached_pool(3)`.
+In the above code you create a :c:type:`memcached_pool_st` object with three
+server by making use of :c:func:`memcached_pool()`.
 
-When memcached_pool_destroy() all memory will be released that is associated
+When :c:func:`memcached_pool_destroy()` all memory will be released that is associated
 with the pool.
 
 
@@ -77,6 +80,8 @@ Adding a value to the server
 
 .. code-block:: c
 
+Adding a value to the Server::
+
    char *key= "foo";
    char *value= "value";
 
@@ -104,14 +109,14 @@ Fetching multiple values
    size_t key_length[]= {5, 3, 4};
    unsigned int x;
    uint32_t flags;
+
    char return_key[MEMCACHED_MAX_KEY];
    size_t return_key_length;
    char *return_value;
    size_t return_value_length;
+
    rc= memcached_mget(memc, keys, key_length, 3);
+
    x= 0;
    while ((return_value= memcached_fetch(memc, return_key, &return_key_length, 
                                          &return_value_length, &flags, &rc)))
@@ -122,7 +127,7 @@ Fetching multiple values
 
 
 Notice that you freed values returned from memcached_fetch(). The define
-\ ``MEMCACHED_MAX_KEY``\  is provided for usage.
+:c:type:`MEMCACHED_MAX_KEY` is provided for usage.
 
 
 
index 091d9011eb7a9c644e7b57d1bf9e02e704dc932d..e50c800d2787dc104f4f50a9b5d7a2f5397fa68a 100644 (file)
@@ -23,8 +23,8 @@ DESCRIPTION
 -----------
 
 
-\ **libmemcachedutil**\  is a small and thread-safe client library that provides
-extra functionality built on top of \ **libmemcached**\ .
+:program:`libmemcachedutil`  is a small and thread-safe client library that 
+provides extra functionality built on top of :program:`libmemcached`.
 
 
 -------
@@ -32,10 +32,10 @@ THREADS
 -------
 
 
-Do not try to access an instance of \ ``memcached_st``\  from multiple threads
+Do not try to access an instance of :c:type:`memcached_st` from multiple threads
 at the same time. If you want to access memcached from multiple threads
-you should either clone the \ ``memcached_st``\ , or use the memcached pool
-implementation. see memcached_pool_create(3).
+you should either clone the :c:type:`memcached_st`, or use the memcached pool
+implementation. see :c:func:`memcached_pool_create()`.
 
 
 ----
@@ -52,6 +52,5 @@ SEE ALSO
 --------
 
 
-:manpage:`libmemcached(3)`
-:manpage:`memcached_pool_create(3)` :manpage:`memcached_pool_destroy(3)` :manpage:`memcached_pool_pop(3)` :manpage:`memcached_pool_push(3)`
+:manpage:`libmemcached(3)` :manpage:`memcached_pool_create(3)` :manpage:`memcached_pool_destroy(3)` :manpage:`memcached_pool_pop(3)` :manpage:`memcached_pool_push(3)`
 
index 56fbf1f3edf378c38cb946cba24d107992ff7500..9a0c49d232f007a9ca21433e37622a219be5f9b1 100644 (file)
@@ -24,16 +24,16 @@ DESCRIPTION
 -----------
 
 
-libmemcached(3) has the ability to query a memcached server (or collection
-of servers) for their current state. Queries to find state return a
-\ ``memcached_analysis_st``\  structure. You are responsible for freeing this structure.
+:program:`libmemcached` has the ability to query a memcached server (or 
+collection of servers) for their current state. Queries to find state return a
+:c:type:`memcached_analysis_st` structure. You are responsible for freeing this structure.
 
-memcached_analyze() analyzes useful information based on the provided servers
-and sets the result to the \ ``memcached_analysis_st``\  structure. The return value
-must be freed by the calling application.
+:c:func:`memcached_analyze()` analyzes useful information based on the 
+provided servers and sets the result to the :c:type:`memcached_analysis_st` 
+structure. The return value must be freed by the calling application.
 
-A command line tool, memstat(1) with the option --analyze, is provided so that
-you do not have to write an application to use this method.
+A command line tool, :c:func:`memstat()` with the option :option:`--analyze`, 
+is provided so that you do not have to write an application to use this method.
 
 
 ------
@@ -41,11 +41,11 @@ RETURN
 ------
 
 
-A pointer to the allocated \ ``memcached_analysis_st``\  structure on success and
-a NULL pointer on failure. You may inspect the error detail by checking the
-\ ``memcached_return_t``\  value.
+A pointer to the allocated :c:type:`memcached_analysis_st` structure on 
+success and a NULL pointer on failure. You may inspect the error detail by 
+checking the :c:type:`memcached_return_t` value.
 
-Any method returning a \ ``memcached_analysis_st``\  expects you to free the
+Any method returning a :c:type:`memcached_analysis_st` expects you to free the
 memory allocated for it.
 
 
index 20244c761697284b7bca41c3d37c57a335d3f9cb..a99b2cbc53deb4a48e44072d326861a97071a0f2 100644 (file)
@@ -30,43 +30,48 @@ DESCRIPTION
 -----------
 
 
-memcached_prepend() and memcached_append are used to 
+:c:func:`memcached_prepend()` and memcached_append are used to 
 modify information on a server. All methods take a key, and its length to
-store the object. Keys are currently limited to 250 characters when using either a version of memcached(1) which is 1.4 or below, or when using the text protocol.
-You must supply both a value and a length. Optionally you
+store the object. Keys are currently limited to 250 characters when using 
+either a version of memcached which is 1.4 or below, or when using the text 
+protocol. You must supply both a value and a length. Optionally you
 may test an expiration time for the object and a 16 byte value (it is
-meant to be used as a bitmap). "flags" is a 4byte space that is stored alongside of the main value. Many sub libraries make use of this field, so in most cases users should avoid making use of it.
+meant to be used as a bitmap). "flags" is a 4byte space that is stored 
+alongside of the main value. Many sub libraries make use of this field, 
+so in most cases users should avoid making use of it.
 
-memcached_prepend() places a segment of data before the last piece of data 
-stored. Currently expiration and key are not used in the server.
+:c:func:`memcached_prepend()` places a segment of data before the last piece 
+of data stored. Currently expiration and key are not used in the server.
 
-memcached_append() places a segment of data at the end of the last piece of 
-data stored. Currently expiration and key are not used in the server.
+:c:func:`memcached_append()` places a segment of data at the end of the last 
+piece of data stored. Currently expiration and key are not used in the server.
 
-memcached_prepend_by_key() and memcached_append_by_key_by_key(,
-methods both behave in a similar method as the non key 
-methods. The difference is that they use their group_key parameter to map
-objects to particular servers.
+:c:func:`memcached_prepend_by_key()` and 
+:c:func:`memcached_append_by_key_by_key()` methods both behave in a similar 
+method as the non key methods. The difference is that they use their 
+group_key parameter to map objects to particular servers.
 
-If you are looking for performance, memcached_set() with non-blocking IO is 
-the fastest way to store data on the server.
+If you are looking for performance, :c:func:`memcached_set()` with non-blocking
+IO is the fastest way to store data on the server.
 
-All of the above functions are testsed with the \ ``MEMCACHED_BEHAVIOR_USE_UDP``\ 
-behavior enabled. However, when using these operations with this behavior on, there 
-are limits to the size of the payload being sent to the server.  The reason for 
-these limits is that the Memcached Server does not allow multi-datagram requests
+All of the above functions are testsed with the 
+:c:type:`MEMCACHED_BEHAVIOR_USE_UDP` behavior enabled. However, when using 
+these operations with this behavior on, there are limits to the size of the 
+payload being sent to the server.  The reason for these limits is that the 
+Memcached Server does not allow multi-datagram requests
 and the current server implementation sets a datagram size to 1400 bytes. Due 
 to protocol overhead, the actual limit of the user supplied data is less than 
 1400 bytes and depends on the protocol in use as, well as the operation being 
-executed. When running with the binary protocol, \ `` MEMCACHED_BEHAVIOR_BINARY_PROTOCOL``\ , 
-the size of the key,value, flags and expiry combined may not exceed 1368 bytes. 
-When running with the ASCII protocol, the exact limit fluctuates depending on 
-which function is being executed and whether the function is a cas operation 
-or not. For non-cas ASCII set operations, there are at least 1335 bytes available 
-to split among the key, key_prefix, and value; for cas ASCII operations there are 
-at least 1318 bytes available to split among the key, key_prefix and value. If the
-total size of the command, including overhead, exceeds 1400 bytes, a \ ``MEMCACHED_WRITE_FAILURE``\ 
-will be returned.
+executed. When running with the binary protocol, 
+:c:type:`MEMCACHED_BEHAVIOR_BINARY_PROTOCOL`, the size of the key,value, 
+flags and expiry combined may not exceed 1368 bytes. When running with the 
+ASCII protocol, the exact limit fluctuates depending on which function is 
+being executed and whether the function is a cas operation or not. For 
+non-cas ASCII set operations, there are at least 1335 bytes available 
+to split among the key, key_prefix, and value; for cas ASCII operations 
+there are at least 1318 bytes available to split among the key, key_prefix 
+and value. If the total size of the command, including overhead, exceeds 
+1400 bytes, a :c:type:`MEMCACHED_WRITE_FAILURE` will be returned.
 
 
 ------
@@ -74,9 +79,10 @@ RETURN
 ------
 
 
-All methods return a value of type \ ``memcached_return_t``\ .
-On success the value will be \ ``MEMCACHED_SUCCESS``\ .
-Use memcached_strerror() to translate this value to a printable string.
+All methods return a value of type :c:type:`memcached_return_t`.
+On success the value will be :c:type:`MEMCACHED_SUCCESS`.
+Use :c:func:`memcached_strerror()` to translate this value to a printable 
+string.
 
 
 ----
@@ -93,5 +99,5 @@ SEE ALSO
 --------
 
 
-memcached(1) libmemached(3) memcached_strerror(3) memcached_set(3) memcached_add(3) memcached_cas(3) memcached_replace(3)
+:manpage:`memcached(1)` :manpage:`libmemached(3)` :manpage:`memcached_strerror(3)` :manpage:`memcached_set(3)` :manpage:`memcached_add(3)` :manpage:`memcached_cas(3)` :manpage:`memcached_replace(3)`
 
index 59ec483933719fbaedbfb3b305a9e93df3346c15..baa2eacd698585ebde104c14e4120d77d08352f2 100644 (file)
@@ -257,7 +257,9 @@ When enabled a host which is problematic will only be checked for usage based on
 
 .. c:type:: MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY
  
-When enabled the prefix key will be added to the key when determining server by hash.
+When enabled the prefix key will be added to the key when determining server
+by hash. See :c:type:`MEMCACHED_CALLBACK_NAMESPACE` for additional
+information.
  
 
 
index e5723d90984fc6375859ca845c329e09370516ae..060e43ab69664c8a2cd2236c85106e57bda7c19f 100644 (file)
@@ -14,7 +14,7 @@ SYNOPSIS
 
 #include <libmemcached/memcached.h>
  
-.. c:function:: memcached_return_t memcached_callback_set (memcached_st *ptr, memcached_callback_t flag, void *data);
+.. c:function:: memcached_return_t memcached_callback_set (memcached_st *ptr, memcached_callback_t flag, const void *data);
  
 .. c:function:: void * memcached_callback_get (memcached_st *ptr, memcached_callback_t flag, memcached_return_t *error);
 
@@ -53,6 +53,10 @@ When :c:func:`memcached_delete()` is called this function will be excuted.
 At the point of its execution all connections are closed.
 
 .. c:type:: MEMCACHED_CALLBACK_PREFIX_KEY
+
+   See :c:type:`MEMCACHED_CALLBACK_NAMESPACE`
+
+.. c:type:: MEMCACHED_CALLBACK_NAMESPACE
  
 You can set a value which will be used to create a domain for your keys.
 The value specified here will be prefixed to each of your keys. The value can 
diff --git a/libmemcached/assert.hpp b/libmemcached/assert.hpp
new file mode 100644 (file)
index 0000000..8a46784
--- /dev/null
@@ -0,0 +1,57 @@
+/*  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 <cstdlib>
+#include <cstdio>
+
+#ifdef NDEBUG
+#define        assert(__expr, __mesg)  ((void)0)
+#else
+
+#define assert_msg(__expr, __mesg) \
+do \
+{ \
+  if (not (__expr)) \
+  { \
+    fprintf(stderr, "\nAssertion \"%s\" failed for function \"%s\" likely for %s, at %s:%d\n", #__expr, __func__, (#__mesg),  __FILE__, __LINE__);\
+    abort(); \
+  } \
+} while (0)
+
+#endif
index 2bfc5bbad711106cebf87a62999d0c0f4a203495..f06d9ca06242387247bfbefb42e8cad782d0685b 100644 (file)
@@ -49,8 +49,10 @@ static memcached_return_t text_incr_decr(memcached_st *ptr,
   memcached_server_write_instance_st instance;
   bool no_reply= ptr->flags.no_reply;
 
-  if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
+  if (memcached_failed(memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
+  {
     return memcached_set_error(*ptr, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT);
+  }
 
   server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
   instance= memcached_server_instance_fetch(ptr, server_key);
@@ -58,7 +60,7 @@ static memcached_return_t text_incr_decr(memcached_st *ptr,
   int send_length;
   send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
                         "%s %.*s%.*s %" PRIu64 "%s\r\n", verb,
-                        memcached_print_array(ptr->prefix_key),
+                        memcached_print_array(ptr->_namespace),
                         (int)key_length, key,
                         offset, no_reply ? " noreply" : "");
   if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0)
@@ -111,15 +113,13 @@ static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd,
                                            uint32_t expiration,
                                            uint64_t *value)
 {
-  uint32_t server_key;
-  memcached_server_write_instance_st instance;
   bool no_reply= ptr->flags.no_reply;
 
   if (memcached_server_count(ptr) == 0)
     return memcached_set_error(*ptr, MEMCACHED_NO_SERVERS, MEMCACHED_AT);
 
-  server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
-  instance= memcached_server_instance_fetch(ptr, server_key);
+  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+  memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
 
   if (no_reply)
   {
@@ -133,10 +133,10 @@ static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd,
 
   request.message.header.request.magic= PROTOCOL_BINARY_REQ;
   request.message.header.request.opcode= cmd;
-  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->prefix_key)));
+  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->_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(ptr->prefix_key) +request.message.header.request.extlen));
+  request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(ptr->_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);
@@ -144,12 +144,12 @@ static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd,
   struct libmemcached_io_vector_st vector[]=
   {
     { sizeof(request.bytes), request.bytes },
-    { memcached_array_size(ptr->prefix_key), ptr->prefix_key },
+    { memcached_array_size(ptr->_namespace), memcached_array_string(ptr->_namespace) },
     { key_length, key }
   };
 
   memcached_return_t rc;
-  if ((rc= memcached_vdo(instance, vector, 3, true)) != MEMCACHED_SUCCESS)
+  if (memcached_failed(rc= memcached_vdo(instance, vector, 3, true)))
   {
     memcached_io_reset(instance);
     return (rc == MEMCACHED_SUCCESS) ? MEMCACHED_WRITE_FAILURE : rc;
@@ -166,10 +166,6 @@ memcached_return_t memcached_increment(memcached_st *ptr,
                                        uint32_t offset,
                                        uint64_t *value)
 {
-  uint64_t local_value;
-  if (! value)
-    value= &local_value;
-
   return memcached_increment_by_key(ptr, key, key_length, key, key_length, offset, value);
 }
 
@@ -178,10 +174,6 @@ memcached_return_t memcached_decrement(memcached_st *ptr,
                                        uint32_t offset,
                                        uint64_t *value)
 {
-  uint64_t local_value;
-  if (! value)
-    value= &local_value;
-
   return memcached_decrement_by_key(ptr, key, key_length, key, key_length, offset, value);
 }
 
index 60aa6b17db327308a690d20f68a76a745c90d812..0c182ec2e2f07036096cec7e350254723a28e512 100644 (file)
@@ -212,7 +212,7 @@ memcached_return_t memcached_behavior_set(memcached_st *ptr,
                                memcached_literal_param("MEMCACHED_BEHAVIOR_USER_DATA deprecated."));
 
   case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY:
-    ptr->flags.hash_with_prefix_key= bool(data);
+    ptr->flags.hash_with_namespace= bool(data);
     break;
 
   case MEMCACHED_BEHAVIOR_NOREPLY:
@@ -255,6 +255,11 @@ bool _is_auto_eject_host(const memcached_st *ptr)
 uint64_t memcached_behavior_get(memcached_st *ptr,
                                 const memcached_behavior_t flag)
 {
+  if (not ptr)
+  {
+    return MEMCACHED_INVALID_ARGUMENTS;
+  }
+
   switch (flag)
   {
   case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
@@ -410,7 +415,7 @@ uint64_t memcached_behavior_get(memcached_st *ptr,
     return 0;
 
   case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY:
-    return ptr->flags.hash_with_prefix_key;
+    return ptr->flags.hash_with_namespace;
 
   case MEMCACHED_BEHAVIOR_NOREPLY:
     return ptr->flags.no_reply;
index 9818af4f860e139c543ce84f311092c6533e83c8..473978634ce820bdafe3937f54d1ebc3caa0e33f 100644 (file)
 
 memcached_return_t memcached_callback_set(memcached_st *ptr,
                                           const memcached_callback_t flag,
-                                          void *data)
+                                          const void *data)
 {
   switch (flag)
   {
   case MEMCACHED_CALLBACK_PREFIX_KEY:
     {
-      return memcached_set_prefix_key(ptr, (char*)data, data ? strlen((char*)data) : 0);
+      return memcached_set_namespace(ptr, (char*)data, data ? strlen((char*)data) : 0);
     }
   case MEMCACHED_CALLBACK_USER_DATA:
     {
-      ptr->user_data= data;
+      ptr->user_data= const_cast<void *>(data);
       break;
     }
   case MEMCACHED_CALLBACK_CLEANUP_FUNCTION:
@@ -78,7 +78,6 @@ memcached_return_t memcached_callback_set(memcached_st *ptr,
       break;
     }
   case MEMCACHED_CALLBACK_MAX:
-  default:
     return MEMCACHED_FAILURE;
   }
 
@@ -98,10 +97,10 @@ void *memcached_callback_get(memcached_st *ptr,
   {
   case MEMCACHED_CALLBACK_PREFIX_KEY:
     {
-      if (ptr->prefix_key)
+      if (ptr->_namespace)
       {
         *error= MEMCACHED_SUCCESS;
-        return (void *)memcached_array_string(ptr->prefix_key);
+        return (void *)memcached_array_string(ptr->_namespace);
       }
       else
       {
index 816e966b935553d3bbad81e3fad364d1f19d16cf..a9465d2e3e2061e9438860904cf5769d4ba8b1bc 100644 (file)
@@ -50,7 +50,7 @@ extern "C" {
 LIBMEMCACHED_API
 memcached_return_t memcached_callback_set(memcached_st *ptr,
                                           const memcached_callback_t flag,
-                                          void *data);
+                                          const void *data);
 LIBMEMCACHED_API
 void *memcached_callback_get(memcached_st *ptr,
                              const memcached_callback_t flag,
index 40f45111826a9f840212990c67f72b10941a5305..46230ce3169585f7a6c6f029e3dcecee022656e5 100644 (file)
@@ -66,6 +66,7 @@
 #include <libmemcached/memcached.h>
 #include <libmemcached/watchpoint.h>
 #include <libmemcached/is.h>
+#include <libmemcached/namespace.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -99,7 +100,7 @@ memcached_return_t memcached_server_execute(memcached_st *ptr,
 #include <libmemcached/byteorder.h>
 #include <libmemcached/initialize_query.h>
 #include <libmemcached/response.h>
-#include <libmemcached/prefix_key.h>
+#include <libmemcached/namespace.h>
 
 /* string value */
 struct memcached_continuum_item_st
@@ -141,27 +142,32 @@ memcached_return_t run_distribution(memcached_st *ptr);
 LIBMEMCACHED_LOCAL
 void set_last_disconnected_host(memcached_server_write_instance_st ptr);
 
+#ifdef __cplusplus
 LIBMEMCACHED_LOCAL
-memcached_return_t memcached_key_test(const char * const *keys,
+memcached_return_t memcached_key_test(const memcached_st& memc,
+                                      const char * const *keys,
                                       const size_t *key_length,
                                       size_t number_of_keys);
+#endif
 
 LIBMEMCACHED_LOCAL
 memcached_return_t memcached_purge(memcached_server_write_instance_st ptr);
 
 LIBMEMCACHED_LOCAL
-memcached_server_st *memcached_server_create_with(const memcached_st *memc,
-                                                  memcached_server_write_instance_st host,
-                                                  const char *hostname,
-                                                  in_port_t port,
-                                                  uint32_t weight,
-                                                  memcached_connection_t type);
+  memcached_server_st *__server_create_with(const memcached_st *memc,
+                                            memcached_server_write_instance_st host,
+                                            const char *hostname,
+                                            in_port_t port,
+                                            uint32_t weight,
+                                            memcached_connection_t type);
 
 
 static inline memcached_return_t memcached_validate_key_length(size_t key_length, bool binary)
 {
   unlikely (key_length == 0)
+  {
     return MEMCACHED_BAD_KEY_PROVIDED;
+  }
 
   if (binary)
   {
index 5e6c77f568a44b07c2dcc68ecb4e9163a2eee5fa..43924116fc69f20919bf7b01b30c4385528bc54e 100644 (file)
@@ -101,11 +101,11 @@ static memcached_return_t connect_poll(memcached_server_st *ptr)
           int err;
           socklen_t len= sizeof (err);
           (void)getsockopt(ptr->fd, SOL_SOCKET, SO_ERROR, &err, &len);
-          ptr->cached_errno= (err == 0) ? get_socket_errno() : err;
+          memcached_set_errno(*ptr, (err == 0) ? get_socket_errno() : err, MEMCACHED_AT);
         }
         else
         {
-          ptr->cached_errno= get_socket_errno();
+          memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
         }
 
         WATCHPOINT_ASSERT(ptr->fd != INVALID_SOCKET);
@@ -347,7 +347,8 @@ static memcached_return_t unix_socket_connect(memcached_server_st *ptr)
 
   if ((ptr->fd= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
   {
-    return memcached_set_errno(*ptr, errno, NULL);
+    memcached_set_errno(*ptr, errno, NULL);
+    return MEMCACHED_CONNECTION_FAILURE;
   }
 
   struct sockaddr_un servAddr;
@@ -374,7 +375,8 @@ static memcached_return_t unix_socket_connect(memcached_server_st *ptr)
 
       default:
         WATCHPOINT_ERRNO(errno);
-        return memcached_set_errno(*ptr, errno, MEMCACHED_AT);
+        memcached_set_errno(*ptr, errno, MEMCACHED_AT);
+        return MEMCACHED_CONNECTION_FAILURE;
       }
     }
   } while (0);
@@ -540,7 +542,9 @@ memcached_return_t memcached_connect(memcached_server_write_instance_st ptr)
   memcached_return_t rc= MEMCACHED_NO_SERVERS;
 
   if (ptr->fd != INVALID_SOCKET)
+  {
     return MEMCACHED_SUCCESS;
+  }
 
   LIBMEMCACHED_MEMCACHED_CONNECT_START();
 
index 2cf2767190ef24e26996fc222c1930e586e7f9b9..165745e75af99b1aa4fd508fc098ac6bbfefaca3 100644 (file)
@@ -127,7 +127,8 @@ enum memcached_callback_t {
 #endif
   MEMCACHED_CALLBACK_GET_FAILURE = 7,
   MEMCACHED_CALLBACK_DELETE_TRIGGER = 8,
-  MEMCACHED_CALLBACK_MAX
+  MEMCACHED_CALLBACK_MAX,
+  MEMCACHED_CALLBACK_NAMESPACE= MEMCACHED_CALLBACK_PREFIX_KEY
 };
 
 #ifndef __cplusplus
index 1ae891a7bea073a4b1dda5763de5b6126faf6011..7ef05b07aef8f756945bc3e179e6aa1e52c1d8f2 100644 (file)
@@ -58,26 +58,26 @@ memcached_return_t memcached_delete_by_key(memcached_st *ptr,
 {
   bool to_write;
   char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  uint32_t server_key;
   memcached_server_write_instance_st instance;
 
   LIBMEMCACHED_MEMCACHED_DELETE_START();
 
   memcached_return_t rc;
-  if ((rc= initialize_query(ptr)) != MEMCACHED_SUCCESS)
+  if (memcached_failed(rc= initialize_query(ptr)))
   {
     return rc;
   }
 
   rc= memcached_validate_key_length(key_length,
                                     ptr->flags.binary_protocol);
-  unlikely (rc != MEMCACHED_SUCCESS)
+
+  unlikely (memcached_failed(rc))
     return rc;
 
   unlikely (memcached_server_count(ptr) == 0)
     return MEMCACHED_NO_SERVERS;
 
-  server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
+  uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
   instance= memcached_server_instance_fetch(ptr, server_key);
 
   to_write= (ptr->flags.buffer_requests) ? false : true;
@@ -134,7 +134,7 @@ memcached_return_t memcached_delete_by_key(memcached_st *ptr,
           }
           send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
                                 "delete %.*s%.*s %u%s\r\n",
-                                memcached_print_array(ptr->prefix_key),
+                                memcached_print_array(ptr->_namespace),
                                 (int) key_length, key,
                                 (uint32_t)expiration,
                                 no_reply ? " noreply" :"" );
@@ -144,7 +144,7 @@ memcached_return_t memcached_delete_by_key(memcached_st *ptr,
     {
       send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
                             "delete %.*s%.*s%s\r\n",
-                            memcached_print_array(ptr->prefix_key),
+                            memcached_print_array(ptr->_namespace),
                             (int)key_length, key, no_reply ? " noreply" :"");
     }
 
@@ -208,9 +208,9 @@ static inline memcached_return_t binary_delete(memcached_st *ptr,
   {
     request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETE;
   }
-  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->prefix_key)));
+  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->_namespace)));
   request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-  request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(ptr->prefix_key)));
+  request.message.header.request.bodylen= htonl((uint32_t)(key_length + memcached_array_size(ptr->_namespace)));
 
   if (ptr->flags.use_udp && ! flush)
   {
@@ -225,7 +225,7 @@ static inline memcached_return_t binary_delete(memcached_st *ptr,
   struct libmemcached_io_vector_st vector[]=
   {
     { sizeof(request.bytes), request.bytes},
-    { memcached_array_size(ptr->prefix_key), memcached_array_string(ptr->prefix_key) },
+    { memcached_array_size(ptr->_namespace), memcached_array_string(ptr->_namespace) },
     { key_length, key },
   };
 
index 5cfb4be29f6f3c45e9699c472b8f2520b65f90cf..a8f420431e71c0c8af37de62a08f6dac20894911 100644 (file)
@@ -50,12 +50,31 @@ struct memcached_error_t
   char message[MAX_ERROR_LENGTH];
 };
 
+static void _set(memcached_server_st& server, memcached_st& memc)
+{
+  if (server.error_messages && server.error_messages->query_id != server.root->query_id)
+  {
+    memcached_error_free(server);
+  }
+
+  if (memc.error_messages == NULL)
+    return;
+
+  memcached_error_t *error= (struct memcached_error_t *)libmemcached_malloc(&memc, sizeof(struct memcached_error_t));
+  if (not error) // Bad business if this happens
+    return;
+
+  memcpy(error, memc.error_messages, sizeof(memcached_error_t));
+  error->next= server.error_messages;
+  server.error_messages= error;
+}
+
 static void _set(memcached_st& memc, memcached_string_t *str, memcached_return_t &rc, const char *at, int local_errno= 0)
 {
   (void)at;
   if (memc.error_messages && memc.error_messages->query_id != memc.query_id)
   {
-    memcached_error_free(&memc);
+    memcached_error_free(memc);
   }
 
   // For memory allocation we use our error since it is a bit more specific
@@ -196,6 +215,7 @@ memcached_return_t memcached_set_error(memcached_server_st& self, memcached_retu
     return rc;
 
   _set(*self.root, &error_host, rc, at);
+  _set(self, (*self.root));
 
   return rc;
 }
@@ -215,6 +235,7 @@ memcached_return_t memcached_set_error(memcached_server_st& self, memcached_retu
     return rc;
 
   _set(*self.root, &error_host, rc, at);
+  _set(self, *self.root);
 
   return rc;
 }
@@ -285,13 +306,12 @@ memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errn
 
   memcached_string_t error_host= { hostname_port_message, size };
 
-  self.cached_errno= local_errno; // Store in the actual server
-
   memcached_return_t rc= MEMCACHED_ERRNO;
   if (not self.root)
     return rc;
 
   _set(*self.root, &error_host, rc, at, local_errno);
+  _set(self, (*self.root));
 
   return rc;
 }
@@ -307,13 +327,12 @@ memcached_return_t memcached_set_errno(memcached_server_st& self, int local_errn
 
   memcached_string_t error_host= { hostname_port_message, size };
 
-  self.cached_errno= local_errno; // Store in the actual server
-
   memcached_return_t rc= MEMCACHED_ERRNO;
   if (not self.root)
     return rc;
 
   _set(*self.root, &error_host, rc, at, local_errno);
+  _set(self, (*self.root));
 
   return rc;
 }
@@ -360,13 +379,16 @@ static void _error_free(memcached_error_t *error)
   }
 }
 
-void memcached_error_free(memcached_st *self)
+void memcached_error_free(memcached_stself)
 {
-  if (not self)
-    return;
+  _error_free(self.error_messages);
+  self.error_messages= NULL;
+}
 
-  _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_last_error_message(memcached_st *memc)
@@ -417,3 +439,40 @@ int memcached_last_error_errno(memcached_st *memc)
 
   return memc->error_messages->local_errno;
 }
+
+const char *memcached_server_error(memcached_server_instance_st server)
+{
+  if (not server)
+    return memcached_strerror(server->root, MEMCACHED_INVALID_ARGUMENTS);
+
+  if (not server->error_messages)
+    return memcached_strerror(server->root, MEMCACHED_SUCCESS);
+
+  if (not server->error_messages->size)
+    return memcached_strerror(server->root, server->error_messages->rc);
+
+  return server->error_messages->message;
+}
+
+
+memcached_error_t *memcached_error_copy(const memcached_server_st& server)
+{
+  if (not server.error_messages)
+    return NULL;
+
+  memcached_error_t *error= (memcached_error_t *)libmemcached_malloc(server.root, sizeof(memcached_error_t));
+  memcpy(error, server.error_messages, sizeof(memcached_error_t));
+  error->next= NULL;
+
+  return error;
+}
+
+memcached_return_t memcached_server_error_return(memcached_server_instance_st ptr)
+{
+  if (ptr and ptr->error_messages)
+  {
+    return ptr->error_messages->rc;
+  }
+
+  return MEMCACHED_FAILURE;
+}
index 754cffe8699dab7d879b62fd1267658ba3249683..99beb8cafbc840c640f59dccc1cf75861399ef0c 100644 (file)
@@ -41,9 +41,6 @@
 extern "C" {
 #endif
 
-LIBMEMCACHED_LOCAL
-  void memcached_error_free(memcached_st *error);
-
 LIBMEMCACHED_API
   const char *memcached_last_error_message(memcached_st *memc);
 
@@ -56,6 +53,12 @@ LIBMEMCACHED_API
 LIBMEMCACHED_API
   int memcached_last_error_errno(memcached_st *memc);
 
+LIBMEMCACHED_API
+  const char *memcached_server_error(memcached_server_instance_st ptr);
+
+LIBMEMCACHED_API
+  memcached_return_t memcached_server_error_return(memcached_server_instance_st ptr);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index 1c683fc5d7e5d2bf155af42a53fc0a2e75b23cba..55ff1bd9d06e429e29b54a5b8cf7648489f55f5b 100644 (file)
@@ -84,4 +84,13 @@ LIBMEMCACHED_LOCAL
 LIBMEMCACHED_LOCAL
 bool memcached_has_current_error(memcached_st &memc);
 
+LIBMEMCACHED_LOCAL
+void memcached_error_free(memcached_st&);
+
+LIBMEMCACHED_LOCAL
+void memcached_error_free(memcached_server_st&);
+
+LIBMEMCACHED_LOCAL
+memcached_error_t *memcached_error_copy(const memcached_server_st&);
+
 #endif
index 665c816fc10b3c69a160cf2936df4d2d5a070b31..4759072abdd758445e47674f37ef52cd9f151835 100644 (file)
@@ -10,8 +10,7 @@
  * @brief Exception declarations
  */
 
-#ifndef LIBMEMACHED_EXCEPTION_HPP
-#define LIBMEMACHED_EXCEPTION_HPP
+#pragma once
 
 #include <stdexcept>
 #include <string>
@@ -59,5 +58,3 @@ namespace memcache
   };
 
 } /* namespace libmemcached */
-
-#endif /* LIBMEMACHED_EXCEPTION_HPP */
index dd0b036d8433cecc7177e54f9c40912f1a2a5b0c..7ef608ddda231c9e9613b62187629aa4f6a4c949 100644 (file)
@@ -122,8 +122,6 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr,
                                             memcached_result_st *result,
                                             memcached_return_t *error)
 {
-  memcached_server_st *server;
-
   memcached_return_t unused;
   if (not error)
     error= &unused;
@@ -159,6 +157,7 @@ memcached_result_st *memcached_fetch_result(memcached_st *ptr,
   }
 
   *error= MEMCACHED_MAXIMUM_RETURN; // We use this to see if we ever go into the loop
+  memcached_server_st *server;
   while ((server= memcached_io_get_readable_server(ptr)))
   {
     char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
index 0cef87f5120021a1ce5be905d02699c894c4d0c2..dcb9f0012ba7234f8ae882ae635d4b6ad4030268 100644 (file)
@@ -67,6 +67,10 @@ char *memcached_get_by_key(memcached_st *ptr,
                            uint32_t *flags,
                            memcached_return_t *error)
 {
+  memcached_return_t unused;
+  if (error == NULL)
+    error= &unused;
+
   unlikely (ptr->flags.use_udp)
   {
     if (value_length) 
@@ -81,8 +85,8 @@ char *memcached_get_by_key(memcached_st *ptr,
 
   /* Request the key */
   *error= memcached_mget_by_key_real(ptr, group_key, group_key_length,
-                                     (const char * const *)&key,
-                                     &key_length, 1, false);
+                                     (const char * const *)&key, &key_length, 
+                                     1, false);
   assert(ptr->query_id == query_id +1);
 
 
@@ -219,7 +223,7 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
     return memcached_set_error(*ptr, MEMCACHED_NOTFOUND, MEMCACHED_AT, memcached_literal_param("number_of_keys was zero"));
   }
 
-  if (ptr->flags.verify_key && (memcached_key_test(keys, key_length, number_of_keys) == MEMCACHED_BAD_KEY_PROVIDED))
+  if (memcached_failed(memcached_key_test(*ptr, keys, key_length, number_of_keys)))
   {
     return memcached_set_error(*ptr, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT, memcached_literal_param("A bad key value was provided"));
   }
@@ -227,7 +231,7 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
   bool is_group_key_set= false;
   if (group_key && group_key_length)
   {
-    if (ptr->flags.verify_key and (memcached_key_test((const char * const *)&group_key, &group_key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
+    if (memcached_failed(memcached_key_test(*ptr, (const char * const *)&group_key, &group_key_length, 1)))
     {
       return memcached_set_error(*ptr, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT, memcached_literal_param("A bad group key was provided."));
     }
@@ -296,7 +300,7 @@ static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
     struct libmemcached_io_vector_st vector[]=
     {
       { get_command_length, get_command },
-      { memcached_array_size(ptr->prefix_key), memcached_array_string(ptr->prefix_key) },
+      { memcached_array_size(ptr->_namespace), memcached_array_string(ptr->_namespace) },
       { key_length[x], keys[x] },
       { 1, " " }
     };
@@ -489,14 +493,14 @@ static memcached_return_t simple_binary_mget(memcached_st *ptr,
       return vk;
     }
 
-    request.message.header.request.keylen= htons((uint16_t)(key_length[x] + memcached_array_size(ptr->prefix_key)));
+    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->prefix_key)));
+    request.message.header.request.bodylen= htonl((uint32_t)( key_length[x] + memcached_array_size(ptr->_namespace)));
 
     struct libmemcached_io_vector_st vector[]=
     {
       { sizeof(request.bytes), request.bytes },
-      { memcached_array_size(ptr->prefix_key), memcached_array_string(ptr->prefix_key) },
+      { memcached_array_size(ptr->_namespace), memcached_array_string(ptr->_namespace) },
       { key_length[x], keys[x] }
     };
 
@@ -608,9 +612,9 @@ static memcached_return_t replication_binary_mget(memcached_st *ptr,
       protocol_binary_request_getk request= {};
       request.message.header.request.magic= PROTOCOL_BINARY_REQ;
       request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
-      request.message.header.request.keylen= htons((uint16_t)(key_length[x] + memcached_array_size(ptr->prefix_key)));
+      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->prefix_key)));
+      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
@@ -625,7 +629,7 @@ static memcached_return_t replication_binary_mget(memcached_st *ptr,
       struct libmemcached_io_vector_st vector[]=
       {
         { sizeof(request.bytes), request.bytes },
-        { memcached_array_size(ptr->prefix_key), memcached_array_string(ptr->prefix_key) },
+        { memcached_array_size(ptr->_namespace), memcached_array_string(ptr->_namespace) },
         { key_length[x], keys[x] }
       };
 
index e239320d3b02f26451ae730843838245b1e4a015..ae07dfd0ea466829df85e16d09633f7e8e53d4fc 100644 (file)
@@ -107,16 +107,16 @@ static inline uint32_t _generate_hash_wrapper(const memcached_st *ptr, const cha
   if (memcached_server_count(ptr) == 1)
     return 0;
 
-  if (ptr->flags.hash_with_prefix_key)
+  if (ptr->flags.hash_with_namespace)
   {
-    size_t temp_length= memcached_array_size(ptr->prefix_key) + key_length;
+    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->prefix_key), memcached_array_size(ptr->prefix_key));
-    strncpy(temp + memcached_array_size(ptr->prefix_key), key, key_length);
+    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);
   }
index 32bf8ce37d9301bd6139feb77aecb041e1e3a07b..db6398914a699472d6163c3d4327b9f882e93055 100644 (file)
@@ -344,7 +344,9 @@ static memcached_return_t update_continuum(memcached_st *ptr)
 memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_server_list_st list)
 {
   if (not list)
+  {
     return MEMCACHED_SUCCESS;
+  }
 
   uint32_t count= memcached_server_list_count(list);
 
@@ -362,21 +364,19 @@ memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_serv
     memcached_server_write_instance_st instance;
 
     if ((ptr->flags.use_udp && list[x].type != MEMCACHED_CONNECTION_UDP)
-            || ((list[x].type == MEMCACHED_CONNECTION_UDP)
-            && ! (ptr->flags.use_udp)) )
+        or ((list[x].type == MEMCACHED_CONNECTION_UDP) and not (ptr->flags.use_udp)) )
     {
       return MEMCACHED_INVALID_HOST_PROTOCOL;
     }
 
     WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
 
+    // We have extended the array, and now we will find it, and use it.
     instance= memcached_server_instance_fetch(ptr, memcached_server_count(ptr));
     WATCHPOINT_ASSERT(instance);
 
-    /* TODO check return type */
-    instance= memcached_server_create_with(ptr, instance, list[x].hostname,
-                                           list[x].port, list[x].weight, list[x].type);
-    if (not instance)
+    if (not __server_create_with(ptr, instance, list[x].hostname,
+                                 list[x].port, list[x].weight, list[x].type))
     {
       return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
     }
@@ -454,7 +454,7 @@ memcached_return_t memcached_server_add_with_weight(memcached_st *ptr,
   if (not hostname)
     hostname= "localhost";
 
-  return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_TCP);
+  return server_add(ptr, hostname, port, weight, hostname[0] == '/' ? MEMCACHED_CONNECTION_UNIX_SOCKET  : MEMCACHED_CONNECTION_TCP);
 }
 
 static memcached_return_t server_add(memcached_st *ptr, const char *hostname,
@@ -480,7 +480,10 @@ static memcached_return_t server_add(memcached_st *ptr, const char *hostname,
   /* TODO: Check return type */
   memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, memcached_server_count(ptr));
 
-  (void)memcached_server_create_with(ptr, instance, hostname, port, weight, type);
+  if (not __server_create_with(ptr, instance, hostname, port, weight, type))
+  {
+    return memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+  }
 
   if (weight > 1)
   {
@@ -489,6 +492,7 @@ static memcached_return_t server_add(memcached_st *ptr, const char *hostname,
 
   ptr->number_of_hosts++;
 
+  // @note we place the count in the bottom of the server list
   instance= memcached_server_instance_fetch(ptr, 0);
   memcached_servers_set_count(instance, memcached_server_count(ptr));
 
index e799093fa60c3cdfaa64f6a02b366ad5e909620e..db612892245d430561b369b43b978547048741e8 100644 (file)
@@ -12,6 +12,7 @@ EXTRA_DIST+= \
             libmemcached/memcached/README.txt
 
 noinst_HEADERS+= \
+                libmemcached/assert.hpp \
                 libmemcached/byteorder.h \
                 libmemcached/common.h \
                 libmemcached/do.hpp \
@@ -54,7 +55,7 @@ nobase_include_HEADERS+= \
                         libmemcached/memcached/vbucket.h \
                         libmemcached/options.h \
                         libmemcached/parse.h \
-                        libmemcached/prefix_key.h \
+                        libmemcached/namespace.h \
                         libmemcached/protocol/cache.h \
                         libmemcached/protocol/callback.h \
                         libmemcached/protocol_handler.h \
@@ -130,7 +131,7 @@ libmemcached_libmemcached_la_SOURCES+= \
                                       libmemcached/memcached.cc \
                                       libmemcached/options.cc \
                                       libmemcached/parse.cc \
-                                      libmemcached/prefix_key.cc \
+                                      libmemcached/namespace.cc \
                                       libmemcached/purge.cc \
                                       libmemcached/quit.cc \
                                       libmemcached/response.cc \
index a787b0c288801b467e6ffe27837a154caabe69a8..f77a097325c84d0c166c5f4149c8d793c54427d5 100644 (file)
@@ -128,11 +128,11 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr,
           int err;
           socklen_t len= sizeof (err);
           (void)getsockopt(ptr->fd, SOL_SOCKET, SO_ERROR, &err, &len);
-          ptr->cached_errno= (err == 0) ? get_socket_errno() : err;
+          memcached_set_errno(*ptr, (err == 0) ? get_socket_errno() : err, MEMCACHED_AT);
         }
         else
         {
-          ptr->cached_errno= get_socket_errno();
+          memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
         }
         memcached_quit_server(ptr, true);
 
@@ -141,10 +141,9 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr,
     }
   }
 
-  ptr->cached_errno= get_socket_errno();
   memcached_quit_server(ptr, true);
 
-  return memcached_set_error(*ptr, MEMCACHED_FAILURE, MEMCACHED_AT);
+  return memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
 }
 
 memcached_return_t memcached_io_wait_for_write(memcached_server_write_instance_st ptr)
@@ -711,7 +710,7 @@ static ssize_t io_flush(memcached_server_write_instance_st ptr,
 
     if (sent_length == SOCKET_ERROR)
     {
-      ptr->cached_errno= get_socket_errno();
+      memcached_set_errno(*ptr, get_socket_errno(), MEMCACHED_AT);
 #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());
index c2c2b14ba4f37255fc027e2adb34802813627711..02e0c2b326dbfcb51400c04e8c2c17c3a36dd58e 100644 (file)
@@ -1,20 +1,67 @@
-#include "common.h"
+/*  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.
+ *
+ */
 
-memcached_return_t memcached_key_test(const char * const *keys,
+#include <libmemcached/common.h>
+
+memcached_return_t memcached_key_test(const memcached_st &memc,
+                                      const char * const *keys,
                                       const size_t *key_length,
                                       size_t number_of_keys)
 {
+  if (not memc.flags.verify_key)
+    return MEMCACHED_SUCCESS;
+
+  if (memc.flags.binary_protocol)
+    return MEMCACHED_SUCCESS;
+
   for (uint32_t x= 0; x < number_of_keys; x++)
   {
-    memcached_return_t rc;
-    rc= memcached_validate_key_length(*(key_length + x), false);
-    if (rc != MEMCACHED_SUCCESS)
+    memcached_return_t rc= memcached_validate_key_length(*(key_length + x), false);
+    if (memcached_failed(rc))
+    {
       return rc;
+    }
  
     for (size_t y= 0; y < *(key_length + x); y++)
     {
       if ((isgraph(keys[x][y])) == 0)
+      {
         return MEMCACHED_BAD_KEY_PROVIDED;
+      }
     }
   }
 
index f93f74b41169be93c343b694b4d9494c6121648b..359a4403bdbf07c2ae2e92babe8d844f5119a5e1 100644 (file)
@@ -51,7 +51,7 @@ static const memcached_st global_copy= {
     .auto_eject_hosts= false,
     .binary_protocol= false,
     .buffer_requests= false,
-    .hash_with_prefix_key= false,
+    .hash_with_namespace= false,
     .no_block= false,
     .no_reply= false,
     .randomize_replica_read= false,
@@ -74,7 +74,7 @@ static inline bool _memcached_init(memcached_st *self)
   self->flags.auto_eject_hosts= false;
   self->flags.binary_protocol= false;
   self->flags.buffer_requests= false;
-  self->flags.hash_with_prefix_key= false;
+  self->flags.hash_with_namespace= false;
   self->flags.no_block= false;
   self->flags.no_reply= false;
   self->flags.randomize_replica_read= false;
@@ -135,7 +135,7 @@ static inline bool _memcached_init(memcached_st *self)
   self->sasl.is_allocated= false;
 
   self->error_messages= NULL;
-  self->prefix_key= NULL;
+  self->_namespace= NULL;
   self->configure.initial_pool_size= 1;
   self->configure.max_pool_size= 1;
   self->configure.version= -1;
@@ -160,10 +160,10 @@ static void _free(memcached_st *ptr, bool release_st)
 
   libmemcached_free(ptr, ptr->ketama.continuum);
 
-  memcached_array_free(ptr->prefix_key);
-  ptr->prefix_key= NULL;
+  memcached_array_free(ptr->_namespace);
+  ptr->_namespace= NULL;
 
-  memcached_error_free(ptr);
+  memcached_error_free(*ptr);
 
   if (ptr->sasl.callbacks)
   {
@@ -371,8 +371,8 @@ memcached_st *memcached_clone(memcached_st *clone, const memcached_st *source)
   }
 
 
-  new_clone->prefix_key= memcached_array_clone(new_clone, source->prefix_key);
-  new_clone->configure.filename= memcached_array_clone(new_clone, source->prefix_key);
+  new_clone->_namespace= memcached_array_clone(new_clone, source->_namespace);
+  new_clone->configure.filename= memcached_array_clone(new_clone, source->_namespace);
 
 #ifdef LIBMEMCACHED_WITH_SASL_SUPPORT
   if (source->sasl.callbacks)
index 099a4b306960f26323fc3f274034b4cac81c84c3..440898e1e34ea29ab681b665f663748245465d2d 100644 (file)
@@ -98,7 +98,7 @@ struct memcached_st {
     bool auto_eject_hosts:1;
     bool binary_protocol:1;
     bool buffer_requests:1;
-    bool hash_with_prefix_key:1;
+    bool hash_with_namespace:1;
     bool no_block:1; // Don't block
     bool no_reply:1;
     bool randomize_replica_read:1;
@@ -151,7 +151,7 @@ struct memcached_st {
   memcached_callback_st *callbacks;
   struct memcached_sasl_st sasl;
   struct memcached_error_t *error_messages;
-  struct memcached_array_st *prefix_key;
+  struct memcached_array_st *_namespace;
   struct {
     uint32_t initial_pool_size;
     uint32_t max_pool_size;
index 3f1185d195dcbb5c77ade6887eaa1b41be87000d..c0a4620af9aff1b3f396eea7997fa8a80d97a3bc 100644 (file)
@@ -38,6 +38,7 @@
 #pragma once
 
 
+#include <libmemcached/util/pid.h>
 #include <libmemcached/util/flush.h>
 #include <libmemcached/util/ping.h>
 #include <libmemcached/util/pool.h>
diff --git a/libmemcached/namespace.cc b/libmemcached/namespace.cc
new file mode 100644 (file)
index 0000000..372af2a
--- /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.
+ *
+ */
+
+#include <libmemcached/common.h>
+
+memcached_return_t memcached_set_namespace(memcached_st *self, const char *key, size_t key_length)
+{
+  WATCHPOINT_ASSERT(self);
+
+  if (key and key_length == 0)
+  { 
+    WATCHPOINT_ASSERT(key_length);
+    return memcached_set_error(*self, 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(*self, 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= self->flags.verify_key;
+    self->flags.verify_key= true;
+    if (memcached_failed(memcached_key_test(*self, (const char **)&key, &key_length, 1)))
+    {
+      self->flags.verify_key= orig;
+      return memcached_set_error(*self, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT);
+    }
+    self->flags.verify_key= orig;
+
+    if ((key_length > MEMCACHED_PREFIX_KEY_MAX_SIZE -1))
+    {
+      return memcached_set_error(*self, MEMCACHED_KEY_TOO_BIG, MEMCACHED_AT);
+    }
+
+    memcached_array_free(self->_namespace);
+    self->_namespace= memcached_strcpy(self, key, key_length);
+
+    if (not self->_namespace)
+    {
+      return memcached_set_error(*self, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+    }
+  }
+  else
+  {
+    memcached_array_free(self->_namespace);
+    self->_namespace= NULL;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
diff --git a/libmemcached/namespace.h b/libmemcached/namespace.h
new file mode 100644 (file)
index 0000000..60cddd6
--- /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_LOCAL
+  memcached_return_t memcached_set_namespace(memcached_st *self, const char *str, size_t length);
+
+#ifdef __cplusplus
+}
+#endif
index 2e478dcc81d0be6289ae379cc005526d66b2e8ef..096a31119b374a3fdf2140331c0d433208b3b506 100644 (file)
 #line 36 "libmemcached/options/parser.yy"
 
 
-#include <config.h>
-
-#include <stdint.h>
-
 #include <libmemcached/common.h>
 #include <libmemcached/options.hpp>
 
@@ -89,6 +85,8 @@
 #include <libmemcached/options/symbol.h>
 #include <libmemcached/options/scanner.h>
 
+#include <iostream>
+
 #pragma GCC diagnostic ignored "-Wold-style-cast"
 
 int conf_lex(YYSTYPE* lvalp, void* scanner);
@@ -104,7 +102,7 @@ inline void config_error(Context *context, yyscan_t *scanner, const char *error)
 
 
 /* Line 189 of yacc.c  */
-#line 108 "libmemcached/options/parser.cc"
+#line 106 "libmemcached/options/parser.cc"
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
@@ -140,65 +138,66 @@ inline void config_error(Context *context, yyscan_t *scanner, const char *error)
      CONFIGURE_FILE = 264,
      EMPTY_LINE = 265,
      SERVER = 266,
-     SERVERS = 267,
-     SERVERS_OPTION = 268,
-     UNKNOWN_OPTION = 269,
-     UNKNOWN = 270,
-     BINARY_PROTOCOL = 271,
-     BUFFER_REQUESTS = 272,
-     CONNECT_TIMEOUT = 273,
-     DISTRIBUTION = 274,
-     HASH = 275,
-     HASH_WITH_NAMESPACE = 276,
-     IO_BYTES_WATERMARK = 277,
-     IO_KEY_PREFETCH = 278,
-     IO_MSG_WATERMARK = 279,
-     KETAMA_HASH = 280,
-     KETAMA_WEIGHTED = 281,
-     NOREPLY = 282,
-     NUMBER_OF_REPLICAS = 283,
-     POLL_TIMEOUT = 284,
-     RANDOMIZE_REPLICA_READ = 285,
-     RCV_TIMEOUT = 286,
-     REMOVE_FAILED_SERVERS = 287,
-     RETRY_TIMEOUT = 288,
-     SND_TIMEOUT = 289,
-     SOCKET_RECV_SIZE = 290,
-     SOCKET_SEND_SIZE = 291,
-     SORT_HOSTS = 292,
-     SUPPORT_CAS = 293,
-     USER_DATA = 294,
-     USE_UDP = 295,
-     VERIFY_KEY = 296,
-     _TCP_KEEPALIVE = 297,
-     _TCP_KEEPIDLE = 298,
-     _TCP_NODELAY = 299,
-     NAMESPACE = 300,
-     POOL_MIN = 301,
-     POOL_MAX = 302,
-     MD5 = 303,
-     CRC = 304,
-     FNV1_64 = 305,
-     FNV1A_64 = 306,
-     FNV1_32 = 307,
-     FNV1A_32 = 308,
-     HSIEH = 309,
-     MURMUR = 310,
-     JENKINS = 311,
-     CONSISTENT = 312,
-     MODULA = 313,
-     RANDOM = 314,
-     TRUE = 315,
-     FALSE = 316,
-     FLOAT = 317,
-     NUMBER = 318,
-     PORT = 319,
-     WEIGHT_START = 320,
-     IPADDRESS = 321,
-     HOSTNAME = 322,
-     STRING = 323,
-     QUOTED_STRING = 324,
-     FILE_PATH = 325
+     SOCKET = 267,
+     SERVERS = 268,
+     SERVERS_OPTION = 269,
+     UNKNOWN_OPTION = 270,
+     UNKNOWN = 271,
+     BINARY_PROTOCOL = 272,
+     BUFFER_REQUESTS = 273,
+     CONNECT_TIMEOUT = 274,
+     DISTRIBUTION = 275,
+     HASH = 276,
+     HASH_WITH_NAMESPACE = 277,
+     IO_BYTES_WATERMARK = 278,
+     IO_KEY_PREFETCH = 279,
+     IO_MSG_WATERMARK = 280,
+     KETAMA_HASH = 281,
+     KETAMA_WEIGHTED = 282,
+     NOREPLY = 283,
+     NUMBER_OF_REPLICAS = 284,
+     POLL_TIMEOUT = 285,
+     RANDOMIZE_REPLICA_READ = 286,
+     RCV_TIMEOUT = 287,
+     REMOVE_FAILED_SERVERS = 288,
+     RETRY_TIMEOUT = 289,
+     SND_TIMEOUT = 290,
+     SOCKET_RECV_SIZE = 291,
+     SOCKET_SEND_SIZE = 292,
+     SORT_HOSTS = 293,
+     SUPPORT_CAS = 294,
+     USER_DATA = 295,
+     USE_UDP = 296,
+     VERIFY_KEY = 297,
+     _TCP_KEEPALIVE = 298,
+     _TCP_KEEPIDLE = 299,
+     _TCP_NODELAY = 300,
+     NAMESPACE = 301,
+     POOL_MIN = 302,
+     POOL_MAX = 303,
+     MD5 = 304,
+     CRC = 305,
+     FNV1_64 = 306,
+     FNV1A_64 = 307,
+     FNV1_32 = 308,
+     FNV1A_32 = 309,
+     HSIEH = 310,
+     MURMUR = 311,
+     JENKINS = 312,
+     CONSISTENT = 313,
+     MODULA = 314,
+     RANDOM = 315,
+     TRUE = 316,
+     FALSE = 317,
+     FLOAT = 318,
+     NUMBER = 319,
+     PORT = 320,
+     WEIGHT_START = 321,
+     IPADDRESS = 322,
+     HOSTNAME = 323,
+     STRING = 324,
+     QUOTED_STRING = 325,
+     FILE_PATH = 326
    };
 #endif
 
@@ -215,7 +214,7 @@ inline void config_error(Context *context, yyscan_t *scanner, const char *error)
 
 
 /* Line 264 of yacc.c  */
-#line 219 "libmemcached/options/parser.cc"
+#line 218 "libmemcached/options/parser.cc"
 
 #ifdef short
 # undef short
@@ -428,22 +427,22 @@ union yyalloc
 #endif
 
 /* YYFINAL -- State number of the termination state.  */
-#define YYFINAL  69
+#define YYFINAL  71
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   73
+#define YYLAST   74
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  74
+#define YYNTOKENS  75
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  12
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  66
+#define YYNRULES  67
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  82
+#define YYNSTATES  85
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   325
+#define YYMAXUTOK   326
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -454,10 +453,10 @@ static const yytype_uint8 yytranslate[] =
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,    73,     2,     2,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,    62,     2,     2,     2,     2,     2,
+       2,     2,    74,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,    63,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    63,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,    64,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -482,8 +481,8 @@ static const yytype_uint8 yytranslate[] =
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
       35,    36,    37,    38,    39,    40,    41,    42,    43,    44,
       45,    46,    47,    48,    49,    50,    51,    52,    53,    54,
-      55,    56,    57,    58,    59,    60,    61,    64,    65,    66,
-      67,    68,    69,    70,    71,    72
+      55,    56,    57,    58,    59,    60,    61,    62,    65,    66,
+      67,    68,    69,    70,    71,    72,    73
 };
 
 #if YYDEBUG
@@ -492,45 +491,45 @@ static const yytype_uint8 yytranslate[] =
 static const yytype_uint8 yyprhs[] =
 {
        0,     0,     3,     5,     9,    11,    13,    15,    17,    19,
-      21,    23,    27,    32,    37,    40,    43,    46,    48,    51,
-      54,    59,    62,    65,    67,    69,    71,    73,    75,    77,
-      79,    81,    83,    85,    87,    89,    91,    93,    95,    97,
-      99,   101,   103,   105,   107,   109,   111,   113,   115,   117,
-     118,   120,   121,   123,   125,   127,   129,   131,   133,   135,
-     137,   139,   141,   143,   145,   147,   149
+      21,    23,    27,    32,    37,    41,    44,    47,    50,    52,
+      55,    58,    63,    66,    69,    71,    73,    75,    77,    79,
+      81,    83,    85,    87,    89,    91,    93,    95,    97,    99,
+     101,   103,   105,   107,   109,   111,   113,   115,   117,   119,
+     121,   122,   124,   125,   127,   129,   131,   133,   135,   137,
+     139,   141,   143,   145,   147,   149,   151,   153
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      75,     0,    -1,    76,    -1,    75,    73,    76,    -1,    77,
+      76,     0,    -1,    77,    -1,    76,    74,    77,    -1,    78,
       -1,     3,    -1,    10,    -1,     4,    -1,     5,    -1,     6,
-      -1,     7,    -1,     8,    73,    84,    -1,    11,    69,    81,
-      82,    -1,    11,    68,    81,    82,    -1,     9,    84,    -1,
-      46,    65,    -1,    47,    65,    -1,    78,    -1,    45,    84,
-      -1,    19,    85,    -1,    19,    85,    62,    83,    -1,    20,
-      83,    -1,    79,    65,    -1,    80,    -1,    39,    -1,    32,
-      -1,    18,    -1,    24,    -1,    22,    -1,    23,    -1,    28,
-      -1,    29,    -1,    31,    -1,    33,    -1,    34,    -1,    35,
-      -1,    36,    -1,    16,    -1,    17,    -1,    21,    -1,    27,
-      -1,    30,    -1,    37,    -1,    38,    -1,    44,    -1,    42,
-      -1,    43,    -1,    40,    -1,    41,    -1,    -1,    66,    -1,
-      -1,    67,    -1,    48,    -1,    49,    -1,    50,    -1,    51,
-      -1,    52,    -1,    53,    -1,    54,    -1,    55,    -1,    56,
-      -1,    70,    -1,    71,    -1,    57,    -1,    58,    -1,    59,
-      -1
+      -1,     7,    -1,     8,    74,    85,    -1,    11,    70,    82,
+      83,    -1,    11,    69,    82,    83,    -1,    12,    85,    83,
+      -1,     9,    85,    -1,    47,    66,    -1,    48,    66,    -1,
+      79,    -1,    46,    85,    -1,    20,    86,    -1,    20,    86,
+      63,    84,    -1,    21,    84,    -1,    80,    66,    -1,    81,
+      -1,    40,    -1,    33,    -1,    19,    -1,    25,    -1,    23,
+      -1,    24,    -1,    29,    -1,    30,    -1,    32,    -1,    34,
+      -1,    35,    -1,    36,    -1,    37,    -1,    17,    -1,    18,
+      -1,    22,    -1,    28,    -1,    31,    -1,    38,    -1,    39,
+      -1,    45,    -1,    43,    -1,    44,    -1,    41,    -1,    42,
+      -1,    -1,    67,    -1,    -1,    68,    -1,    49,    -1,    50,
+      -1,    51,    -1,    52,    -1,    53,    -1,    54,    -1,    55,
+      -1,    56,    -1,    57,    -1,    71,    -1,    72,    -1,    58,
+      -1,    59,    -1,    60,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   159,   159,   160,   164,   166,   168,   170,   175,   180,
-     184,   188,   199,   207,   215,   219,   223,   227,   231,   238,
-     245,   256,   263,   270,   277,   283,   287,   291,   295,   299,
-     303,   307,   311,   315,   319,   323,   327,   334,   338,   342,
-     346,   350,   354,   358,   362,   366,   370,   374,   378,   385,
-     386,   391,   392,   397,   401,   405,   409,   413,   417,   421,
-     425,   429,   436,   440,   448,   452,   456
+       0,   158,   158,   159,   163,   165,   167,   169,   174,   179,
+     183,   187,   198,   206,   214,   221,   225,   229,   233,   237,
+     244,   251,   262,   269,   276,   283,   289,   293,   297,   301,
+     305,   309,   313,   317,   321,   325,   329,   333,   340,   344,
+     348,   352,   356,   360,   364,   368,   372,   376,   380,   384,
+     391,   392,   397,   398,   403,   407,   411,   415,   419,   423,
+     427,   431,   435,   442,   446,   457,   461,   465
 };
 #endif
 
@@ -541,7 +540,7 @@ static const char *const yytname[] =
 {
   "$end", "error", "$undefined", "COMMENT", "END", "ERROR", "RESET",
   "PARSER_DEBUG", "INCLUDE", "CONFIGURE_FILE", "EMPTY_LINE", "SERVER",
-  "SERVERS", "SERVERS_OPTION", "UNKNOWN_OPTION", "UNKNOWN",
+  "SOCKET", "SERVERS", "SERVERS_OPTION", "UNKNOWN_OPTION", "UNKNOWN",
   "BINARY_PROTOCOL", "BUFFER_REQUESTS", "CONNECT_TIMEOUT", "DISTRIBUTION",
   "HASH", "HASH_WITH_NAMESPACE", "IO_BYTES_WATERMARK", "IO_KEY_PREFETCH",
   "IO_MSG_WATERMARK", "KETAMA_HASH", "KETAMA_WEIGHTED", "NOREPLY",
@@ -571,33 +570,33 @@ static const yytype_uint16 yytoknum[] =
      285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
      295,   296,   297,   298,   299,   300,   301,   302,   303,   304,
      305,   306,   307,   308,   309,   310,   311,   312,   313,   314,
-     315,   316,    44,    61,   317,   318,   319,   320,   321,   322,
-     323,   324,   325,    32
+     315,   316,   317,    44,    61,   318,   319,   320,   321,   322,
+     323,   324,   325,   326,    32
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    74,    75,    75,    76,    76,    76,    76,    76,    76,
-      76,    76,    77,    77,    77,    77,    77,    77,    78,    78,
-      78,    78,    78,    78,    78,    79,    79,    79,    79,    79,
-      79,    79,    79,    79,    79,    79,    79,    80,    80,    80,
-      80,    80,    80,    80,    80,    80,    80,    80,    80,    81,
-      81,    82,    82,    83,    83,    83,    83,    83,    83,    83,
-      83,    83,    84,    84,    85,    85,    85
+       0,    75,    76,    76,    77,    77,    77,    77,    77,    77,
+      77,    77,    78,    78,    78,    78,    78,    78,    78,    79,
+      79,    79,    79,    79,    79,    79,    80,    80,    80,    80,
+      80,    80,    80,    80,    80,    80,    80,    80,    81,    81,
+      81,    81,    81,    81,    81,    81,    81,    81,    81,    81,
+      82,    82,    83,    83,    84,    84,    84,    84,    84,    84,
+      84,    84,    84,    85,    85,    86,    86,    86
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const yytype_uint8 yyr2[] =
 {
        0,     2,     1,     3,     1,     1,     1,     1,     1,     1,
-       1,     3,     4,     4,     2,     2,     2,     1,     2,     2,
-       4,     2,     2,     1,     1,     1,     1,     1,     1,     1,
+       1,     3,     4,     4,     3,     2,     2,     2,     1,     2,
+       2,     4,     2,     2,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     1,     0,
-       1,     0,     1,     1,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1
+       0,     1,     0,     1,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -606,21 +605,21 @@ static const yytype_uint8 yyr2[] =
 static const yytype_uint8 yydefact[] =
 {
        0,     5,     7,     8,     9,    10,     0,     0,     6,     0,
-      37,    38,    26,     0,     0,    39,    28,    29,    27,    40,
-      30,    31,    41,    32,    25,    33,    34,    35,    36,    42,
-      43,    24,    47,    48,    45,    46,    44,     0,     0,     0,
-       0,     2,     4,    17,     0,    23,     0,    62,    63,    14,
-      49,    49,    64,    65,    66,    19,    53,    54,    55,    56,
-      57,    58,    59,    60,    61,    21,    18,    15,    16,     1,
-       0,    22,    11,    50,    51,    51,     0,     3,    52,    13,
-      12,    20
+       0,    38,    39,    27,     0,     0,    40,    29,    30,    28,
+      41,    31,    32,    42,    33,    26,    34,    35,    36,    37,
+      43,    44,    25,    48,    49,    46,    47,    45,     0,     0,
+       0,     0,     2,     4,    18,     0,    24,     0,    63,    64,
+      15,    50,    50,    52,    65,    66,    67,    20,    54,    55,
+      56,    57,    58,    59,    60,    61,    62,    22,    19,    16,
+      17,     1,     0,    23,    11,    51,    52,    52,    53,    14,
+       0,     3,    13,    12,    21
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,    40,    41,    42,    43,    44,    45,    74,    79,    65,
-      49,    55
+      -1,    41,    42,    43,    44,    45,    46,    76,    79,    67,
+      50,    57
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
@@ -628,22 +627,22 @@ static const yytype_int8 yydefgoto[] =
 #define YYPACT_NINF -61
 static const yytype_int8 yypact[] =
 {
-      -2,   -61,   -61,   -61,   -61,   -61,   -60,   -23,   -61,   -45,
-     -61,   -61,   -61,   -47,     8,   -61,   -61,   -61,   -61,   -61,
+      -2,   -61,   -61,   -61,   -61,   -61,   -60,   -24,   -61,   -20,
+     -24,   -61,   -61,   -61,   -47,    13,   -61,   -61,   -61,   -61,
      -61,   -61,   -61,   -61,   -61,   -61,   -61,   -61,   -61,   -61,
-     -61,   -61,   -61,   -61,   -61,   -61,   -61,   -23,   -16,   -15,
-       0,   -61,   -61,   -61,   -14,   -61,   -23,   -61,   -61,   -61,
-     -13,   -13,   -61,   -61,   -61,   -10,   -61,   -61,   -61,   -61,
+     -61,   -61,   -61,   -61,   -61,   -61,   -61,   -61,   -24,   -41,
+     -15,     0,   -61,   -61,   -61,   -11,   -61,   -24,   -61,   -61,
+     -61,   -10,   -10,   -12,   -61,   -61,   -61,    -5,   -61,   -61,
      -61,   -61,   -61,   -61,   -61,   -61,   -61,   -61,   -61,   -61,
-      -2,   -61,   -61,   -61,    -1,    -1,     8,   -61,   -61,   -61,
-     -61,   -61
+     -61,   -61,    -2,   -61,   -61,   -61,   -12,   -12,   -61,   -61,
+      13,   -61,   -61,   -61,   -61
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -61,   -61,    -5,   -61,   -61,   -61,   -61,     3,    -8,    -7,
-       9,   -61
+     -61,   -61,   -13,   -61,   -61,   -61,   -61,     8,   -23,    -9,
+      14,   -61
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -653,26 +652,26 @@ static const yytype_int8 yypgoto[] =
 #define YYTABLE_NINF -1
 static const yytype_uint8 yytable[] =
 {
-      69,     1,     2,     3,     4,     5,     6,     7,     8,     9,
-      52,    53,    54,    46,    10,    11,    12,    13,    14,    15,
-      16,    17,    18,    50,    51,    19,    20,    21,    22,    23,
+      71,     1,     2,     3,     4,     5,     6,     7,     8,     9,
+      10,    54,    55,    56,    47,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    53,    69,    20,    21,    22,    23,
       24,    25,    26,    27,    28,    29,    30,    31,    32,    33,
-      34,    35,    36,    37,    38,    39,    66,    47,    48,    67,
-      68,    71,    76,    73,    75,    72,    56,    57,    58,    59,
-      60,    61,    62,    63,    64,    77,    78,    80,     0,    81,
-       0,     0,     0,    70
+      34,    35,    36,    37,    38,    39,    40,    48,    49,    51,
+      52,    70,    68,    82,    83,    73,    78,    75,    80,    81,
+      77,    74,    58,    59,    60,    61,    62,    63,    64,    65,
+      66,    84,     0,     0,    72
 };
 
 static const yytype_int8 yycheck[] =
 {
        0,     3,     4,     5,     6,     7,     8,     9,    10,    11,
-      57,    58,    59,    73,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    68,    69,    27,    28,    29,    30,    31,
+      12,    58,    59,    60,    74,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    10,    66,    28,    29,    30,    31,
       32,    33,    34,    35,    36,    37,    38,    39,    40,    41,
-      42,    43,    44,    45,    46,    47,    37,    70,    71,    65,
-      65,    65,    62,    66,    51,    46,    48,    49,    50,    51,
-      52,    53,    54,    55,    56,    70,    67,    75,    -1,    76,
-      -1,    -1,    -1,    73
+      42,    43,    44,    45,    46,    47,    48,    71,    72,    69,
+      70,    66,    38,    76,    77,    66,    68,    67,    63,    72,
+      52,    47,    49,    50,    51,    52,    53,    54,    55,    56,
+      57,    80,    -1,    -1,    74
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -680,14 +679,14 @@ static const yytype_int8 yycheck[] =
 static const yytype_uint8 yystos[] =
 {
        0,     3,     4,     5,     6,     7,     8,     9,    10,    11,
-      16,    17,    18,    19,    20,    21,    22,    23,    24,    27,
+      12,    17,    18,    19,    20,    21,    22,    23,    24,    25,
       28,    29,    30,    31,    32,    33,    34,    35,    36,    37,
       38,    39,    40,    41,    42,    43,    44,    45,    46,    47,
-      75,    76,    77,    78,    79,    80,    73,    70,    71,    84,
-      68,    69,    57,    58,    59,    85,    48,    49,    50,    51,
-      52,    53,    54,    55,    56,    83,    84,    65,    65,     0,
-      73,    65,    84,    66,    81,    81,    62,    76,    67,    82,
-      82,    83
+      48,    76,    77,    78,    79,    80,    81,    74,    71,    72,
+      85,    69,    70,    85,    58,    59,    60,    86,    49,    50,
+      51,    52,    53,    54,    55,    56,    57,    84,    85,    66,
+      66,     0,    74,    66,    85,    67,    82,    82,    68,    83,
+      63,    77,    83,    83,    84
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -1522,28 +1521,28 @@ yyreduce:
         case 4:
 
 /* Line 1464 of yacc.c  */
-#line 165 "libmemcached/options/parser.yy"
+#line 164 "libmemcached/options/parser.yy"
     { ;}
     break;
 
   case 5:
 
 /* Line 1464 of yacc.c  */
-#line 167 "libmemcached/options/parser.yy"
+#line 166 "libmemcached/options/parser.yy"
     { ;}
     break;
 
   case 6:
 
 /* Line 1464 of yacc.c  */
-#line 169 "libmemcached/options/parser.yy"
+#line 168 "libmemcached/options/parser.yy"
     { ;}
     break;
 
   case 7:
 
 /* Line 1464 of yacc.c  */
-#line 171 "libmemcached/options/parser.yy"
+#line 170 "libmemcached/options/parser.yy"
     {
             context->set_end();
             YYACCEPT;
@@ -1553,7 +1552,7 @@ yyreduce:
   case 8:
 
 /* Line 1464 of yacc.c  */
-#line 176 "libmemcached/options/parser.yy"
+#line 175 "libmemcached/options/parser.yy"
     {
             context->rc= MEMCACHED_PARSE_USER_ERROR;
             parser_abort(context, NULL);
@@ -1563,7 +1562,7 @@ yyreduce:
   case 9:
 
 /* Line 1464 of yacc.c  */
-#line 181 "libmemcached/options/parser.yy"
+#line 180 "libmemcached/options/parser.yy"
     {
             memcached_reset(context->memc);
           ;}
@@ -1572,7 +1571,7 @@ yyreduce:
   case 10:
 
 /* Line 1464 of yacc.c  */
-#line 185 "libmemcached/options/parser.yy"
+#line 184 "libmemcached/options/parser.yy"
     {
             yydebug= 1;
           ;}
@@ -1581,7 +1580,7 @@ yyreduce:
   case 11:
 
 /* Line 1464 of yacc.c  */
-#line 189 "libmemcached/options/parser.yy"
+#line 188 "libmemcached/options/parser.yy"
     {
             if ((context->rc= memcached_parse_configure_file(*context->memc, (yyvsp[(3) - (3)].string).c_str, (yyvsp[(3) - (3)].string).size)) != MEMCACHED_SUCCESS)
             {
@@ -1593,7 +1592,7 @@ yyreduce:
   case 12:
 
 /* Line 1464 of yacc.c  */
-#line 200 "libmemcached/options/parser.yy"
+#line 199 "libmemcached/options/parser.yy"
     {
             if (memcached_failed(context->rc= memcached_server_add_with_weight(context->memc, (yyvsp[(2) - (4)].server).c_str, (yyvsp[(3) - (4)].number), (yyvsp[(4) - (4)].number))))
             {
@@ -1606,7 +1605,7 @@ yyreduce:
   case 13:
 
 /* Line 1464 of yacc.c  */
-#line 208 "libmemcached/options/parser.yy"
+#line 207 "libmemcached/options/parser.yy"
     {
             if (memcached_failed(context->rc= memcached_server_add_with_weight(context->memc, (yyvsp[(2) - (4)].server).c_str, (yyvsp[(3) - (4)].number), (yyvsp[(4) - (4)].number))))
             {
@@ -1619,46 +1618,58 @@ yyreduce:
   case 14:
 
 /* Line 1464 of yacc.c  */
-#line 216 "libmemcached/options/parser.yy"
+#line 215 "libmemcached/options/parser.yy"
     {
-            memcached_set_configuration_file(context->memc, (yyvsp[(2) - (2)].string).c_str, (yyvsp[(2) - (2)].string).size);
+            if (memcached_failed(context->rc= memcached_server_add_unix_socket_with_weight(context->memc, (yyvsp[(2) - (3)].string).c_str, (yyvsp[(3) - (3)].number))))
+            {
+              parser_abort(context, NULL);
+            }
           ;}
     break;
 
   case 15:
 
 /* Line 1464 of yacc.c  */
-#line 220 "libmemcached/options/parser.yy"
+#line 222 "libmemcached/options/parser.yy"
     {
-            context->memc->configure.initial_pool_size= (yyvsp[(2) - (2)].number);
+            memcached_set_configuration_file(context->memc, (yyvsp[(2) - (2)].string).c_str, (yyvsp[(2) - (2)].string).size);
           ;}
     break;
 
   case 16:
 
 /* Line 1464 of yacc.c  */
-#line 224 "libmemcached/options/parser.yy"
+#line 226 "libmemcached/options/parser.yy"
+    {
+            context->memc->configure.initial_pool_size= (yyvsp[(2) - (2)].number);
+          ;}
+    break;
+
+  case 17:
+
+/* Line 1464 of yacc.c  */
+#line 230 "libmemcached/options/parser.yy"
     {
             context->memc->configure.max_pool_size= (yyvsp[(2) - (2)].number);
           ;}
     break;
 
-  case 18:
+  case 19:
 
 /* Line 1464 of yacc.c  */
-#line 232 "libmemcached/options/parser.yy"
+#line 238 "libmemcached/options/parser.yy"
     {
-            if ((context->rc= memcached_set_prefix_key(context->memc, (yyvsp[(2) - (2)].string).c_str, (yyvsp[(2) - (2)].string).size)) != MEMCACHED_SUCCESS)
+            if ((context->rc= memcached_set_namespace(context->memc, (yyvsp[(2) - (2)].string).c_str, (yyvsp[(2) - (2)].string).size)) != MEMCACHED_SUCCESS)
             {
               parser_abort(context, NULL);;
             }
           ;}
     break;
 
-  case 19:
+  case 20:
 
 /* Line 1464 of yacc.c  */
-#line 239 "libmemcached/options/parser.yy"
+#line 245 "libmemcached/options/parser.yy"
     {
             if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, (yyvsp[(2) - (2)].distribution))) != MEMCACHED_SUCCESS)
             {
@@ -1667,10 +1678,10 @@ yyreduce:
           ;}
     break;
 
-  case 20:
+  case 21:
 
 /* Line 1464 of yacc.c  */
-#line 246 "libmemcached/options/parser.yy"
+#line 252 "libmemcached/options/parser.yy"
     {
             if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_DISTRIBUTION, (yyvsp[(2) - (4)].distribution))) != MEMCACHED_SUCCESS)
             {
@@ -1683,10 +1694,10 @@ yyreduce:
           ;}
     break;
 
-  case 21:
+  case 22:
 
 /* Line 1464 of yacc.c  */
-#line 257 "libmemcached/options/parser.yy"
+#line 263 "libmemcached/options/parser.yy"
     {
             if ((context->rc= memcached_behavior_set(context->memc, MEMCACHED_BEHAVIOR_HASH, (yyvsp[(2) - (2)].hash))) != MEMCACHED_SUCCESS)
             {
@@ -1695,10 +1706,10 @@ yyreduce:
           ;}
     break;
 
-  case 22:
+  case 23:
 
 /* Line 1464 of yacc.c  */
-#line 264 "libmemcached/options/parser.yy"
+#line 270 "libmemcached/options/parser.yy"
     {
             if ((context->rc= memcached_behavior_set(context->memc, (yyvsp[(1) - (2)].behavior), (yyvsp[(2) - (2)].number))) != MEMCACHED_SUCCESS)
             {
@@ -1707,10 +1718,10 @@ yyreduce:
           ;}
     break;
 
-  case 23:
+  case 24:
 
 /* Line 1464 of yacc.c  */
-#line 271 "libmemcached/options/parser.yy"
+#line 277 "libmemcached/options/parser.yy"
     {
             if ((context->rc= memcached_behavior_set(context->memc, (yyvsp[(1) - (1)].behavior), true)) != MEMCACHED_SUCCESS)
             {
@@ -1719,380 +1730,383 @@ yyreduce:
           ;}
     break;
 
-  case 24:
+  case 25:
 
 /* Line 1464 of yacc.c  */
-#line 278 "libmemcached/options/parser.yy"
+#line 284 "libmemcached/options/parser.yy"
     {
           ;}
     break;
 
-  case 25:
+  case 26:
 
 /* Line 1464 of yacc.c  */
-#line 284 "libmemcached/options/parser.yy"
+#line 290 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_REMOVE_FAILED_SERVERS;
           ;}
     break;
 
-  case 26:
+  case 27:
 
 /* Line 1464 of yacc.c  */
-#line 288 "libmemcached/options/parser.yy"
+#line 294 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT;
           ;}
     break;
 
-  case 27:
+  case 28:
 
 /* Line 1464 of yacc.c  */
-#line 292 "libmemcached/options/parser.yy"
+#line 298 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK;
           ;}
     break;
 
-  case 28:
+  case 29:
 
 /* Line 1464 of yacc.c  */
-#line 296 "libmemcached/options/parser.yy"
+#line 302 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK;
           ;}
     break;
 
-  case 29:
+  case 30:
 
 /* Line 1464 of yacc.c  */
-#line 300 "libmemcached/options/parser.yy"
+#line 306 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH;
           ;}
     break;
 
-  case 30:
+  case 31:
 
 /* Line 1464 of yacc.c  */
-#line 304 "libmemcached/options/parser.yy"
+#line 310 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS;
           ;}
     break;
 
-  case 31:
+  case 32:
 
 /* Line 1464 of yacc.c  */
-#line 308 "libmemcached/options/parser.yy"
+#line 314 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_POLL_TIMEOUT;
           ;}
     break;
 
-  case 32:
+  case 33:
 
 /* Line 1464 of yacc.c  */
-#line 312 "libmemcached/options/parser.yy"
+#line 318 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_RCV_TIMEOUT;
           ;}
     break;
 
-  case 33:
+  case 34:
 
 /* Line 1464 of yacc.c  */
-#line 316 "libmemcached/options/parser.yy"
+#line 322 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_RETRY_TIMEOUT;
           ;}
     break;
 
-  case 34:
+  case 35:
 
 /* Line 1464 of yacc.c  */
-#line 320 "libmemcached/options/parser.yy"
+#line 326 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_SND_TIMEOUT;
           ;}
     break;
 
-  case 35:
+  case 36:
 
 /* Line 1464 of yacc.c  */
-#line 324 "libmemcached/options/parser.yy"
+#line 330 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE;
           ;}
     break;
 
-  case 36:
+  case 37:
 
 /* Line 1464 of yacc.c  */
-#line 328 "libmemcached/options/parser.yy"
+#line 334 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE;
           ;}
     break;
 
-  case 37:
+  case 38:
 
 /* Line 1464 of yacc.c  */
-#line 335 "libmemcached/options/parser.yy"
+#line 341 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_BINARY_PROTOCOL;
           ;}
     break;
 
-  case 38:
+  case 39:
 
 /* Line 1464 of yacc.c  */
-#line 339 "libmemcached/options/parser.yy"
+#line 345 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_BUFFER_REQUESTS;
           ;}
     break;
 
-  case 39:
+  case 40:
 
 /* Line 1464 of yacc.c  */
-#line 343 "libmemcached/options/parser.yy"
+#line 349 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY;
           ;}
     break;
 
-  case 40:
+  case 41:
 
 /* Line 1464 of yacc.c  */
-#line 347 "libmemcached/options/parser.yy"
+#line 353 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_NOREPLY;
           ;}
     break;
 
-  case 41:
+  case 42:
 
 /* Line 1464 of yacc.c  */
-#line 351 "libmemcached/options/parser.yy"
+#line 357 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ;
           ;}
     break;
 
-  case 42:
+  case 43:
 
 /* Line 1464 of yacc.c  */
-#line 355 "libmemcached/options/parser.yy"
+#line 361 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_SORT_HOSTS;
           ;}
     break;
 
-  case 43:
+  case 44:
 
 /* Line 1464 of yacc.c  */
-#line 359 "libmemcached/options/parser.yy"
+#line 365 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_SUPPORT_CAS;
           ;}
     break;
 
-  case 44:
+  case 45:
 
 /* Line 1464 of yacc.c  */
-#line 363 "libmemcached/options/parser.yy"
+#line 369 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_TCP_NODELAY;
           ;}
     break;
 
-  case 45:
+  case 46:
 
 /* Line 1464 of yacc.c  */
-#line 367 "libmemcached/options/parser.yy"
+#line 373 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_TCP_KEEPALIVE;
           ;}
     break;
 
-  case 46:
+  case 47:
 
 /* Line 1464 of yacc.c  */
-#line 371 "libmemcached/options/parser.yy"
+#line 377 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_TCP_KEEPIDLE;
           ;}
     break;
 
-  case 47:
+  case 48:
 
 /* Line 1464 of yacc.c  */
-#line 375 "libmemcached/options/parser.yy"
+#line 381 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_USE_UDP;
           ;}
     break;
 
-  case 48:
+  case 49:
 
 /* Line 1464 of yacc.c  */
-#line 379 "libmemcached/options/parser.yy"
+#line 385 "libmemcached/options/parser.yy"
     {
             (yyval.behavior)= MEMCACHED_BEHAVIOR_VERIFY_KEY;
           ;}
     break;
 
-  case 49:
+  case 50:
 
 /* Line 1464 of yacc.c  */
-#line 385 "libmemcached/options/parser.yy"
+#line 391 "libmemcached/options/parser.yy"
     { (yyval.number)= MEMCACHED_DEFAULT_PORT;;}
     break;
 
-  case 50:
+  case 51:
 
 /* Line 1464 of yacc.c  */
-#line 387 "libmemcached/options/parser.yy"
+#line 393 "libmemcached/options/parser.yy"
     { ;}
     break;
 
-  case 51:
+  case 52:
 
 /* Line 1464 of yacc.c  */
-#line 391 "libmemcached/options/parser.yy"
+#line 397 "libmemcached/options/parser.yy"
     { (yyval.number)= 1; ;}
     break;
 
-  case 52:
+  case 53:
 
 /* Line 1464 of yacc.c  */
-#line 393 "libmemcached/options/parser.yy"
+#line 399 "libmemcached/options/parser.yy"
     { ;}
     break;
 
-  case 53:
+  case 54:
 
 /* Line 1464 of yacc.c  */
-#line 398 "libmemcached/options/parser.yy"
+#line 404 "libmemcached/options/parser.yy"
     {
             (yyval.hash)= MEMCACHED_HASH_MD5;
           ;}
     break;
 
-  case 54:
+  case 55:
 
 /* Line 1464 of yacc.c  */
-#line 402 "libmemcached/options/parser.yy"
+#line 408 "libmemcached/options/parser.yy"
     {
             (yyval.hash)= MEMCACHED_HASH_CRC;
           ;}
     break;
 
-  case 55:
+  case 56:
 
 /* Line 1464 of yacc.c  */
-#line 406 "libmemcached/options/parser.yy"
+#line 412 "libmemcached/options/parser.yy"
     {
             (yyval.hash)= MEMCACHED_HASH_FNV1_64;
           ;}
     break;
 
-  case 56:
+  case 57:
 
 /* Line 1464 of yacc.c  */
-#line 410 "libmemcached/options/parser.yy"
+#line 416 "libmemcached/options/parser.yy"
     {
             (yyval.hash)= MEMCACHED_HASH_FNV1A_64;
           ;}
     break;
 
-  case 57:
+  case 58:
 
 /* Line 1464 of yacc.c  */
-#line 414 "libmemcached/options/parser.yy"
+#line 420 "libmemcached/options/parser.yy"
     {
             (yyval.hash)= MEMCACHED_HASH_FNV1_32;
           ;}
     break;
 
-  case 58:
+  case 59:
 
 /* Line 1464 of yacc.c  */
-#line 418 "libmemcached/options/parser.yy"
+#line 424 "libmemcached/options/parser.yy"
     {
             (yyval.hash)= MEMCACHED_HASH_FNV1A_32;
           ;}
     break;
 
-  case 59:
+  case 60:
 
 /* Line 1464 of yacc.c  */
-#line 422 "libmemcached/options/parser.yy"
+#line 428 "libmemcached/options/parser.yy"
     {
             (yyval.hash)= MEMCACHED_HASH_HSIEH;
           ;}
     break;
 
-  case 60:
+  case 61:
 
 /* Line 1464 of yacc.c  */
-#line 426 "libmemcached/options/parser.yy"
+#line 432 "libmemcached/options/parser.yy"
     {
             (yyval.hash)= MEMCACHED_HASH_MURMUR;
           ;}
     break;
 
-  case 61:
+  case 62:
 
 /* Line 1464 of yacc.c  */
-#line 430 "libmemcached/options/parser.yy"
+#line 436 "libmemcached/options/parser.yy"
     {
             (yyval.hash)= MEMCACHED_HASH_JENKINS;
           ;}
     break;
 
-  case 62:
+  case 63:
 
 /* Line 1464 of yacc.c  */
-#line 437 "libmemcached/options/parser.yy"
+#line 443 "libmemcached/options/parser.yy"
     {
             (yyval.string)= (yyvsp[(1) - (1)].string);
           ;}
     break;
 
-  case 63:
+  case 64:
 
 /* Line 1464 of yacc.c  */
-#line 441 "libmemcached/options/parser.yy"
+#line 447 "libmemcached/options/parser.yy"
     {
+            (yyval.string)= (yyvsp[(1) - (1)].string);
+            #if 0
             (yyval.string).c_str= (yyvsp[(1) - (1)].string).c_str +1; // +1 to move use passed the initial quote
             (yyval.string).size= (yyvsp[(1) - (1)].string).size -2; // -2 removes the begin and end quote
+            #endif
           ;}
     break;
 
-  case 64:
+  case 65:
 
 /* Line 1464 of yacc.c  */
-#line 449 "libmemcached/options/parser.yy"
+#line 458 "libmemcached/options/parser.yy"
     {
             (yyval.distribution)= MEMCACHED_DISTRIBUTION_CONSISTENT;
           ;}
     break;
 
-  case 65:
+  case 66:
 
 /* Line 1464 of yacc.c  */
-#line 453 "libmemcached/options/parser.yy"
+#line 462 "libmemcached/options/parser.yy"
     {
             (yyval.distribution)= MEMCACHED_DISTRIBUTION_MODULA;
           ;}
     break;
 
-  case 66:
+  case 67:
 
 /* Line 1464 of yacc.c  */
-#line 457 "libmemcached/options/parser.yy"
+#line 466 "libmemcached/options/parser.yy"
     {
             (yyval.distribution)= MEMCACHED_DISTRIBUTION_RANDOM;
           ;}
@@ -2101,7 +2115,7 @@ yyreduce:
 
 
 /* Line 1464 of yacc.c  */
-#line 2105 "libmemcached/options/parser.cc"
+#line 2119 "libmemcached/options/parser.cc"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2313,7 +2327,7 @@ yyreturn:
 
 
 /* Line 1684 of yacc.c  */
-#line 462 "libmemcached/options/parser.yy"
+#line 471 "libmemcached/options/parser.yy"
  
 
 void Context::start() 
index 1f305e5c464510763e56fb00f6a777f0ed3fe7a8..16657d2457f1ca39c8257cbda2d5c44305253eba 100644 (file)
      CONFIGURE_FILE = 264,
      EMPTY_LINE = 265,
      SERVER = 266,
-     SERVERS = 267,
-     SERVERS_OPTION = 268,
-     UNKNOWN_OPTION = 269,
-     UNKNOWN = 270,
-     BINARY_PROTOCOL = 271,
-     BUFFER_REQUESTS = 272,
-     CONNECT_TIMEOUT = 273,
-     DISTRIBUTION = 274,
-     HASH = 275,
-     HASH_WITH_NAMESPACE = 276,
-     IO_BYTES_WATERMARK = 277,
-     IO_KEY_PREFETCH = 278,
-     IO_MSG_WATERMARK = 279,
-     KETAMA_HASH = 280,
-     KETAMA_WEIGHTED = 281,
-     NOREPLY = 282,
-     NUMBER_OF_REPLICAS = 283,
-     POLL_TIMEOUT = 284,
-     RANDOMIZE_REPLICA_READ = 285,
-     RCV_TIMEOUT = 286,
-     REMOVE_FAILED_SERVERS = 287,
-     RETRY_TIMEOUT = 288,
-     SND_TIMEOUT = 289,
-     SOCKET_RECV_SIZE = 290,
-     SOCKET_SEND_SIZE = 291,
-     SORT_HOSTS = 292,
-     SUPPORT_CAS = 293,
-     USER_DATA = 294,
-     USE_UDP = 295,
-     VERIFY_KEY = 296,
-     _TCP_KEEPALIVE = 297,
-     _TCP_KEEPIDLE = 298,
-     _TCP_NODELAY = 299,
-     NAMESPACE = 300,
-     POOL_MIN = 301,
-     POOL_MAX = 302,
-     MD5 = 303,
-     CRC = 304,
-     FNV1_64 = 305,
-     FNV1A_64 = 306,
-     FNV1_32 = 307,
-     FNV1A_32 = 308,
-     HSIEH = 309,
-     MURMUR = 310,
-     JENKINS = 311,
-     CONSISTENT = 312,
-     MODULA = 313,
-     RANDOM = 314,
-     TRUE = 315,
-     FALSE = 316,
-     FLOAT = 317,
-     NUMBER = 318,
-     PORT = 319,
-     WEIGHT_START = 320,
-     IPADDRESS = 321,
-     HOSTNAME = 322,
-     STRING = 323,
-     QUOTED_STRING = 324,
-     FILE_PATH = 325
+     SOCKET = 267,
+     SERVERS = 268,
+     SERVERS_OPTION = 269,
+     UNKNOWN_OPTION = 270,
+     UNKNOWN = 271,
+     BINARY_PROTOCOL = 272,
+     BUFFER_REQUESTS = 273,
+     CONNECT_TIMEOUT = 274,
+     DISTRIBUTION = 275,
+     HASH = 276,
+     HASH_WITH_NAMESPACE = 277,
+     IO_BYTES_WATERMARK = 278,
+     IO_KEY_PREFETCH = 279,
+     IO_MSG_WATERMARK = 280,
+     KETAMA_HASH = 281,
+     KETAMA_WEIGHTED = 282,
+     NOREPLY = 283,
+     NUMBER_OF_REPLICAS = 284,
+     POLL_TIMEOUT = 285,
+     RANDOMIZE_REPLICA_READ = 286,
+     RCV_TIMEOUT = 287,
+     REMOVE_FAILED_SERVERS = 288,
+     RETRY_TIMEOUT = 289,
+     SND_TIMEOUT = 290,
+     SOCKET_RECV_SIZE = 291,
+     SOCKET_SEND_SIZE = 292,
+     SORT_HOSTS = 293,
+     SUPPORT_CAS = 294,
+     USER_DATA = 295,
+     USE_UDP = 296,
+     VERIFY_KEY = 297,
+     _TCP_KEEPALIVE = 298,
+     _TCP_KEEPIDLE = 299,
+     _TCP_NODELAY = 300,
+     NAMESPACE = 301,
+     POOL_MIN = 302,
+     POOL_MAX = 303,
+     MD5 = 304,
+     CRC = 305,
+     FNV1_64 = 306,
+     FNV1A_64 = 307,
+     FNV1_32 = 308,
+     FNV1A_32 = 309,
+     HSIEH = 310,
+     MURMUR = 311,
+     JENKINS = 312,
+     CONSISTENT = 313,
+     MODULA = 314,
+     RANDOM = 315,
+     TRUE = 316,
+     FALSE = 317,
+     FLOAT = 318,
+     NUMBER = 319,
+     PORT = 320,
+     WEIGHT_START = 321,
+     IPADDRESS = 322,
+     HOSTNAME = 323,
+     STRING = 324,
+     QUOTED_STRING = 325,
+     FILE_PATH = 326
    };
 #endif
 
index fd5a0cb98ae53aa4f3fe4ff38ed69d1140285805..db2e446521f4df2e6cb72e4004c977a5939b701c 100644 (file)
@@ -449,8 +449,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
        yyg->yy_c_buf_p = yy_cp;
 
 /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
-#define YY_NUM_RULES 64
-#define YY_END_OF_BUFFER 65
+#define YY_NUM_RULES 65
+#define YY_END_OF_BUFFER 66
 /* This struct is not used in this scanner,
    but its presence is necessary. */
 struct yy_trans_info
@@ -458,65 +458,65 @@ struct yy_trans_info
        flex_int32_t yy_verify;
        flex_int32_t yy_nxt;
        };
-static yyconst flex_int16_t yy_accept[514] =
+static yyconst flex_int16_t yy_accept[521] =
     {   0,
-        0,    0,   65,   63,    5,    5,    1,   63,   63,   63,
-        2,   63,   63,   63,   63,   63,   63,   63,   63,   63,
-       63,   63,   63,   63,   63,    0,   62,   47,    0,    0,
-        0,    2,    3,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   66,   64,    5,    5,    1,   64,   64,   64,
+        2,   64,   64,   64,   64,   64,   64,   64,   64,   64,
+       64,   64,   64,   64,   64,   64,    0,   63,    0,   48,
+        0,    0,    0,    2,    3,    0,    0,    0,    0,    0,
         0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    6,   47,   47,   47,   47,   47,   47,   47,   47,
-       47,   47,   47,   47,   47,    4,   61,   61,    2,    3,
-       61,   52,   61,   43,   61,   61,   61,   61,   61,   61,
-       51,   61,   61,   61,   61,   61,   61,   47,   47,   47,
-       47,   47,   47,   47,   47,   47,   47,   47,   47,   47,
-
-       47,   47,   47,   47,   47,   47,   47,    4,    0,   61,
-        2,    3,   61,   61,   61,   61,   61,   61,   61,   61,
-       61,   61,   61,   61,   61,   45,   47,   47,   47,   47,
-       47,    0,   47,   47,   47,   47,   47,   47,   47,   47,
-       47,   47,   47,   47,   47,   47,   47,   47,   47,    4,
-       61,   61,    3,   61,   41,   44,   46,   61,    0,   57,
-       61,   61,   61,   61,   61,   40,   61,   47,   47,   47,
-       47,   47,   47,    0,    0,    0,   47,   47,   47,   47,
-       47,   47,    0,   47,   47,   47,    0,   47,   47,   47,
-        0,    0,   47,   47,    4,    0,   61,    3,   61,    0,
-
-       61,   61,   61,   61,   49,   58,   50,   61,   47,   47,
-       47,   47,   47,    0,   14,    0,    0,    0,   47,   47,
-       47,    0,    0,   47,    0,   47,   47,   47,    0,   47,
-        0,   47,    0,    0,    0,    0,   47,    4,   60,   61,
-       61,   61,   61,   55,   53,   39,   59,   42,   47,   47,
-       47,   47,   47,    0,    0,    0,    0,   47,   47,   47,
-        0,    0,   47,    0,   47,    0,   47,    0,   47,    0,
-       47,    0,    0,    0,    0,   47,   60,   61,   56,   54,
-        0,    0,   47,   47,   47,    0,    0,    0,    0,   47,
-       18,    0,    0,    0,    0,   47,    0,    0,    0,    7,
-
-        0,    0,    0,   47,    0,    0,   33,    0,    0,   60,
-       61,    0,    0,   47,    0,   47,    0,    0,    0,    0,
-       47,    0,    0,    0,    0,   47,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,   48,    0,
-        0,   47,    0,   47,    0,    0,    0,    0,   47,    0,
-        0,   37,   36,   47,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,   34,    0,    0,    0,    0,
-        0,   47,    0,    0,    0,    0,   38,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,   28,    0,    0,    0,
-        0,   35,    0,    0,    0,    0,   47,    0,    0,    0,
-
-        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-       29,    0,    0,   32,    0,    0,    0,    0,   47,    0,
-        0,    0,    0,    0,    0,    0,   22,    0,    0,   25,
-        0,    0,    0,   31,    0,    0,    0,    0,   12,    0,
-        0,    0,    0,    0,   20,    0,    0,    0,    0,    0,
-       30,    0,    0,    0,    0,    0,    0,    0,    0,    0,
-        0,    0,   24,    0,    0,    8,    9,   10,    0,    0,
-        0,    0,    0,    0,    0,    0,    0,    0,   11,    0,
-        0,   16,    0,    0,    0,    0,    0,    0,    0,    0,
-       17,    0,    0,    0,   26,   27,    0,    0,    0,    0,
-
-        0,   13,   15,   19,    0,    0,    0,    0,    0,    0,
-       21,   23,    0
+        0,    0,    0,    0,    6,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,   48,   48,   48,    4,   62,
+       62,    2,    3,   62,   53,   62,   44,   62,   62,   62,
+       62,   62,   62,   63,    0,   62,   52,   62,   62,   62,
+       62,   62,   62,   48,   48,   48,   48,   48,   48,   48,
+
+       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,    4,    0,   62,    2,    3,   62,   62,
+       62,   62,   62,   62,   62,   62,   62,   62,   62,   62,
+       62,   46,   48,   48,   48,   48,   48,    0,   48,   48,
+       48,   48,   48,   48,   48,   48,   48,   48,   48,   48,
+       48,   48,   48,   48,   48,    4,   62,   62,    3,   62,
+       42,   45,   47,   62,    0,   58,   62,   62,   62,   62,
+       62,   41,   62,   48,   48,   48,   48,   48,   48,    0,
+        0,    0,   48,   48,   48,   48,   48,   48,    0,   48,
+       48,   48,    0,   48,   48,   48,    0,    0,   48,   48,
+
+        4,    0,   62,    3,   62,    0,   62,   62,   62,   62,
+       50,   59,   51,   62,   48,   48,   48,   48,   48,    0,
+       15,    0,    0,    0,   48,   48,   48,    0,    0,   48,
+        0,   48,   48,   48,    0,   48,    0,   48,    0,    0,
+        0,    0,   48,    4,   61,   62,   62,   62,   62,   56,
+       54,   40,   60,   43,   48,   48,   48,   48,   48,    0,
+        0,    0,    0,   48,   48,   48,    0,    0,   48,    0,
+       48,    0,   48,    0,   48,    0,   48,    0,    0,    0,
+        0,   48,   61,   62,   57,   55,    0,    0,   48,   48,
+       48,    0,    0,    0,    0,   48,   19,    0,    0,    0,
+
+        0,   48,    0,    0,    0,    7,    0,    0,    8,    0,
+       48,    0,    0,   34,    0,    0,   61,   62,    0,    0,
+       48,    0,   48,    0,    0,    0,    0,   48,    0,    0,
+        0,    0,   48,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,   49,    0,    0,   48,    0,
+       48,    0,    0,    0,    0,   48,    0,    0,   38,   37,
+       48,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   35,    0,    0,    0,    0,    0,   48,    0,
+        0,    0,    0,   39,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,   29,    0,    0,    0,    0,   36,    0,
+
+        0,    0,    0,   48,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   30,    0,    0,
+       33,    0,    0,    0,    0,   48,    0,    0,    0,    0,
+        0,    0,    0,   23,    0,    0,   26,    0,    0,    0,
+       32,    0,    0,    0,    0,   13,    0,    0,    0,    0,
+        0,   21,    0,    0,    0,    0,    0,   31,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,   25,
+        0,    0,    9,   10,   11,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,   12,    0,    0,   17,    0,
+        0,    0,    0,    0,    0,    0,    0,   18,    0,    0,
+
+        0,   27,   28,    0,    0,    0,    0,    0,   14,   16,
+       20,    0,    0,    0,    0,    0,    0,   22,   24,    0
     } ;
 
 static yyconst flex_int32_t yy_ec[256] =
@@ -530,11 +530,11 @@ static yyconst flex_int32_t yy_ec[256] =
        19,    1,   20,    1,   21,   22,   23,   24,   25,   26,
        27,   28,   29,   30,   31,   32,   33,   34,   35,   36,
        37,   38,   39,   40,   41,   42,   43,   44,   45,   46,
-        1,    1,    1,    1,   47,    1,   48,   49,   50,   51,
+        1,   47,    1,    1,   48,    1,   49,   50,   51,   52,
 
-       52,   53,   54,   55,   56,   57,   58,   59,   60,   61,
-       62,   63,   64,   65,   66,   67,   68,   69,   70,   71,
-       72,   73,    1,    1,    1,    1,    1,    1,    1,    1,
+       53,   54,   55,   56,   57,   58,   59,   60,   61,   62,
+       63,   64,   65,   66,   67,   68,   69,   70,   71,   72,
+       73,   74,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -551,335 +551,343 @@ static yyconst flex_int32_t yy_ec[256] =
         1,    1,    1,    1,    1
     } ;
 
-static yyconst flex_int32_t yy_meta[74] =
+static yyconst flex_int32_t yy_meta[75] =
     {   0,
-        1,    1,    2,    1,    3,    1,    1,    3,    3,    1,
-        3,    3,    3,    3,    3,    3,    3,    1,    1,    1,
-        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        3,    3,    3,    3,    3,    3,    3,    3,    3,    3,
-        3,    3,    3
+        1,    1,    1,    1,    2,    1,    1,    2,    2,    1,
+        2,    2,    2,    2,    2,    2,    2,    1,    1,    1,
+        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+        2,    2,    2,    2,    2,    2,    1,    2,    2,    2,
+        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+        2,    2,    2,    2,    2,    2,    2,    2,    2,    2,
+        2,    2,    2,    2
     } ;
 
-static yyconst flex_int16_t yy_base[518] =
+static yyconst flex_int16_t yy_base[526] =
     {   0,
-        0,  641,  636, 1648, 1648, 1648, 1648,  629,  625,  604,
-       65,   72,    0,   55,   50,   57,   71,   55,   62,   72,
-       74,   78,   75,   63,  619,  616,  613,  132,  195,  103,
-      208,  251,  215,  235,  228,  230,  237,  245,  265,  281,
-      286,  294,  296,  311,  313,  327,  343,  354,  361,  370,
-      610, 1648,  417,  305,   69,   77,   86,   75,  347,   78,
-      362,  402,   91,  113,  189,  417,  397,  482,  525,  489,
-      413,  466,  502,  507,  509,  514,  516,  542,  550,  557,
-      569,  576,  578,  590,  621,  598,  623,  215,  232,  246,
-      242,  248,  604,  278,  275,  293,  354,  295,  303,  402,
-
-      311,  330,  427,  331,  335,  355,  358,  638,  671,  714,
-      757,  645,  634,  686,  669,  692,  694,  747,  738,  703,
-      749,  775,  701,  781,  790,  783,  376,  423,  566,  421,
-      453,  778,  521,  523,  530,  532,  537,  569,  602,  573,
-      627,  624,  597,  638,  631,  688,  594,  759,  708,  838,
-      851,  824,  861,  874,  876,  881,  883,  888,  894,  896,
-      901,  910,  928,  942,  937,  951,  953,  711,  735,  749,
-      768,  769,  501,  767,  788,  775,  778,  782,  794,  593,
-      582,  796,  840,  845,  850,  875,  872,  901,  568,  903,
-      932,  913,  560,  929,  997, 1014, 1057, 1648,  996,  969,
-
-      959,  987, 1012, 1036, 1030, 1041, 1043, 1048,  943,  995,
-     1013, 1031, 1026, 1015, 1648, 1036, 1033, 1052, 1044, 1052,
-     1048, 1049, 1058, 1059, 1064, 1069,  552, 1058, 1068, 1058,
-     1071, 1062, 1076, 1073, 1085, 1086, 1067, 1648, 1135, 1124,
-     1133, 1148, 1154, 1159, 1165, 1167, 1178, 1183,  549,  537,
-     1113, 1126, 1155, 1149, 1159,  527,  524, 1168, 1145,  523,
-     1165, 1178, 1167, 1164,  519, 1160,  507, 1169,  481, 1173,
-     1169, 1185, 1189, 1179, 1197,  440, 1241, 1239, 1223, 1254,
-     1197, 1200, 1201,  439, 1200, 1211, 1225, 1231, 1226, 1248,
-        0, 1237, 1242, 1232, 1243, 1233, 1255, 1255, 1253, 1648,
-
-     1258, 1246, 1248,  417, 1253, 1265, 1648, 1252, 1262, 1313,
-     1318, 1259, 1280, 1288, 1275, 1285, 1300,  411, 1291, 1309,
-     1309, 1309, 1311,  384,  381, 1312, 1304, 1320, 1310, 1309,
-     1320, 1321, 1307, 1325, 1330, 1317, 1329, 1328, 1374, 1319,
-     1330,  383, 1340, 1355,  376, 1344, 1363, 1349,  336,  339,
-     1355, 1648, 1648,  331, 1350, 1363, 1368, 1354, 1374, 1364,
-     1360, 1379, 1369, 1378, 1382, 1648, 1359, 1365, 1365, 1381,
-     1375, 1374, 1376, 1391, 1387, 1398, 1648, 1400, 1400, 1404,
-     1403, 1412, 1410, 1406, 1405, 1424, 1648, 1410, 1422, 1420,
-     1408, 1648, 1419, 1430, 1427, 1432, 1424, 1438, 1420, 1436,
-
-     1424, 1438, 1424, 1441,  312, 1442, 1436,  306,  301,  298,
-     1648, 1450, 1470, 1648, 1473, 1458, 1466, 1464,  281, 1467,
-     1476, 1462, 1470, 1469,  274, 1470, 1648, 1483, 1468, 1648,
-     1470, 1471, 1486, 1648, 1477, 1473, 1489, 1474, 1648, 1491,
-     1479, 1495, 1499, 1489, 1648, 1499,  264,  252, 1517, 1520,
-     1648, 1518, 1512,  238, 1512, 1514, 1521, 1527, 1518, 1528,
-     1530, 1521, 1648, 1515, 1516, 1648, 1648, 1648,  229, 1527,
-     1543,  228, 1534, 1543, 1544, 1543, 1544, 1545, 1648, 1550,
-     1534, 1648,  215, 1553, 1554, 1547,  199,  196, 1577, 1572,
-     1648, 1565,  143, 1563, 1648, 1648, 1581,  120,  119, 1569,
-
-     1583, 1648, 1648, 1648, 1584, 1572, 1590, 1574, 1590,  116,
-     1648, 1648, 1648, 1641,  126, 1644,  113
+        0,  622,  626, 1711, 1711, 1711, 1711,   70,  617,  597,
+       67,   74,    0,   57,   52,   59,   73,   57,   64,   74,
+      610,   77,   79,   77,   65,  609,  101, 1711,  606,  138,
+      202,  215,  217,  230,  237,  250,  252,  259,  265,  277,
+      282,  287,  297,  271,  315,  377,  323,  342,  350,  359,
+      364,  396,  401,  591, 1711,  449,  242,   73,   80,   89,
+       76,  378,   78,  397,  398,   91,   76,   91,  441,  328,
+      515,  528,  481,  499,  421,  541,  543,  548,  553,  559,
+      565,  576,  590,  595,  649,    0,  597,  622,  614,  624,
+      656,  632,  674,   85,  131,  124,  230,  249,  572,  260,
+
+      272,  285,  403,  300,  319,  375,  336,  376,  650,  381,
+      401,  415,  436,  717,  730,  743,  756,  768,  781,  787,
+      789,  797,  803,  808,  825,  810,  838,  852,  854,  863,
+      870,  702,  454,  455,  651,  442,  456,  656,  461,  534,
+      538,  533,  537,  562,  571,  581,  628,  642,  570,  655,
+      650,  656,  569,  687,  664,  893,  921,  872,  928,  907,
+      879,  942,  944,  949,  951,  958,  967,  973,  975,  980,
+      993,  995, 1000,  660,  683,  720,  750,  755,  126,  755,
+      795,  786,  787,  805,  860,  567,  564,  856,  856,  855,
+      941,  969,  971,  987,  547,  981,  996,  976,  546,  999,
+
+     1048, 1062, 1075, 1711, 1088, 1090, 1024, 1097, 1106, 1112,
+     1117, 1124, 1132, 1134, 1012, 1043, 1089, 1095, 1090, 1081,
+     1711, 1087, 1085, 1107, 1099, 1116, 1111, 1110, 1120, 1124,
+     1132, 1139,  527, 1128, 1138, 1128, 1141, 1132, 1146, 1139,
+     1151, 1159, 1139, 1711, 1205, 1182, 1199, 1218, 1220, 1228,
+     1233, 1235, 1240, 1246,  526,  517, 1165, 1192, 1217, 1217,
+     1225,  514,  513, 1235, 1212,  472, 1229, 1240, 1230, 1229,
+      471, 1223,  457, 1231,  258, 1230, 1230, 1246, 1248, 1237,
+     1254,  456, 1297, 1310, 1312, 1317, 1243, 1257, 1258,  451,
+     1263, 1287, 1289, 1293, 1288, 1310,    0, 1299, 1302, 1292,
+
+     1304, 1293, 1315, 1315, 1313, 1711, 1318, 1308, 1711, 1309,
+      406, 1313, 1325, 1711, 1311, 1321, 1376, 1378, 1316, 1348,
+     1363, 1349, 1351, 1364,  403, 1355, 1373, 1370, 1371, 1374,
+      373,  372, 1375, 1367, 1382, 1371, 1370, 1381, 1382, 1368,
+     1386, 1418, 1378, 1391, 1388, 1406, 1394, 1405,  367, 1414,
+     1415,  362, 1402, 1423, 1409,  346,  352, 1415, 1711, 1711,
+      348, 1410, 1423, 1428, 1414, 1433, 1424, 1420, 1439, 1429,
+     1438, 1442, 1711, 1419, 1425, 1425, 1442, 1436, 1439, 1448,
+     1464, 1469, 1473, 1711, 1461, 1459, 1463, 1463, 1472, 1470,
+     1466, 1465, 1484, 1711, 1470, 1482, 1480, 1469, 1711, 1480,
+
+     1491, 1488, 1493, 1485, 1499, 1481, 1497, 1486, 1500, 1490,
+     1513,  334, 1516, 1510,  333,  340,  336, 1711, 1512, 1530,
+     1711, 1533, 1518, 1527, 1525,  322, 1528, 1537, 1523, 1531,
+     1529,  321, 1531, 1711, 1544, 1530, 1711, 1532, 1533, 1548,
+     1711, 1539, 1535, 1551, 1536, 1711, 1553, 1542, 1558, 1565,
+     1562, 1711, 1565,  319,  289, 1578, 1581, 1711, 1579, 1573,
+      285, 1573, 1576, 1583, 1589, 1580, 1590, 1591, 1582, 1711,
+     1577, 1578, 1711, 1711, 1711,  282, 1590, 1606,  253, 1597,
+     1606, 1607, 1606, 1607, 1608, 1711, 1613, 1598, 1711,  243,
+     1616, 1621, 1612,  237,  221, 1630, 1632, 1711, 1627,  229,
+
+     1625, 1711, 1711, 1643,  217,  208, 1631, 1646, 1711, 1711,
+     1711, 1647, 1635, 1653, 1636, 1652,  202, 1711, 1711, 1711,
+     1704,  154, 1706,  131, 1708
     } ;
 
-static yyconst flex_int16_t yy_def[518] =
+static yyconst flex_int16_t yy_def[526] =
     {   0,
-      513,    1,  513,  513,  513,  513,  513,  514,  513,  513,
-      515,  513,  515,  515,  515,  515,  515,  515,  515,  515,
-      515,  515,  515,  515,  516,  514,  514,  513,  513,  517,
-      517,  517,  513,  517,  517,  517,  517,  517,  517,  517,
-      517,  517,  517,  517,  517,  517,  517,  517,  517,  517,
-      516,  513,   28,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,  513,  517,  517,  517,  513,
-      517,  517,  517,  517,  517,  517,  517,  517,  517,  517,
-      517,  517,  517,  517,  517,  517,  517,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
-
-       53,   53,   53,   53,   53,   53,   53,  513,  517,  517,
-      517,  513,  517,  517,  517,  517,  517,  517,  517,  517,
-      517,  517,  517,  517,  517,  517,   53,   53,   53,   53,
-       53,  513,   53,   53,   53,   53,   53,   53,   53,   53,
-       53,   53,   53,   53,   53,   53,   53,   53,   53,  513,
-      517,  517,  513,  517,  517,  517,  517,  517,  517,  517,
-      517,  517,  517,  517,  517,  517,  517,   53,   53,   53,
-       53,   53,   53,  513,  513,  513,   53,   53,   53,   53,
-       53,   53,  513,   53,   53,   53,  513,   53,   53,   53,
-      513,  513,   53,   53,  513,  517,  517,  513,  517,  517,
-
-      517,  517,  517,  517,  517,  517,  517,  517,   53,   53,
-       53,   53,   53,  513,  513,  513,  513,  513,   53,   53,
-       53,  513,  513,   53,  513,   53,   53,   53,  513,   53,
-      513,   53,  513,  513,  513,  513,   53,  513,  517,  517,
-      517,  517,  517,  517,  517,  517,  517,  517,   53,   53,
-       53,   53,   53,  513,  513,  513,  513,   53,   53,   53,
-      513,  513,   53,  513,   53,  513,   53,  513,   53,  513,
-       53,  513,  513,  513,  513,   53,  517,  517,  517,  517,
-      513,  513,   53,   53,   53,  513,  513,  513,  513,   53,
-       53,  513,  513,  513,  513,   53,  513,  513,  513,  513,
-
-      513,  513,  513,   53,  513,  513,  513,  513,  513,  517,
-      517,  513,  513,   53,  513,   53,  513,  513,  513,  513,
-       53,  513,  513,  513,  513,   53,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  517,  513,
-      513,   53,  513,   53,  513,  513,  513,  513,   53,  513,
-      513,  513,  513,   53,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,   53,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,   53,  513,  513,  513,
-
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,   53,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,    0,  513,  513,  513,  513
+      520,    1,  520,  520,  520,  520,  520,  521,  520,  520,
+      522,  520,  522,  522,  522,  522,  522,  522,  522,  522,
+      522,  522,  522,  522,  522,  523,  521,  520,  521,  520,
+      520,  524,  524,  524,  520,  524,  524,  524,  524,  524,
+      524,  524,  524,  524,  524,  525,  524,  524,  524,  524,
+      524,  524,  524,  523,  520,   30,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,  520,  524,
+      524,  524,  520,  524,  524,  524,  524,  524,  524,  524,
+      524,  524,  524,  524,  525,   85,  524,  524,  524,  524,
+      524,  524,  524,   56,   56,   56,   56,   56,   56,   56,
+
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,  520,  524,  524,  524,  520,  524,  524,
+      524,  524,  524,  524,  524,  524,  524,  524,  524,  524,
+      524,  524,   56,   56,   56,   56,   56,  520,   56,   56,
+       56,   56,   56,   56,   56,   56,   56,   56,   56,   56,
+       56,   56,   56,   56,   56,  520,  524,  524,  520,  524,
+      524,  524,  524,  524,  524,  524,  524,  524,  524,  524,
+      524,  524,  524,   56,   56,   56,   56,   56,   56,  520,
+      520,  520,   56,   56,   56,   56,   56,   56,  520,   56,
+       56,   56,  520,   56,   56,   56,  520,  520,   56,   56,
+
+      520,  524,  524,  520,  524,  524,  524,  524,  524,  524,
+      524,  524,  524,  524,   56,   56,   56,   56,   56,  520,
+      520,  520,  520,  520,   56,   56,   56,  520,  520,   56,
+      520,   56,   56,   56,  520,   56,  520,   56,  520,  520,
+      520,  520,   56,  520,  524,  524,  524,  524,  524,  524,
+      524,  524,  524,  524,   56,   56,   56,   56,   56,  520,
+      520,  520,  520,   56,   56,   56,  520,  520,   56,  520,
+       56,  520,   56,  520,   56,  520,   56,  520,  520,  520,
+      520,   56,  524,  524,  524,  524,  520,  520,   56,   56,
+       56,  520,  520,  520,  520,   56,   56,  520,  520,  520,
+
+      520,   56,  520,  520,  520,  520,  520,  520,  520,  520,
+       56,  520,  520,  520,  520,  520,  524,  524,  520,  520,
+       56,  520,   56,  520,  520,  520,  520,   56,  520,  520,
+      520,  520,   56,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  524,  520,  520,   56,  520,
+       56,  520,  520,  520,  520,   56,  520,  520,  520,  520,
+       56,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,   56,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+
+      520,  520,  520,   56,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,   56,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,    0,
+      520,  520,  520,  520,  520
     } ;
 
-static yyconst flex_int16_t yy_nxt[1722] =
+static yyconst flex_int16_t yy_nxt[1786] =
     {   0,
         4,    5,    6,    7,    8,    4,    7,    9,    4,   10,
        11,   11,   11,   11,   11,   11,   11,   12,    7,    4,
        13,   13,   14,   15,   16,   17,   13,   18,   19,   20,
-       13,   13,   21,   13,   13,   13,   13,   22,   23,   24,
-       13,   13,   13,   13,   13,   13,    4,   13,   13,   14,
-       15,   16,   17,   13,   18,   19,   20,   13,   13,   21,
-       13,   13,   13,   13,   22,   23,   24,   13,   13,   13,
-       13,   13,   13,   31,   36,   32,   32,   32,   32,   32,
-       32,   32,   33,   33,   33,   33,   33,   33,   33,   34,
-       37,   39,   35,   41,   38,   42,   43,   44,   47,   49,
-
-       50,   36,   48,   90,   40,   91,   92,   30,   45,   93,
-       30,   30,   97,  105,   46,   67,   34,   37,   39,   35,
-       41,   38,   42,   43,   44,   47,   49,   50,   30,   48,
-       90,   40,   91,   92,  512,   45,   93,  504,  503,   97,
-      105,   46,   53,   53,   53,   53,   53,   53,   53,   30,
-      500,  106,   53,   54,   55,   56,   53,   53,   53,   57,
-       58,   53,   53,   53,   53,   59,   53,   60,   53,   61,
-       62,   63,   64,   65,   53,   53,   53,   53,  106,   53,
-       54,   55,   56,   53,   53,   53,   57,   58,   53,   53,
-       53,   53,   59,   53,   60,   53,   61,   62,   63,   64,
-
-       65,   53,   53,   53,   53,   66,   66,   66,   66,   66,
-       66,   66,   30,  107,  496,   30,   30,  495,   68,   68,
-       68,   68,   68,   68,   68,   70,   70,   70,   70,   70,
-       70,   70,   30,  491,   30,   30,   30,   30,   30,   30,
-      107,   30,   30,   30,   30,   30,  482,  479,  127,   30,
-       72,   73,   30,   30,   30,   30,  468,  128,   30,   31,
-       74,   69,   69,   69,   69,   69,   69,   69,   71,   30,
-      463,  462,   30,   30,   30,  127,   30,   72,   73,  129,
-      130,   30,   75,   30,  128,   30,  131,   74,   30,   30,
-       30,   30,  445,   30,   30,   71,   76,   30,   30,  439,
-
-       30,   30,   30,   30,   30,  432,  129,  130,  431,   75,
-      133,   30,  134,  131,   78,   30,   79,   30,   30,   30,
-       30,   30,   77,   76,  430,  135,   81,   30,  138,   80,
-      427,   30,   30,   88,   30,   30,   82,  133,  380,  134,
-       30,   78,   30,   79,  139,   89,  378,   30,  142,   77,
-       30,   30,  135,  143,  377,  138,   80,   30,   30,   30,
-       88,   30,   30,   82,   83,   30,  146,   94,   30,   30,
-      147,  139,   89,   30,   30,  142,   84,   30,   30,  148,
-      143,   95,   98,  373,   99,  136,  100,   96,  137,   30,
-      370,   83,   85,  146,   94,  149,  168,  147,   86,  353,
-
-       30,   30,  352,   84,   30,   30,  148,   30,   95,   98,
-       87,   99,  136,  100,   96,  137,   30,   30,  346,   85,
-       30,   30,  149,  168,  334,   86,  101,  108,  108,  108,
-      108,  108,  108,  108,  140,  102,  103,   87,   53,   53,
-       53,  141,  104,   30,   53,   53,  315,  309,  169,  144,
-       53,  113,   53,  101,   53,   53,   53,   53,   53,   30,
-      172,  140,  102,  103,  145,   53,   53,   53,  141,  104,
-       30,   53,   53,   30,   30,  169,  144,   53,  113,   53,
-      173,   53,   53,   53,   53,   53,   30,  172,  302,   30,
-      109,  145,  110,  110,  110,  110,  110,  110,  110,  112,
-
-      112,  112,  112,  112,  112,  112,   30,  173,  214,   30,
-       30,   30,   30,   30,   30,   30,   30,   30,   30,  215,
-       30,   30,   30,   30,   30,  300,  298,  117,   30,   30,
-      292,  289,   30,   31,  288,  111,  111,  111,  111,  111,
-      111,  111,  114,  115,  282,  177,   30,  178,   30,   30,
-       30,  179,  116,   30,   30,   30,  281,   30,   30,  266,
-       30,   30,   30,  180,   30,   30,  118,  236,  181,  114,
-      115,   30,  177,   30,  178,  231,   30,   30,  179,  116,
-       30,  119,   30,   30,   30,   30,   30,  120,   30,  223,
-      180,  170,  182,  118,   30,  181,   30,   30,   30,  171,
-
-      222,  191,   30,   30,  187,   30,   30,  184,  119,  183,
-      122,  132,   52,  123,  120,   30,  121,   27,  170,  182,
-       27,   52,   30,   29,   30,   30,  171,   30,   30,   30,
-       30,   30,   28,   27,  184,  513,   30,  122,   30,  125,
-      123,   30,   30,  121,   30,  124,   25,  126,  150,  150,
-      150,  150,  150,  150,  150,  153,  153,  153,  153,  153,
-      153,  153,  154,  513,  185,  186,  125,   30,  188,   30,
-      189,  513,  124,   30,  126,   30,   30,   30,   30,   30,
-       30,  151,  151,  151,  151,  151,  151,  151,  513,  154,
-       30,  185,  186,   30,   30,  188,   30,  189,   30,   30,
-
-       30,   30,   30,  513,  513,   30,  156,   30,   30,   30,
-       30,   30,  155,  513,  158,   30,  157,   30,   30,  513,
-      513,   30,  109,  190,  152,  152,  152,  152,  152,  152,
-      152,  162,   30,  156,  513,  165,  194,  513,   30,  155,
-      159,  158,   30,  157,  513,   30,   30,   30,  209,   30,
-      190,   30,  513,   30,   30,   30,   30,   30,  162,  210,
-       30,   30,  165,  194,   30,   30,  192,  111,  111,  111,
-      111,  111,  111,  111,  160,  209,  513,  211,  161,   30,
-      163,  513,   30,   30,   30,   30,  210,   30,   30,   30,
-       30,   30,  212,   30,   30,   30,  193,   30,   30,  174,
-
-      513,  160,  513,   30,  211,  161,  213,  163,  175,  513,
-      176,  216,  217,  218,  167,  164,  219,  220,  221,  212,
-      166,   30,  513,  193,  513,  513,  174,   30,   30,   30,
-      224,   30,  109,  213,  513,  175,   30,  176,  216,  217,
-      218,  167,  164,  219,  220,  221,  513,  166,  195,  195,
-      195,  195,  195,  195,  195,   30,  513,  224,   30,  196,
-      513,  197,  197,  197,  197,  197,  197,  197,  513,  513,
-       30,  198,  198,  198,  198,  198,  198,  198,   30,  225,
-       30,   30,   30,   30,   30,   30,  226,   30,   30,   30,
-       30,   30,   30,  513,  227,   30,   30,   30,   30,  228,
-
-       30,   30,   30,   30,   30,   30,  225,  201,   30,   30,
-      202,  229,  199,  226,   30,  513,  513,   30,   30,  513,
-       30,  227,   30,  513,  203,  230,  228,   30,  513,   30,
-      513,  513,   30,  513,  200,   30,   30,  232,  229,  199,
-       30,   30,   30,  204,   30,   30,   30,   30,  205,   30,
-       30,  203,  230,  235,  237,   30,   30,   30,   30,   30,
-       30,   30,  233,   30,  232,  234,   30,   30,  513,  207,
-      204,  244,  513,   30,   30,  205,   30,   30,  513,  206,
-      235,  237,  242,   30,  513,  243,  513,  249,   30,  233,
-      208,   30,  234,  513,   30,   30,  207,   30,  513,   30,
-
-       30,  245,  513,   30,   30,   30,  206,  238,  238,  238,
-      238,  238,  238,  238,  249,   30,   30,  208,   30,   30,
-       30,   30,   30,  513,  239,  239,  239,  239,  239,  239,
-      239,  513,  250,   30,   30,  241,  246,   30,   30,  251,
-       30,  513,   30,   30,   30,   30,  513,   30,   30,   30,
-       30,   30,   30,  252,  253,   30,   30,  254,   30,  250,
-       30,   30,  241,  246,   30,  196,  251,  240,  240,  240,
-      240,  240,  240,  240,  247,  255,   30,  256,  257,  258,
-      252,  253,   30,  259,  254,  260,  248,   30,  261,   30,
-      262,  263,  264,  265,   30,  267,  268,  269,  270,  271,
-
-      272,  247,  255,   30,  256,  257,  258,  273,  274,  275,
-      259,  276,  260,  248,  513,  261,  513,  262,  263,  264,
-      265,  513,  267,  268,  269,  270,  271,  272,   30,  513,
-      513,   30,  196,  513,  273,  274,  275,   30,  276,   30,
-       30,   30,   30,   30,  513,  277,  277,  277,  277,  277,
-      277,  277,   30,  283,  513,   30,   30,  278,   30,  513,
-      279,   30,   30,   30,  513,  284,   30,   30,  280,   30,
-       30,   30,   30,   30,   30,   30,  285,  286,  513,   30,
-      283,   30,   30,  287,  278,   30,   30,   30,  290,  291,
-       30,   30,  284,  293,   30,  296,  297,  513,  294,  299,
-
-       30,  301,  513,  285,  286,   30,  295,  303,  304,  305,
-      287,   30,  306,   30,  307,  290,  291,  308,  513,  513,
-      293,  513,  296,  297,   30,  294,  299,   30,  301,   30,
-       30,   30,  312,  295,  303,  304,  305,  313,  314,  306,
-      316,  307,  513,   30,  308,   30,   30,   30,   30,   30,
-      317,  310,  310,  310,  310,  310,  310,  310,   30,  312,
-      513,   30,   30,  318,  313,  314,  319,  316,  320,   30,
-      321,  322,  311,  513,  323,  324,  325,  317,  326,  327,
-      328,  329,  330,  331,  332,   30,  333,   30,  335,  336,
-      318,  337,  338,  319,  513,  320,  340,  321,  322,  311,
-
-       30,  323,  324,  325,  341,  326,  327,  328,  329,  330,
-      331,  332,  342,  333,  343,  335,  336,   30,  337,  338,
-       30,   30,   30,  340,  344,   30,   30,  345,  347,  348,
-      513,  341,  513,  349,  350,  351,  354,  513,  355,  342,
-      356,  343,  357,  358,  359,  360,  361,  362,  365,  366,
-      363,  344,  367,  368,  345,  347,  348,  339,  364,   30,
-      349,  350,  351,  354,   30,  355,  369,  356,  371,  357,
-      358,  359,  360,  361,  362,  365,  366,  363,   30,  367,
-      368,   30,   30,  372,  339,  364,  374,  375,  376,  379,
-      381,  382,  383,  369,  384,  371,  385,  386,  387,  388,
-
-      389,  390,  391,  392,  393,  394,  395,  396,  397,  398,
-      372,  399,  400,  374,  375,  376,  379,  381,  382,  383,
-       30,  384,  401,  385,  386,  387,  388,  389,  390,  391,
-      392,  393,  394,  395,  396,  397,  398,  402,  399,  400,
-      403,  404,  405,  406,  407,  408,  409,  410,  411,  401,
-      412,  413,  414,  415,  416,  417,  418,  419,  420,  421,
-      422,  423,  424,  425,  402,  426,  428,  403,  404,  405,
-      406,  407,  408,  409,  410,  411,  429,  412,  413,  414,
-      415,  416,  417,  418,  419,  420,  421,  422,  423,  424,
-      425,  433,  426,  428,  434,  435,  436,  437,  438,  440,
-
-      441,  442,  443,  429,  444,  446,  447,  448,  449,  450,
-      451,  452,  453,  454,  455,  456,  457,  458,  433,  459,
-      460,  434,  435,  436,  437,  438,  440,  441,  442,  443,
-      461,  444,  446,  447,  448,  449,  450,  451,  452,  453,
-      454,  455,  456,  457,  458,  464,  459,  460,  465,  466,
-      467,  469,  470,  471,  472,  473,  474,  461,  475,  476,
-      477,  478,  480,  481,  483,  484,  485,  486,  487,  488,
-      489,  490,  464,  492,  493,  465,  466,  467,  469,  470,
-      471,  472,  473,  474,  494,  475,  476,  477,  478,  480,
-      481,  483,  484,  485,  486,  487,  488,  489,  490,  497,
-
-      492,  493,  498,  499,  501,  502,  505,  506,  507,  508,
-      509,  494,  510,  511,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  497,  513,  513,  498,
-      499,  501,  502,  505,  506,  507,  508,  509,  513,  510,
-      511,   26,  513,   26,   51,   51,   51,    3,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513
+       13,   21,   22,   13,   13,   13,   13,   23,   24,   25,
+       13,   13,   13,   13,   13,   13,    4,    4,   13,   13,
+       14,   15,   16,   17,   13,   18,   19,   20,   13,   21,
+       22,   13,   13,   13,   13,   23,   24,   25,   13,   13,
+       13,   13,   13,   13,   28,   33,   38,   34,   34,   34,
+       34,   34,   34,   34,   35,   35,   35,   35,   35,   35,
+       35,   36,   39,   41,   37,   43,   40,   44,   45,   50,
+
+       47,   52,   53,   51,   38,   28,   42,   96,   97,   98,
+       99,   48,  103,  111,  112,  113,   29,   49,  133,   36,
+       39,   41,   37,   43,   40,   44,   45,   50,   47,   52,
+       53,   51,   70,  220,   42,   96,   97,   98,   99,   48,
+      103,  111,  112,  113,  221,   49,  133,   29,   56,   56,
+       56,   56,   56,   56,   56,   32,  134,  135,   56,   57,
+       58,   59,   56,   56,   56,   60,   61,   56,   56,   56,
+       56,   62,   56,   63,   56,   64,   65,   66,   67,   68,
+       56,   56,   56,   56,  134,  135,   56,   57,   58,   59,
+       56,   56,   56,   60,   61,   56,   56,   56,   56,   62,
+
+       56,   63,   56,   64,   65,   66,   67,   68,   56,   56,
+       56,   56,   69,   69,   69,   69,   69,   69,   69,   32,
+      519,   32,   32,   32,   32,   32,  511,   71,   71,   71,
+       71,   71,   71,   71,   32,  510,  507,   32,   33,  503,
+       72,   72,   72,   72,   72,   72,   72,   73,   73,   73,
+       73,   73,   73,   73,   32,  502,   32,   32,   32,   32,
+       32,  498,   32,   32,   32,  308,   32,   32,  136,   32,
+       94,  489,   32,   32,   75,   32,  309,   32,   32,   32,
+       76,   32,   95,   74,   32,   32,   32,  137,   77,   32,
+       32,   32,  139,   82,   32,   32,  136,   32,   94,   32,
+
+      486,   32,   75,  475,   32,   32,   32,  470,   76,  140,
+       95,   74,   32,   79,   78,  137,   77,  141,   32,   32,
+      139,   82,   32,   32,   32,   81,  469,   32,   80,   32,
+       32,   32,   32,  144,   32,   32,   32,  140,   87,  452,
+      446,   79,   78,  439,   32,  141,   32,  438,   83,   32,
+       32,  437,  434,   81,   32,  387,   80,   32,   32,  385,
+      145,  144,   32,   32,  384,   88,   32,   32,   32,  380,
+       32,   32,   32,  148,  377,   32,   83,   27,   27,   27,
+       27,   84,   27,   27,   85,   85,   27,   89,  145,   32,
+      360,  359,   90,   88,   27,   27,   27,   32,  100,  149,
+
+       32,  148,   91,   32,   32,   32,   32,  146,   32,   32,
+      353,   32,  101,  341,  147,   89,  152,  104,  102,  105,
+       90,  106,  107,   29,   85,   32,  100,  149,   32,   32,
+       91,  108,  109,   92,  142,  146,  153,  143,  110,  154,
+      101,   93,  147,   32,  152,  104,  102,  105,   32,  106,
+      107,  114,  114,  114,  114,  114,  114,  114,  322,  108,
+      109,   92,  142,  316,  153,  143,  110,  154,   32,   93,
+       56,   56,   56,  155,  174,  306,   56,   56,  304,  298,
+      175,  178,   56,  179,   56,  183,   56,   56,   56,   56,
+       56,  118,  118,  118,  118,  118,  118,  118,   56,   56,
+
+       56,  155,  174,   32,   56,   56,   32,   32,  175,  178,
+       56,  179,   56,  183,   56,   56,   56,   56,   56,   32,
+      295,  294,   32,  115,  288,  116,  116,  116,  116,  116,
+      116,  116,   32,  287,  272,   32,   33,  119,  117,  117,
+      117,  117,  117,  117,  117,   32,   32,   32,   32,   32,
+       32,   32,   32,  242,  237,   32,   32,   32,  184,  185,
+       32,   32,   32,   32,  186,  119,   32,   32,  187,   32,
+      123,  229,   32,   32,  228,   32,  197,  193,  189,  138,
+       32,  120,  121,   32,   32,  188,  184,  185,   32,  124,
+       32,  122,  186,   55,   32,   32,  187,   32,   32,   32,
+
+       32,   32,   32,   32,   32,   32,   32,  125,  520,  120,
+      121,   55,   32,  188,   46,  190,   31,  124,   32,  122,
+      126,   32,   32,   32,   30,  520,   32,   26,   32,   32,
+       32,   32,   32,  520,  520,  125,   32,   32,  520,   32,
+       32,  520,   32,  190,   32,  520,  128,  129,  126,   27,
+       27,   27,   27,   84,   27,   27,   85,   85,   27,  520,
+       32,   32,  127,   32,   32,  191,   27,   27,   27,   32,
+      520,   32,  150,  131,  128,  129,  176,  180,   32,   32,
+      130,   32,   32,  192,  177,  194,  181,  151,  182,  195,
+      127,  196,  200,  191,  198,   29,   85,  215,  132,  520,
+
+      150,  131,  520,   32,  176,  180,   32,  216,  130,   32,
+       32,  192,  177,  194,  181,  151,  182,  195,  520,  196,
+      200,   32,  520,  520,  199,  215,  132,  156,  156,  156,
+      156,  156,  156,  156,   32,  216,  520,   32,   32,  520,
+      157,  157,  157,  157,  157,  157,  157,   32,  217,   32,
+       32,  115,  199,  158,  158,  158,  158,  158,  158,  158,
+       32,  520,  520,   32,   32,  520,  117,  117,  117,  117,
+      117,  117,  117,  520,  218,  520,  217,   32,  159,  159,
+      159,  159,  159,  159,  159,   32,  520,  520,   32,   32,
+       32,   32,  219,   32,   32,   32,   32,   32,  520,  222,
+
+      520,   32,  218,   32,   32,   32,  520,   32,  520,  160,
+       32,   32,   32,  161,   32,   32,   32,   32,   32,  223,
+      219,  163,  520,  164,  224,  225,  162,  222,   32,   32,
+      520,  520,   32,   32,   32,  166,   32,  160,  168,  520,
+      226,  161,   32,  520,   32,   32,   32,  223,  520,  163,
+      165,  164,  224,  225,  162,   32,   32,   32,   32,   32,
+       32,   32,   32,  166,  520,  167,  168,   32,  226,  169,
+       32,   32,   32,  520,   32,  520,   32,   32,   32,   32,
+      115,  520,  520,   32,  227,   32,   32,   32,  171,  520,
+      230,  520,  170,  167,  173,  231,  232,  169,  520,   32,
+
+      520,   32,  172,  201,  201,  201,  201,  201,  201,  201,
+       32,   32,  227,  520,   32,   32,  171,   32,  230,   32,
+      170,  520,  173,  231,  232,   32,   32,  520,   32,  202,
+      172,  203,  203,  203,  203,  203,  203,  203,  204,  204,
+      204,  204,  204,  204,  204,  205,   32,  520,   32,   32,
+       32,   32,   32,   32,   32,   32,   32,   32,   32,   32,
+      520,  520,   32,  520,  207,   32,   32,  208,   32,  520,
+      520,   32,  520,  205,   32,   32,  520,   32,  520,   32,
+       32,   32,   32,   32,   32,  233,  520,   32,   32,   32,
+      209,   32,  520,  234,  520,  211,  206,   32,   32,   32,
+
+       32,   32,   32,   32,   32,   32,  210,   32,   32,  520,
+      235,  236,  520,  233,   32,  238,  241,  212,  209,  520,
+       32,  234,   32,  211,  243,  213,  239,   32,   32,  240,
+      520,   32,   32,  520,  210,  520,  250,  214,  235,  236,
+       32,  520,   32,  238,  241,  212,  520,   32,  520,  520,
+      520,  520,  243,  213,  239,  520,  255,  240,  244,  244,
+      244,  244,  244,  244,  244,  214,   32,  520,  520,   32,
+       32,   32,  245,  245,  245,  245,  245,  245,  245,   32,
+      256,  520,   32,  202,  255,  246,  246,  246,  246,  246,
+      246,  246,   32,  520,   32,   32,   32,   32,   32,  520,
+
+      520,   32,  520,  248,   32,   32,  249,  520,  256,   32,
+       32,  251,  520,   32,   32,  257,   32,  258,  259,   32,
+       32,   32,   32,  260,   32,   32,  261,  247,   32,  262,
+      252,   32,   32,  263,  264,   32,   32,   32,   32,   32,
+       32,   32,   32,  257,   32,  258,  259,  265,  266,  267,
+      253,  260,  268,   32,  261,  247,  269,  262,  252,   32,
+      270,  263,  264,  271,   32,  273,  274,  275,  276,  277,
+      278,   32,  254,  279,  280,  265,  266,  267,  253,   32,
+      268,   32,  281,  282,  269,  520,   32,  520,  270,   32,
+      202,  271,  520,  273,  274,  275,  276,  277,  278,  520,
+
+      254,  279,  280,   32,  520,  289,   32,   32,  520,   32,
+      281,  282,   32,   32,  520,  283,  283,  283,  283,  283,
+      283,  283,   32,  284,   32,   32,   32,   32,   32,   32,
+      285,  290,   32,  289,  286,   32,   32,   32,  291,   32,
+       32,   32,   32,   32,   32,  292,   32,   32,   32,  293,
+       32,  284,   32,   32,   32,  296,  297,  299,  302,  290,
+      300,  303,  305,  307,  310,   32,  291,   32,  301,  311,
+      312,  313,  314,  292,  315,   32,  520,  293,  319,  520,
+       32,  520,   32,  296,  297,  299,  302,   32,  300,  303,
+      305,  307,  310,   32,  320,  321,  301,  311,  312,  313,
+
+      314,   32,  315,  323,   32,   32,  319,  317,  317,  317,
+      317,  317,  317,  317,   32,  520,   32,   32,   32,   32,
+       32,   32,  320,  321,   32,   32,  324,  325,  326,  520,
+      327,  323,  328,  329,  330,  331,  520,  332,  333,  334,
+      335,  336,  337,  318,   32,  338,  339,  340,  342,  343,
+      344,  345,  520,  347,  324,  325,  326,   32,  327,   32,
+      328,  329,  330,  331,   32,  332,  333,  334,  335,  336,
+      337,  318,  348,  338,  339,  340,  342,  343,  344,  345,
+       32,  347,   32,   32,   32,   32,   32,  349,  350,  520,
+      351,  352,  354,  355,  356,  520,  357,  520,  358,  361,
+
+      348,  362,  363,  364,  365,  366,  367,  368,  369,  372,
+       32,  373,  374,   32,   32,  349,  350,  346,  351,  352,
+      354,  355,  356,   32,  357,   32,  358,  361,  375,  362,
+      363,  364,  365,  366,  367,  368,  369,  372,  370,  373,
+      374,  376,  378,  379,  381,  346,  371,  382,  383,  386,
+      388,  389,  390,   32,  391,  392,  375,  393,  394,  395,
+      396,  397,  398,  399,  400,  401,  370,  402,  403,  376,
+      378,  379,  381,  404,  371,  382,  383,  386,  388,  389,
+      390,  405,  391,  392,  406,  393,  394,  395,  396,  397,
+      398,  399,  400,  401,  407,  402,  403,  408,  409,  410,
+
+      411,  404,  412,  413,  414,  415,  416,  417,  418,  405,
+      419,  420,  406,  421,  422,  423,  424,  425,  426,  427,
+      428,  429,  407,  430,  431,  408,  409,  410,  411,  432,
+      412,  413,  414,  415,  416,  417,  418,  433,  419,  420,
+      435,  421,  422,  423,  424,  425,  426,  427,  428,  429,
+      436,  430,  431,  440,  441,  442,  443,  432,  444,  445,
+      447,  448,  449,  450,  451,  433,  453,  454,  435,  455,
+      456,  457,  458,  459,  460,  461,  462,  463,  436,  464,
+      465,  440,  441,  442,  443,  466,  444,  445,  447,  448,
+      449,  450,  451,  467,  453,  454,  468,  455,  456,  457,
+
+      458,  459,  460,  461,  462,  463,  471,  464,  465,  472,
+      473,  474,  476,  466,  477,  478,  479,  480,  481,  482,
+      483,  467,  484,  485,  468,  487,  488,  490,  491,  492,
+      493,  494,  495,  496,  471,  497,  499,  472,  473,  474,
+      476,  500,  477,  478,  479,  480,  481,  482,  483,  501,
+      484,  485,  504,  487,  488,  490,  491,  492,  493,  494,
+      495,  496,  505,  497,  499,  506,  508,  509,  512,  500,
+      513,  514,  515,  516,  517,  518,  520,  501,  520,  520,
+      504,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      505,  520,  520,  506,  508,  509,  512,  520,  513,  514,
+
+      515,  516,  517,  518,   27,   27,   54,   54,   86,   86,
+        3,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520
     } ;
 
-static yyconst flex_int16_t yy_chk[1722] =
+static yyconst flex_int16_t yy_chk[1786] =
     {   0,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
@@ -888,200 +896,206 @@ static yyconst flex_int16_t yy_chk[1722] =
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
-        1,    1,    1,   11,   15,   11,   11,   11,   11,   11,
-       11,   11,   12,   12,   12,   12,   12,   12,   12,   14,
-       16,   17,   14,   18,   16,   19,   20,   21,   22,   23,
-
-       24,   15,   22,   55,   17,   56,   57,   30,   21,   58,
-       30,   30,   60,   63,   21,  517,   14,   16,   17,   14,
-       18,   16,   19,   20,   21,   22,   23,   24,  515,   22,
-       55,   17,   56,   57,  510,   21,   58,  499,  498,   60,
-       63,   21,   28,   28,   28,   28,   28,   28,   28,   30,
-      493,   64,   28,   28,   28,   28,   28,   28,   28,   28,
-       28,   28,   28,   28,   28,   28,   28,   28,   28,   28,
-       28,   28,   28,   28,   28,   28,   28,   28,   64,   28,
-       28,   28,   28,   28,   28,   28,   28,   28,   28,   28,
-       28,   28,   28,   28,   28,   28,   28,   28,   28,   28,
-
-       28,   28,   28,   28,   28,   29,   29,   29,   29,   29,
-       29,   29,   31,   65,  488,   31,   31,  487,   31,   31,
-       31,   31,   31,   31,   31,   33,   33,   33,   33,   33,
-       33,   33,   35,  483,   36,   35,   35,   36,   36,   34,
-       65,   37,   34,   34,   37,   37,  472,  469,   88,   38,
-       35,   36,   38,   38,   31,   32,  454,   89,   32,   32,
-       37,   32,   32,   32,   32,   32,   32,   32,   34,   39,
-      448,  447,   39,   39,   35,   88,   36,   35,   36,   90,
-       91,   34,   38,   37,   89,   40,   92,   37,   40,   40,
-       41,   38,  425,   41,   41,   34,   39,   32,   42,  419,
-
-       43,   42,   42,   43,   43,  410,   90,   91,  409,   38,
-       94,   39,   95,   92,   41,   44,   42,   45,   44,   44,
-       45,   45,   40,   39,  408,   96,   44,   40,   98,   43,
-      405,   46,   41,   54,   46,   46,   45,   94,  354,   95,
-       42,   41,   43,   42,   99,   54,  350,   47,  101,   40,
-       47,   47,   96,  102,  349,   98,   43,   44,   48,   45,
-       54,   48,   48,   45,   46,   49,  104,   59,   49,   49,
-      105,   99,   54,   46,   50,  101,   47,   50,   50,  106,
-      102,   59,   61,  345,   61,   97,   61,   59,   97,   47,
-      342,   46,   48,  104,   59,  107,  127,  105,   49,  325,
-
-       48,   67,  324,   47,   67,   67,  106,   49,   59,   61,
-       50,   61,   97,   61,   59,   97,   50,   71,  318,   48,
-       71,   71,  107,  127,  304,   49,   62,   66,   66,   66,
-       66,   66,   66,   66,  100,   62,   62,   50,   53,   53,
-       53,  100,   62,   67,   53,   53,  284,  276,  128,  103,
-       53,   71,   53,   62,   53,   53,   53,   53,   53,   71,
-      130,  100,   62,   62,  103,   53,   53,   53,  100,   62,
-       72,   53,   53,   72,   72,  128,  103,   53,   71,   53,
-      131,   53,   53,   53,   53,   53,   68,  130,  269,   68,
-       68,  103,   68,   68,   68,   68,   68,   68,   68,   70,
-
-       70,   70,   70,   70,   70,   70,   73,  131,  173,   73,
-       73,   74,   72,   75,   74,   74,   75,   75,   76,  173,
-       77,   76,   76,   77,   77,  267,  265,   77,   68,   69,
-      260,  257,   69,   69,  256,   69,   69,   69,   69,   69,
-       69,   69,   73,   75,  250,  133,   78,  134,   73,   78,
-       78,  135,   76,   74,   79,   75,  249,   79,   79,  227,
-       76,   80,   77,  136,   80,   80,   78,  193,  137,   73,
-       75,   69,  133,   81,  134,  189,   81,   81,  135,   76,
-       82,   79,   83,   82,   82,   83,   83,   80,   78,  181,
-      136,  129,  138,   78,   84,  137,   79,   84,   84,  129,
-
-      180,  147,   86,   80,  143,   86,   86,  140,   79,  139,
-       83,   93,   51,   84,   80,   81,   82,   27,  129,  138,
-       26,   25,   82,   10,   83,   85,  129,   87,   85,   85,
-       87,   87,    9,    8,  140,    3,   84,   83,  113,   86,
-       84,  113,  113,   82,   86,   85,    2,   87,  108,  108,
-      108,  108,  108,  108,  108,  112,  112,  112,  112,  112,
-      112,  112,  113,    0,  141,  142,   86,   85,  144,   87,
-      145,    0,   85,  115,   87,  109,  115,  115,  109,  109,
-      113,  109,  109,  109,  109,  109,  109,  109,    0,  113,
-      114,  141,  142,  114,  114,  144,  116,  145,  117,  116,
-
-      116,  117,  117,    0,    0,  123,  115,  120,  123,  123,
-      120,  120,  114,    0,  117,  115,  116,  109,  110,    0,
-        0,  110,  110,  146,  110,  110,  110,  110,  110,  110,
-      110,  120,  114,  115,    0,  123,  149,    0,  116,  114,
-      117,  117,  119,  116,    0,  119,  119,  123,  168,  120,
-      146,  118,    0,  121,  118,  118,  121,  121,  120,  169,
-      110,  111,  123,  149,  111,  111,  148,  111,  111,  111,
-      111,  111,  111,  111,  118,  168,    0,  170,  119,  122,
-      121,    0,  122,  122,  119,  124,  169,  126,  124,  124,
-      126,  126,  171,  118,  125,  121,  148,  125,  125,  132,
-
-        0,  118,    0,  111,  170,  119,  172,  121,  132,    0,
-      132,  174,  175,  176,  125,  122,  177,  178,  179,  171,
-      124,  122,    0,  148,    0,    0,  132,  124,  152,  126,
-      182,  152,  152,  172,    0,  132,  125,  132,  174,  175,
-      176,  125,  122,  177,  178,  179,    0,  124,  150,  150,
-      150,  150,  150,  150,  150,  151,    0,  182,  151,  151,
-        0,  151,  151,  151,  151,  151,  151,  151,    0,    0,
-      152,  153,  153,  153,  153,  153,  153,  153,  154,  183,
-      155,  154,  154,  155,  155,  156,  184,  157,  156,  156,
-      157,  157,  158,    0,  185,  158,  158,  151,  159,  186,
-
-      160,  159,  159,  160,  160,  161,  183,  159,  161,  161,
-      159,  187,  154,  184,  162,    0,    0,  162,  162,    0,
-      154,  185,  155,    0,  161,  188,  186,  156,    0,  157,
-        0,    0,  163,    0,  158,  163,  163,  190,  187,  154,
-      159,  165,  160,  162,  165,  165,  164,  161,  163,  164,
-      164,  161,  188,  192,  194,  166,  162,  167,  166,  166,
-      167,  167,  191,  201,  190,  191,  201,  201,    0,  165,
-      162,  201,    0,  200,  163,  163,  200,  200,    0,  164,
-      192,  194,  200,  165,    0,  200,    0,  209,  164,  191,
-      167,  202,  191,    0,  202,  202,  165,  166,    0,  167,
-
-      199,  202,    0,  199,  199,  201,  164,  195,  195,  195,
-      195,  195,  195,  195,  209,  200,  203,  167,  196,  203,
-      203,  196,  196,    0,  196,  196,  196,  196,  196,  196,
-      196,    0,  210,  202,  205,  199,  203,  205,  205,  211,
-      204,    0,  199,  204,  204,  206,    0,  207,  206,  206,
-      207,  207,  208,  212,  213,  208,  208,  214,  203,  210,
-      196,  197,  199,  203,  197,  197,  211,  197,  197,  197,
-      197,  197,  197,  197,  204,  216,  205,  217,  218,  219,
-      212,  213,  204,  220,  214,  221,  208,  206,  222,  207,
-      223,  224,  225,  226,  208,  228,  229,  230,  231,  232,
-
-      233,  204,  216,  197,  217,  218,  219,  234,  235,  236,
-      220,  237,  221,  208,    0,  222,    0,  223,  224,  225,
-      226,    0,  228,  229,  230,  231,  232,  233,  240,    0,
-        0,  240,  240,    0,  234,  235,  236,  241,  237,  239,
-      241,  241,  239,  239,    0,  239,  239,  239,  239,  239,
-      239,  239,  242,  251,    0,  242,  242,  241,  243,    0,
-      242,  243,  243,  244,    0,  252,  244,  244,  243,  245,
-      240,  246,  245,  245,  246,  246,  253,  254,    0,  241,
-      251,  239,  247,  255,  241,  247,  247,  248,  258,  259,
-      248,  248,  252,  261,  242,  263,  264,    0,  262,  266,
-
-      243,  268,    0,  253,  254,  244,  262,  270,  271,  272,
-      255,  245,  273,  246,  274,  258,  259,  275,    0,    0,
-      261,    0,  263,  264,  247,  262,  266,  279,  268,  248,
-      279,  279,  281,  262,  270,  271,  272,  282,  283,  273,
-      285,  274,    0,  278,  275,  277,  278,  278,  277,  277,
-      286,  277,  277,  277,  277,  277,  277,  277,  280,  281,
-        0,  280,  280,  287,  282,  283,  288,  285,  289,  279,
-      290,  292,  278,    0,  293,  294,  295,  286,  296,  297,
-      298,  299,  301,  302,  302,  278,  303,  277,  305,  306,
-      287,  308,  309,  288,    0,  289,  312,  290,  292,  278,
-
-      280,  293,  294,  295,  313,  296,  297,  298,  299,  301,
-      302,  302,  314,  303,  315,  305,  306,  310,  308,  309,
-      310,  310,  311,  312,  316,  311,  311,  317,  319,  320,
-        0,  313,    0,  321,  322,  323,  326,    0,  327,  314,
-      328,  315,  329,  330,  331,  332,  333,  334,  336,  337,
-      335,  316,  338,  340,  317,  319,  320,  311,  335,  310,
-      321,  322,  323,  326,  311,  327,  341,  328,  343,  329,
-      330,  331,  332,  333,  334,  336,  337,  335,  339,  338,
-      340,  339,  339,  344,  311,  335,  346,  347,  348,  351,
-      355,  356,  357,  341,  358,  343,  359,  360,  361,  362,
-
-      363,  364,  365,  367,  368,  369,  370,  371,  372,  373,
-      344,  374,  375,  346,  347,  348,  351,  355,  356,  357,
-      339,  358,  376,  359,  360,  361,  362,  363,  364,  365,
-      367,  368,  369,  370,  371,  372,  373,  378,  374,  375,
-      379,  380,  381,  382,  383,  384,  385,  386,  388,  376,
-      389,  390,  391,  393,  394,  395,  396,  397,  398,  399,
-      400,  401,  402,  403,  378,  404,  406,  379,  380,  381,
-      382,  383,  384,  385,  386,  388,  407,  389,  390,  391,
-      393,  394,  395,  396,  397,  398,  399,  400,  401,  402,
-      403,  412,  404,  406,  413,  415,  416,  417,  418,  420,
-
-      421,  422,  423,  407,  424,  426,  428,  429,  431,  432,
-      433,  435,  436,  437,  438,  440,  441,  442,  412,  443,
-      444,  413,  415,  416,  417,  418,  420,  421,  422,  423,
-      446,  424,  426,  428,  429,  431,  432,  433,  435,  436,
-      437,  438,  440,  441,  442,  449,  443,  444,  450,  452,
-      453,  455,  456,  457,  458,  459,  460,  446,  461,  462,
-      464,  465,  470,  471,  473,  474,  475,  476,  477,  478,
-      480,  481,  449,  484,  485,  450,  452,  453,  455,  456,
-      457,  458,  459,  460,  486,  461,  462,  464,  465,  470,
-      471,  473,  474,  475,  476,  477,  478,  480,  481,  489,
-
-      484,  485,  490,  492,  494,  497,  500,  501,  505,  506,
-      507,  486,  508,  509,    0,    0,    0,    0,    0,    0,
-        0,    0,    0,    0,    0,    0,  489,    0,    0,  490,
-      492,  494,  497,  500,  501,  505,  506,  507,    0,  508,
-      509,  514,    0,  514,  516,  516,  516,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513,  513,  513,  513,  513,  513,  513,  513,  513,  513,
-      513
+        1,    1,    1,    1,    8,   11,   15,   11,   11,   11,
+       11,   11,   11,   11,   12,   12,   12,   12,   12,   12,
+       12,   14,   16,   17,   14,   18,   16,   19,   20,   23,
+
+       22,   24,   25,   23,   15,   27,   17,   58,   59,   60,
+       61,   22,   63,   66,   67,   68,    8,   22,   94,   14,
+       16,   17,   14,   18,   16,   19,   20,   23,   22,   24,
+       25,   23,  524,  179,   17,   58,   59,   60,   61,   22,
+       63,   66,   67,   68,  179,   22,   94,   27,   30,   30,
+       30,   30,   30,   30,   30,  522,   95,   96,   30,   30,
+       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
+       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
+       30,   30,   30,   30,   95,   96,   30,   30,   30,   30,
+       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
+
+       30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
+       30,   30,   31,   31,   31,   31,   31,   31,   31,   32,
+      517,   33,   32,   32,   33,   33,  506,   33,   33,   33,
+       33,   33,   33,   33,   34,  505,  500,   34,   34,  495,
+       34,   34,   34,   34,   34,   34,   34,   35,   35,   35,
+       35,   35,   35,   35,   36,  494,   37,   36,   36,   37,
+       37,  490,   32,   38,   33,  275,   38,   38,   97,   39,
+       57,  479,   39,   39,   37,   44,  275,   34,   44,   44,
+       38,   40,   57,   36,   40,   40,   41,   98,   39,   41,
+       41,   42,  100,   44,   42,   42,   97,   36,   57,   37,
+
+      476,   43,   37,  461,   43,   43,   38,  455,   38,  101,
+       57,   36,   39,   41,   40,   98,   39,  102,   44,   45,
+      100,   44,   45,   45,   40,   43,  454,   47,   42,   41,
+       47,   47,   70,  104,   42,   70,   70,  101,   47,  432,
+      426,   41,   40,  417,   43,  102,   48,  416,   45,   48,
+       48,  415,  412,   43,   49,  361,   42,   49,   49,  357,
+      105,  104,   45,   50,  356,   48,   50,   50,   51,  352,
+       47,   51,   51,  107,  349,   70,   45,   46,   46,   46,
+       46,   46,   46,   46,   46,   46,   46,   49,  105,   48,
+      332,  331,   50,   48,   46,   46,   46,   49,   62,  108,
+
+       52,  107,   51,   52,   52,   53,   50,  106,   53,   53,
+      325,   51,   62,  311,  106,   49,  110,   64,   62,   64,
+       50,   64,   65,   46,   46,   75,   62,  108,   75,   75,
+       51,   65,   65,   52,  103,  106,  111,  103,   65,  112,
+       62,   53,  106,   52,  110,   64,   62,   64,   53,   64,
+       65,   69,   69,   69,   69,   69,   69,   69,  290,   65,
+       65,   52,  103,  282,  111,  103,   65,  112,   75,   53,
+       56,   56,   56,  113,  133,  273,   56,   56,  271,  266,
+      134,  136,   56,  137,   56,  139,   56,   56,   56,   56,
+       56,   73,   73,   73,   73,   73,   73,   73,   56,   56,
+
+       56,  113,  133,   74,   56,   56,   74,   74,  134,  136,
+       56,  137,   56,  139,   56,   56,   56,   56,   56,   71,
+      263,  262,   71,   71,  256,   71,   71,   71,   71,   71,
+       71,   71,   72,  255,  233,   72,   72,   74,   72,   72,
+       72,   72,   72,   72,   72,   76,   74,   77,   76,   76,
+       77,   77,   78,  199,  195,   78,   78,   79,  140,  141,
+       79,   79,   71,   80,  142,   74,   80,   80,  143,   81,
+       80,  187,   81,   81,  186,   72,  153,  149,  145,   99,
+       82,   76,   78,   82,   82,  144,  140,  141,   76,   81,
+       77,   79,  142,   54,   83,   78,  143,   83,   83,   84,
+
+       79,   87,   84,   84,   87,   87,   80,   82,   29,   76,
+       78,   26,   81,  144,   21,  146,   10,   81,   89,   79,
+       83,   89,   89,   82,    9,    3,   88,    2,   90,   88,
+       88,   90,   90,    0,    0,   82,   92,   83,    0,   92,
+       92,    0,   84,  146,   87,    0,   89,   90,   83,   85,
+       85,   85,   85,   85,   85,   85,   85,   85,   85,    0,
+       91,   89,   88,   91,   91,  147,   85,   85,   85,   88,
+        0,   90,  109,   92,   89,   90,  135,  138,   93,   92,
+       91,   93,   93,  148,  135,  150,  138,  109,  138,  151,
+       88,  152,  155,  147,  154,   85,   85,  174,   93,    0,
+
+      109,   92,    0,   91,  135,  138,  132,  175,   91,  132,
+      132,  148,  135,  150,  138,  109,  138,  151,    0,  152,
+      155,   93,    0,    0,  154,  174,   93,  114,  114,  114,
+      114,  114,  114,  114,  115,  175,    0,  115,  115,    0,
+      115,  115,  115,  115,  115,  115,  115,  116,  176,  132,
+      116,  116,  154,  116,  116,  116,  116,  116,  116,  116,
+      117,    0,    0,  117,  117,    0,  117,  117,  117,  117,
+      117,  117,  117,    0,  177,    0,  176,  115,  118,  118,
+      118,  118,  118,  118,  118,  119,    0,    0,  119,  119,
+      116,  120,  178,  121,  120,  120,  121,  121,    0,  180,
+
+        0,  122,  177,  117,  122,  122,    0,  123,    0,  119,
+      123,  123,  124,  120,  126,  124,  124,  126,  126,  181,
+      178,  122,    0,  123,  182,  183,  121,  180,  119,  125,
+        0,    0,  125,  125,  120,  124,  121,  119,  126,    0,
+      184,  120,  127,    0,  122,  127,  127,  181,    0,  122,
+      123,  123,  182,  183,  121,  124,  128,  126,  129,  128,
+      128,  129,  129,  124,    0,  125,  126,  130,  184,  127,
+      130,  130,  125,    0,  131,    0,  158,  131,  131,  158,
+      158,    0,    0,  161,  185,  127,  161,  161,  129,    0,
+      188,    0,  128,  125,  131,  189,  190,  127,    0,  128,
+
+        0,  129,  130,  156,  156,  156,  156,  156,  156,  156,
+      130,  160,  185,    0,  160,  160,  129,  131,  188,  158,
+      128,    0,  131,  189,  190,  157,  161,    0,  157,  157,
+      130,  157,  157,  157,  157,  157,  157,  157,  159,  159,
+      159,  159,  159,  159,  159,  160,  162,    0,  163,  162,
+      162,  163,  163,  164,  160,  165,  164,  164,  165,  165,
+        0,    0,  166,    0,  165,  166,  166,  165,  157,    0,
+        0,  167,    0,  160,  167,  167,    0,  168,    0,  169,
+      168,  168,  169,  169,  170,  191,    0,  170,  170,  162,
+      167,  163,    0,  192,    0,  169,  164,  171,  165,  172,
+
+      171,  171,  172,  172,  173,  166,  168,  173,  173,    0,
+      193,  194,    0,  191,  167,  196,  198,  170,  167,    0,
+      168,  192,  169,  169,  200,  171,  197,  170,  207,  197,
+        0,  207,  207,    0,  168,    0,  207,  173,  193,  194,
+      171,    0,  172,  196,  198,  170,    0,  173,    0,    0,
+        0,    0,  200,  171,  197,    0,  215,  197,  201,  201,
+      201,  201,  201,  201,  201,  173,  202,    0,    0,  202,
+      202,  207,  202,  202,  202,  202,  202,  202,  202,  203,
+      216,    0,  203,  203,  215,  203,  203,  203,  203,  203,
+      203,  203,  205,    0,  206,  205,  205,  206,  206,    0,
+
+        0,  208,    0,  206,  208,  208,  206,    0,  216,  202,
+      209,  208,    0,  209,  209,  217,  210,  218,  219,  210,
+      210,  211,  203,  220,  211,  211,  222,  205,  212,  223,
+      209,  212,  212,  224,  225,  205,  213,  206,  214,  213,
+      213,  214,  214,  217,  208,  218,  219,  226,  227,  228,
+      210,  220,  229,  209,  222,  205,  230,  223,  209,  210,
+      231,  224,  225,  232,  211,  234,  235,  236,  237,  238,
+      239,  212,  214,  240,  241,  226,  227,  228,  210,  213,
+      229,  214,  242,  243,  230,    0,  246,    0,  231,  246,
+      246,  232,    0,  234,  235,  236,  237,  238,  239,    0,
+
+      214,  240,  241,  247,    0,  257,  247,  247,    0,  245,
+      242,  243,  245,  245,    0,  245,  245,  245,  245,  245,
+      245,  245,  248,  247,  249,  248,  248,  249,  249,  246,
+      248,  258,  250,  257,  249,  250,  250,  251,  259,  252,
+      251,  251,  252,  252,  253,  260,  247,  253,  253,  261,
+      254,  247,  245,  254,  254,  264,  265,  267,  269,  258,
+      268,  270,  272,  274,  276,  248,  259,  249,  268,  277,
+      278,  279,  280,  260,  281,  250,    0,  261,  287,    0,
+      251,    0,  252,  264,  265,  267,  269,  253,  268,  270,
+      272,  274,  276,  254,  288,  289,  268,  277,  278,  279,
+
+      280,  283,  281,  291,  283,  283,  287,  283,  283,  283,
+      283,  283,  283,  283,  284,    0,  285,  284,  284,  285,
+      285,  286,  288,  289,  286,  286,  292,  293,  294,    0,
+      295,  291,  296,  298,  299,  300,    0,  301,  302,  303,
+      304,  305,  307,  284,  283,  308,  308,  310,  312,  313,
+      315,  316,    0,  319,  292,  293,  294,  284,  295,  285,
+      296,  298,  299,  300,  286,  301,  302,  303,  304,  305,
+      307,  284,  320,  308,  308,  310,  312,  313,  315,  316,
+      317,  319,  318,  317,  317,  318,  318,  321,  322,    0,
+      323,  324,  326,  327,  328,    0,  329,    0,  330,  333,
+
+      320,  334,  335,  336,  337,  338,  339,  340,  341,  343,
+      346,  344,  345,  346,  346,  321,  322,  318,  323,  324,
+      326,  327,  328,  317,  329,  318,  330,  333,  347,  334,
+      335,  336,  337,  338,  339,  340,  341,  343,  342,  344,
+      345,  348,  350,  351,  353,  318,  342,  354,  355,  358,
+      362,  363,  364,  346,  365,  366,  347,  367,  368,  369,
+      370,  371,  372,  374,  375,  376,  342,  377,  378,  348,
+      350,  351,  353,  379,  342,  354,  355,  358,  362,  363,
+      364,  380,  365,  366,  381,  367,  368,  369,  370,  371,
+      372,  374,  375,  376,  382,  377,  378,  383,  385,  386,
+
+      387,  379,  388,  389,  390,  391,  392,  393,  395,  380,
+      396,  397,  381,  398,  400,  401,  402,  403,  404,  405,
+      406,  407,  382,  408,  409,  383,  385,  386,  387,  410,
+      388,  389,  390,  391,  392,  393,  395,  411,  396,  397,
+      413,  398,  400,  401,  402,  403,  404,  405,  406,  407,
+      414,  408,  409,  419,  420,  422,  423,  410,  424,  425,
+      427,  428,  429,  430,  431,  411,  433,  435,  413,  436,
+      438,  439,  440,  442,  443,  444,  445,  447,  414,  448,
+      449,  419,  420,  422,  423,  450,  424,  425,  427,  428,
+      429,  430,  431,  451,  433,  435,  453,  436,  438,  439,
+
+      440,  442,  443,  444,  445,  447,  456,  448,  449,  457,
+      459,  460,  462,  450,  463,  464,  465,  466,  467,  468,
+      469,  451,  471,  472,  453,  477,  478,  480,  481,  482,
+      483,  484,  485,  487,  456,  488,  491,  457,  459,  460,
+      462,  492,  463,  464,  465,  466,  467,  468,  469,  493,
+      471,  472,  496,  477,  478,  480,  481,  482,  483,  484,
+      485,  487,  497,  488,  491,  499,  501,  504,  507,  492,
+      508,  512,  513,  514,  515,  516,    0,  493,    0,    0,
+      496,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+      497,    0,    0,  499,  501,  504,  507,    0,  508,  512,
+
+      513,  514,  515,  516,  521,  521,  523,  523,  525,  525,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520,  520,  520,  520,  520,  520,
+      520,  520,  520,  520,  520
     } ;
 
-static yyconst flex_int16_t yy_rule_linenum[64] =
+static yyconst flex_int16_t yy_rule_linenum[65] =
     {   0,
-       77,   79,   81,   83,   85,   88,   92,   94,   95,   96,
-       97,   98,   99,  100,  101,  102,  103,  104,  105,  106,
-      107,  108,  109,  110,  111,  112,  113,  114,  115,  116,
-      117,  118,  119,  120,  121,  123,  124,  126,  128,  129,
-      130,  131,  132,  133,  135,  136,  139,  144,  145,  146,
-      148,  149,  150,  151,  152,  153,  154,  155,  156,  158,
-      167,  185,  191
+       77,   79,   81,   83,   85,   88,   92,   94,   96,   97,
+       98,   99,  100,  101,  102,  103,  104,  105,  106,  107,
+      108,  109,  110,  111,  112,  113,  114,  115,  116,  117,
+      118,  119,  120,  121,  122,  123,  125,  126,  128,  130,
+      131,  132,  133,  134,  135,  137,  138,  141,  146,  147,
+      148,  150,  151,  152,  153,  154,  155,  156,  157,  158,
+      160,  169,  187,  194
     } ;
 
 /* The intent behind this definition is that it'll catch
@@ -1136,7 +1150,7 @@ static yyconst flex_int16_t yy_rule_linenum[64] =
 
 #define YY_INPUT(buffer, result, max_size) get_lex_chars(buffer, result, max_size, PARAM)
 
-#line 1140 "libmemcached/options/scanner.cc"
+#line 1154 "libmemcached/options/scanner.cc"
 
 #define INITIAL 0
 
@@ -1443,7 +1457,7 @@ YY_DECL
 
 
 
-#line 1447 "libmemcached/options/scanner.cc"
+#line 1461 "libmemcached/options/scanner.cc"
 
     yylval = yylval_param;
 
@@ -1509,13 +1523,13 @@ yy_match:
                        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                                {
                                yy_current_state = (int) yy_def[yy_current_state];
-                               if ( yy_current_state >= 514 )
+                               if ( yy_current_state >= 521 )
                                        yy_c = yy_meta[(unsigned int) yy_c];
                                }
                        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
                        ++yy_cp;
                        }
-               while ( yy_base[yy_current_state] != 1648 );
+               while ( yy_base[yy_current_state] != 1711 );
 
 yy_find_action:
 /* %% [10.0] code to find the action number goes here */
@@ -1538,13 +1552,13 @@ do_action:      /* This label is used only to access EOF actions. */
                        {
                        if ( yy_act == 0 )
                                fprintf( stderr, "--scanner backing up\n" );
-                       else if ( yy_act < 64 )
+                       else if ( yy_act < 65 )
                                fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
                                         (long)yy_rule_linenum[yy_act], yytext );
-                       else if ( yy_act == 64 )
+                       else if ( yy_act == 65 )
                                fprintf( stderr, "--accepting default rule (\"%s\")\n",
                                         yytext );
-                       else if ( yy_act == 65 )
+                       else if ( yy_act == 66 )
                                fprintf( stderr, "--(end of buffer or a NUL)\n" );
                        else
                                fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@ -1604,269 +1618,274 @@ YY_RULE_SETUP
 case 8:
 YY_RULE_SETUP
 #line 94 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return BINARY_PROTOCOL; }
+{ yyextra->begin= yytext; return SOCKET; }
        YY_BREAK
 case 9:
 YY_RULE_SETUP
-#line 95 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return BUFFER_REQUESTS; }
+#line 96 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return BINARY_PROTOCOL; }
        YY_BREAK
 case 10:
 YY_RULE_SETUP
-#line 96 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return CONFIGURE_FILE; }
+#line 97 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return BUFFER_REQUESTS; }
        YY_BREAK
 case 11:
 YY_RULE_SETUP
-#line 97 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return CONNECT_TIMEOUT; }
+#line 98 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return CONFIGURE_FILE; }
        YY_BREAK
 case 12:
 YY_RULE_SETUP
-#line 98 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return DISTRIBUTION; }
+#line 99 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return CONNECT_TIMEOUT; }
        YY_BREAK
 case 13:
 YY_RULE_SETUP
-#line 99 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return HASH_WITH_NAMESPACE; }
+#line 100 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return DISTRIBUTION; }
        YY_BREAK
 case 14:
 YY_RULE_SETUP
-#line 100 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return HASH; }
+#line 101 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return HASH_WITH_NAMESPACE; }
        YY_BREAK
 case 15:
 YY_RULE_SETUP
-#line 101 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return IO_BYTES_WATERMARK; }
+#line 102 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return HASH; }
        YY_BREAK
 case 16:
 YY_RULE_SETUP
-#line 102 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return IO_KEY_PREFETCH; }
+#line 103 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return IO_BYTES_WATERMARK; }
        YY_BREAK
 case 17:
 YY_RULE_SETUP
-#line 103 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return IO_MSG_WATERMARK; }
+#line 104 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return IO_KEY_PREFETCH; }
        YY_BREAK
 case 18:
 YY_RULE_SETUP
-#line 104 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return NOREPLY; }
+#line 105 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return IO_MSG_WATERMARK; }
        YY_BREAK
 case 19:
 YY_RULE_SETUP
-#line 105 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return NUMBER_OF_REPLICAS; }
+#line 106 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return NOREPLY; }
        YY_BREAK
 case 20:
 YY_RULE_SETUP
-#line 106 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return POLL_TIMEOUT; }
+#line 107 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return NUMBER_OF_REPLICAS; }
        YY_BREAK
 case 21:
 YY_RULE_SETUP
-#line 107 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return RANDOMIZE_REPLICA_READ; }
+#line 108 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return POLL_TIMEOUT; }
        YY_BREAK
 case 22:
 YY_RULE_SETUP
-#line 108 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return RCV_TIMEOUT; }
+#line 109 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return RANDOMIZE_REPLICA_READ; }
        YY_BREAK
 case 23:
 YY_RULE_SETUP
-#line 109 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return REMOVE_FAILED_SERVERS; }
+#line 110 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return RCV_TIMEOUT; }
        YY_BREAK
 case 24:
 YY_RULE_SETUP
-#line 110 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return RETRY_TIMEOUT; }
+#line 111 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return REMOVE_FAILED_SERVERS; }
        YY_BREAK
 case 25:
 YY_RULE_SETUP
-#line 111 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return SND_TIMEOUT; }
+#line 112 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return RETRY_TIMEOUT; }
        YY_BREAK
 case 26:
 YY_RULE_SETUP
-#line 112 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return SOCKET_RECV_SIZE; }
+#line 113 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return SND_TIMEOUT; }
        YY_BREAK
 case 27:
 YY_RULE_SETUP
-#line 113 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return SOCKET_SEND_SIZE; }
+#line 114 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return SOCKET_RECV_SIZE; }
        YY_BREAK
 case 28:
 YY_RULE_SETUP
-#line 114 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return SORT_HOSTS; }
+#line 115 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return SOCKET_SEND_SIZE; }
        YY_BREAK
 case 29:
 YY_RULE_SETUP
-#line 115 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return SUPPORT_CAS; }
+#line 116 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return SORT_HOSTS; }
        YY_BREAK
 case 30:
 YY_RULE_SETUP
-#line 116 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return _TCP_KEEPALIVE; }
+#line 117 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return SUPPORT_CAS; }
        YY_BREAK
 case 31:
 YY_RULE_SETUP
-#line 117 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return _TCP_KEEPIDLE; }
+#line 118 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return _TCP_KEEPALIVE; }
        YY_BREAK
 case 32:
 YY_RULE_SETUP
-#line 118 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return _TCP_NODELAY; }
+#line 119 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return _TCP_KEEPIDLE; }
        YY_BREAK
 case 33:
 YY_RULE_SETUP
-#line 119 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return USE_UDP; }
+#line 120 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return _TCP_NODELAY; }
        YY_BREAK
 case 34:
 YY_RULE_SETUP
-#line 120 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return USER_DATA; }
+#line 121 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return USE_UDP; }
        YY_BREAK
 case 35:
 YY_RULE_SETUP
-#line 121 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return VERIFY_KEY; }
+#line 122 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return USER_DATA; }
        YY_BREAK
 case 36:
 YY_RULE_SETUP
 #line 123 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return POOL_MIN; }
+{ yyextra->begin= yytext; return VERIFY_KEY; }
        YY_BREAK
 case 37:
 YY_RULE_SETUP
-#line 124 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return POOL_MAX; }
+#line 125 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return POOL_MIN; }
        YY_BREAK
 case 38:
 YY_RULE_SETUP
 #line 126 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return NAMESPACE; }
+{ yyextra->begin= yytext; return POOL_MAX; }
        YY_BREAK
 case 39:
 YY_RULE_SETUP
 #line 128 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return INCLUDE; }
+{ yyextra->begin= yytext; return NAMESPACE; }
        YY_BREAK
 case 40:
 YY_RULE_SETUP
-#line 129 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return RESET; }
+#line 130 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return INCLUDE; }
        YY_BREAK
 case 41:
 YY_RULE_SETUP
-#line 130 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return PARSER_DEBUG; }
+#line 131 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return RESET; }
        YY_BREAK
 case 42:
 YY_RULE_SETUP
-#line 131 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return SERVERS; }
+#line 132 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return PARSER_DEBUG; }
        YY_BREAK
 case 43:
 YY_RULE_SETUP
-#line 132 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return END; }
+#line 133 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return SERVERS; }
        YY_BREAK
 case 44:
 YY_RULE_SETUP
-#line 133 "libmemcached/options/scanner.l"
-{ yyextra->begin= yytext; return ERROR; }
+#line 134 "libmemcached/options/scanner.l"
+{ yyextra->begin= yytext; return END; }
        YY_BREAK
 case 45:
 YY_RULE_SETUP
 #line 135 "libmemcached/options/scanner.l"
-{ return TRUE; }
+{ yyextra->begin= yytext; return ERROR; }
        YY_BREAK
 case 46:
 YY_RULE_SETUP
-#line 136 "libmemcached/options/scanner.l"
-{ return FALSE; }
+#line 137 "libmemcached/options/scanner.l"
+{ return TRUE; }
        YY_BREAK
 case 47:
 YY_RULE_SETUP
-#line 139 "libmemcached/options/scanner.l"
+#line 138 "libmemcached/options/scanner.l"
+{ return FALSE; }
+       YY_BREAK
+case 48:
+YY_RULE_SETUP
+#line 141 "libmemcached/options/scanner.l"
 {
       yyextra->begin= yytext;
       return UNKNOWN_OPTION;
     }
        YY_BREAK
-case 48:
-YY_RULE_SETUP
-#line 144 "libmemcached/options/scanner.l"
-{ return CONSISTENT; }
-       YY_BREAK
 case 49:
 YY_RULE_SETUP
-#line 145 "libmemcached/options/scanner.l"
-{ return MODULA; }
+#line 146 "libmemcached/options/scanner.l"
+{ return CONSISTENT; }
        YY_BREAK
 case 50:
 YY_RULE_SETUP
-#line 146 "libmemcached/options/scanner.l"
-{ return RANDOM; }
+#line 147 "libmemcached/options/scanner.l"
+{ return MODULA; }
        YY_BREAK
 case 51:
 YY_RULE_SETUP
 #line 148 "libmemcached/options/scanner.l"
-{ return MD5; }
+{ return RANDOM; }
        YY_BREAK
 case 52:
 YY_RULE_SETUP
-#line 149 "libmemcached/options/scanner.l"
-{ return CRC; }
+#line 150 "libmemcached/options/scanner.l"
+{ return MD5; }
        YY_BREAK
 case 53:
 YY_RULE_SETUP
-#line 150 "libmemcached/options/scanner.l"
-{ return FNV1_64; }
+#line 151 "libmemcached/options/scanner.l"
+{ return CRC; }
        YY_BREAK
 case 54:
 YY_RULE_SETUP
-#line 151 "libmemcached/options/scanner.l"
-{ return FNV1A_64; }
+#line 152 "libmemcached/options/scanner.l"
+{ return FNV1_64; }
        YY_BREAK
 case 55:
 YY_RULE_SETUP
-#line 152 "libmemcached/options/scanner.l"
-{ return FNV1_32; }
+#line 153 "libmemcached/options/scanner.l"
+{ return FNV1A_64; }
        YY_BREAK
 case 56:
 YY_RULE_SETUP
-#line 153 "libmemcached/options/scanner.l"
-{ return FNV1A_32; }
+#line 154 "libmemcached/options/scanner.l"
+{ return FNV1_32; }
        YY_BREAK
 case 57:
 YY_RULE_SETUP
-#line 154 "libmemcached/options/scanner.l"
-{ return HSIEH; }
+#line 155 "libmemcached/options/scanner.l"
+{ return FNV1A_32; }
        YY_BREAK
 case 58:
 YY_RULE_SETUP
-#line 155 "libmemcached/options/scanner.l"
-{ return MURMUR; }
+#line 156 "libmemcached/options/scanner.l"
+{ return HSIEH; }
        YY_BREAK
 case 59:
 YY_RULE_SETUP
-#line 156 "libmemcached/options/scanner.l"
-{ return JENKINS; }
+#line 157 "libmemcached/options/scanner.l"
+{ return MURMUR; }
        YY_BREAK
 case 60:
 YY_RULE_SETUP
 #line 158 "libmemcached/options/scanner.l"
+{ return JENKINS; }
+       YY_BREAK
+case 61:
+YY_RULE_SETUP
+#line 160 "libmemcached/options/scanner.l"
 {
       yylval->server.port= MEMCACHED_DEFAULT_PORT;
       yylval->server.weight= 1;
@@ -1876,9 +1895,9 @@ YY_RULE_SETUP
       return IPADDRESS;
     }
        YY_BREAK
-case 61:
+case 62:
 YY_RULE_SETUP
-#line 167 "libmemcached/options/scanner.l"
+#line 169 "libmemcached/options/scanner.l"
 {
       if (yyextra->is_server())
       {
@@ -1897,29 +1916,31 @@ YY_RULE_SETUP
       return STRING;
     }
        YY_BREAK
-case 62:
+case 63:
+/* rule 63 can match eol */
 YY_RULE_SETUP
-#line 185 "libmemcached/options/scanner.l"
+#line 187 "libmemcached/options/scanner.l"
 {
-      yylval->string.c_str = yytext;
-      yylval->string.size = yyleng;
+      config_get_text(yyscanner)[yyleng -1]= 0;
+      yylval->string.c_str= yytext +1;
+      yylval->string.size= yyleng -2;
       return QUOTED_STRING;
     }
        YY_BREAK
-case 63:
+case 64:
 YY_RULE_SETUP
-#line 191 "libmemcached/options/scanner.l"
+#line 194 "libmemcached/options/scanner.l"
 {
       yyextra->begin= yytext;
       return UNKNOWN;
     }
        YY_BREAK
-case 64:
+case 65:
 YY_RULE_SETUP
-#line 196 "libmemcached/options/scanner.l"
+#line 199 "libmemcached/options/scanner.l"
 ECHO;
        YY_BREAK
-#line 1923 "libmemcached/options/scanner.cc"
+#line 1944 "libmemcached/options/scanner.cc"
 case YY_STATE_EOF(INITIAL):
        yyterminate();
 
@@ -2235,7 +2256,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
                while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                        {
                        yy_current_state = (int) yy_def[yy_current_state];
-                       if ( yy_current_state >= 514 )
+                       if ( yy_current_state >= 521 )
                                yy_c = yy_meta[(unsigned int) yy_c];
                        }
                yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -2269,11 +2290,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
        while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
                {
                yy_current_state = (int) yy_def[yy_current_state];
-               if ( yy_current_state >= 514 )
+               if ( yy_current_state >= 521 )
                        yy_c = yy_meta[(unsigned int) yy_c];
                }
        yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
-       yy_is_jam = (yy_current_state == 513);
+       yy_is_jam = (yy_current_state == 520);
 
        return yy_is_jam ? 0 : yy_current_state;
 }
@@ -3185,7 +3206,7 @@ void config_free (void * ptr , yyscan_t yyscanner)
 
 /* %ok-for-header */
 
-#line 196 "libmemcached/options/scanner.l"
+#line 199 "libmemcached/options/scanner.l"
 
 
 
index 3e7b5aee09b3f8d86dd5c9cc9b6806bb5f065b5e..5a16f0807e45b1257953696a31411d1e9f731cb3 100644 (file)
@@ -471,7 +471,7 @@ extern int config_lex \
 #undef YY_DECL
 #endif
 
-#line 196 "libmemcached/options/scanner.l"
+#line 199 "libmemcached/options/scanner.l"
 
 
 #line 478 "libmemcached/options/scanner.h"
diff --git a/libmemcached/prefix_key.cc b/libmemcached/prefix_key.cc
deleted file mode 100644 (file)
index 8a24190..0000000
+++ /dev/null
@@ -1,65 +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>
-
-memcached_return_t memcached_set_prefix_key(memcached_st *self, const char *key, size_t key_length)
-{
-  WATCHPOINT_ASSERT(self);
-
-  if (key and key_length)
-  {
-    if (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)
-      return memcached_set_error(*self, MEMCACHED_BAD_KEY_PROVIDED, MEMCACHED_AT);
-
-    if ((key_length > MEMCACHED_PREFIX_KEY_MAX_SIZE -1))
-      return memcached_set_error(*self, MEMCACHED_KEY_TOO_BIG, MEMCACHED_AT);
-
-    memcached_array_free(self->prefix_key);
-    self->prefix_key= memcached_strcpy(self, key, key_length);
-
-    if (not self->prefix_key)
-      return memcached_set_error(*self, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
-  }
-  else
-  {
-    memcached_array_free(self->prefix_key);
-    self->prefix_key= NULL;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
diff --git a/libmemcached/prefix_key.h b/libmemcached/prefix_key.h
deleted file mode 100644 (file)
index bd81160..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_LOCAL
-  memcached_return_t memcached_set_prefix_key(memcached_st *self, const char *str, size_t length);
-
-#ifdef __cplusplus
-}
-#endif
index ff1d77b1bd7954a4f69bf7c7b0d603baccf138c4..1548b4ed23c847f1ad2a6f70d4680809803b959a 100644 (file)
@@ -58,9 +58,13 @@ memcached_return_t memcached_read_one_response(memcached_server_write_instance_s
 
   memcached_return_t rc;
   if (ptr->root->flags.binary_protocol)
+  {
     rc= binary_read_one_response(ptr, buffer, buffer_length, result);
+  }
   else
+  {
     rc= textual_read_one_response(ptr, buffer, buffer_length, result);
+  }
 
   unlikely(rc == MEMCACHED_UNKNOWN_READ_FAILURE or
            rc == MEMCACHED_PROTOCOL_ERROR or
@@ -138,7 +142,7 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
     key= result->item_key;
     result->key_length= 0;
 
-    for (prefix_length= memcached_array_size(ptr->root->prefix_key); !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
+    for (prefix_length= memcached_array_size(ptr->root->_namespace); !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
     {
       if (prefix_length == 0)
       {
@@ -214,7 +218,7 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
     if (memcached_failed(rrc) and rrc == MEMCACHED_IN_PROGRESS)
     {
       memcached_quit_server(ptr, true);
-      return memcached_set_error(*ptr, rrc, MEMCACHED_AT);
+      return memcached_set_error(*ptr, MEMCACHED_IN_PROGRESS, MEMCACHED_AT);
     }
     else if (memcached_failed(rrc))
     {
@@ -283,36 +287,16 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
       }
       else if (buffer[1] == 'E') /* SERVER_ERROR */
       {
-        char *rel_ptr;
         char *startptr= buffer + 13, *endptr= startptr;
 
         while (*endptr != '\r' && *endptr != '\n') endptr++;
 
-        /*
-          Yes, we could make this "efficent" but to do that we would need
-          to maintain more state for the size of the buffer. Why waste
-          memory in the struct, which is important, for something that
-          rarely should happen?
-        */
-        rel_ptr= (char *)libmemcached_realloc(ptr->root,
-                                              ptr->cached_server_error,
-                                              (size_t) (endptr - startptr + 1));
-
-        if (rel_ptr == NULL)
-        {
-          /* If we happened to have some memory, we just null it since we don't know the size */
-          if (ptr->cached_server_error)
-            ptr->cached_server_error[0]= 0;
-          return MEMCACHED_SERVER_ERROR;
-        }
-        ptr->cached_server_error= rel_ptr;
-
-        memcpy(ptr->cached_server_error, startptr, (size_t) (endptr - startptr));
-        ptr->cached_server_error[endptr - startptr]= 0;
-        return MEMCACHED_SERVER_ERROR;
+        return memcached_set_error(*ptr, MEMCACHED_SERVER_ERROR, MEMCACHED_AT, startptr, size_t(endptr - startptr));
       }
       else if (buffer[1] == 'T')
+      {
         return MEMCACHED_STORED;
+      }
       else
       {
         WATCHPOINT_STRING(buffer);
@@ -321,6 +305,7 @@ static memcached_return_t textual_read_one_response(memcached_server_write_insta
     }
   case 'D': /* DELETED */
     return MEMCACHED_DELETED;
+
   case 'N': /* NOT_FOUND */
     {
       if (buffer[4] == 'F')
@@ -424,19 +409,35 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
         bodylen -= header.response.extlen;
 
         result->key_length= keylen;
-        if ((rc= memcached_safe_read(ptr, result->item_key, keylen)) != MEMCACHED_SUCCESS)
+        if (memcached_failed(rc= memcached_safe_read(ptr, 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(ptr->root->_namespace) and memcached_array_size(ptr->root->_namespace) >= result->key_length)
+          {
+            return memcached_set_error(*ptr, MEMCACHED_UNKNOWN_READ_FAILURE, MEMCACHED_AT);
+          }
+
+          if (memcached_array_size(ptr->root->_namespace))
+          {
+            result->key_length-= memcached_array_size(ptr->root->_namespace);
+            memmove(result->item_key, result->item_key +memcached_array_size(ptr->root->_namespace), result->key_length);
+          }
+        }
+
         bodylen -= keylen;
-        if (memcached_string_check(&result->value,
-                                   bodylen) != MEMCACHED_SUCCESS)
+        if (memcached_failed(memcached_string_check(&result->value, bodylen)))
+        {
           return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+        }
 
         char *vptr= memcached_string_value_mutable(&result->value);
-        if ((rc= memcached_safe_read(ptr, vptr, bodylen)) != MEMCACHED_SUCCESS)
+        if (memcached_failed(rc= memcached_safe_read(ptr, vptr, bodylen)))
         {
           WATCHPOINT_ERROR(rc);
           return MEMCACHED_UNKNOWN_READ_FAILURE;
@@ -445,11 +446,14 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
         memcached_string_set_length(&result->value, bodylen);
       }
       break;
+
     case PROTOCOL_BINARY_CMD_INCREMENT:
     case PROTOCOL_BINARY_CMD_DECREMENT:
       {
         if (bodylen != sizeof(uint64_t) || buffer_length != sizeof(uint64_t))
+        {
           return MEMCACHED_PROTOCOL_ERROR;
+        }
 
         WATCHPOINT_ASSERT(bodylen == buffer_length);
         uint64_t val;
@@ -463,6 +467,7 @@ static memcached_return_t binary_read_one_response(memcached_server_write_instan
         memcpy(buffer, &val, sizeof(val));
       }
       break;
+
     case PROTOCOL_BINARY_CMD_SASL_LIST_MECHS:
     case PROTOCOL_BINARY_CMD_VERSION:
       {
index ea88967d444716d4599e8194f832d12b2436a0c2..f5fe62e19bf3729fe867c1542c29bc286196ee45 100644 (file)
@@ -50,7 +50,6 @@ static inline void _server_init(memcached_server_st *self, memcached_st *root,
   self->number_of_hosts= 0;
   self->cursor_active= 0;
   self->port= port;
-  self->cached_errno= 0;
   self->fd= -1;
   self->io_bytes_sent= 0;
   self->server_failure_counter= 0;
@@ -61,8 +60,8 @@ static inline void _server_init(memcached_server_st *self, memcached_st *root,
   self->micro_version= UINT8_MAX;
   self->minor_version= UINT8_MAX;
   self->type= type;
+  self->error_messages= NULL;
   self->read_ptr= self->read_buffer;
-  self->cached_server_error= NULL;
   self->read_buffer_length= 0;
   self->read_data_length= 0;
   self->write_buffer_offset= 0;
@@ -113,10 +112,10 @@ static memcached_server_st *_server_create(memcached_server_st *self, const memc
   return self;
 }
 
-memcached_server_st *memcached_server_create_with(const memcached_st *memc,
-                                                  memcached_server_write_instance_st self,
-                                                  const char *hostname, in_port_t port,
-                                                  uint32_t weight, memcached_connection_t type)
+memcached_server_st *__server_create_with(const memcached_st *memc,
+                                          memcached_server_write_instance_st self,
+                                          const char *hostname, in_port_t port,
+                                          uint32_t weight, memcached_connection_t type)
 {
   self= _server_create(self, memc);
 
@@ -135,18 +134,16 @@ memcached_server_st *memcached_server_create_with(const memcached_st *memc,
   return self;
 }
 
-void memcached_server_free(memcached_server_st *self)
+void __server_free(memcached_server_st *self)
 {
-  if (not self)
-    return;
-
   memcached_quit_server(self, false);
 
-  if (self->cached_server_error)
-    free(self->cached_server_error);
-
   if (self->address_info)
+  {
     freeaddrinfo(self->address_info);
+  }
+
+  memcached_error_free(*self);
 
   if (memcached_is_allocated(self))
   {
@@ -158,6 +155,20 @@ void memcached_server_free(memcached_server_st *self)
   }
 }
 
+void memcached_server_free(memcached_server_st *self)
+{
+  if (not self)
+    return;
+
+  if (memcached_server_list_count(self))
+  {
+    memcached_server_list_free(self);
+    return;
+  }
+
+  __server_free(self);
+}
+
 /*
   If we do not have a valid object to clone from, we toss an error.
 */
@@ -168,15 +179,15 @@ memcached_server_st *memcached_server_clone(memcached_server_st *destination,
   if (not source)
     return NULL;
 
-  destination= memcached_server_create_with(source->root, destination,
-                                            source->hostname, source->port, source->weight,
-                                            source->type);
+  destination= __server_create_with(source->root, destination,
+                                    source->hostname, source->port, source->weight,
+                                    source->type);
   if (not destination)
   {
-    destination->cached_errno= source->cached_errno;
-
-    if (source->cached_server_error)
-      destination->cached_server_error= strdup(source->cached_server_error);
+    if (source->error_messages)
+    {
+      destination->error_messages= memcached_error_copy(*source);
+    }
   }
 
   return destination;
@@ -194,6 +205,7 @@ memcached_return_t memcached_server_cursor(const memcached_st *ptr,
     return rc;
   }
 
+  size_t errors= 0;
   for (uint32_t x= 0; x < memcached_server_count(ptr); x++)
   {
     memcached_server_instance_st instance=
@@ -201,16 +213,17 @@ memcached_return_t memcached_server_cursor(const memcached_st *ptr,
 
     for (uint32_t y= 0; y < number_of_callbacks; y++)
     {
-      unsigned int iferror;
+      memcached_return_t ret= (*callback[y])(ptr, instance, context);
 
-      iferror= (*callback[y])(ptr, instance, context);
-
-      if (iferror)
+      if (memcached_failed(ret))
+      {
+        errors++;
         continue;
+      }
     }
   }
 
-  return MEMCACHED_SUCCESS;
+  return errors ? MEMCACHED_SOME_ERRORS : MEMCACHED_SUCCESS;
 }
 
 memcached_return_t memcached_server_execute(memcached_st *ptr,
@@ -253,7 +266,7 @@ memcached_server_instance_st memcached_server_by_key(const memcached_st *ptr,
     return NULL;
   }
 
-  if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
+  if (memcached_failed((memcached_key_test(*ptr, (const char **)&key, &key_length, 1))))
   {
     *error= MEMCACHED_BAD_KEY_PROVIDED;
     return NULL;
@@ -270,7 +283,7 @@ void memcached_server_error_reset(memcached_server_st *self)
   if (not self)
     return;
 
-  self->cached_server_error[0]= 0;
+  memcached_error_free(*self);
 }
 
 memcached_server_instance_st memcached_server_get_last_disconnect(const memcached_st *self)
@@ -282,23 +295,6 @@ memcached_server_instance_st memcached_server_get_last_disconnect(const memcache
   return self->last_disconnected_server;
 }
 
-void memcached_server_list_free(memcached_server_list_st self)
-{
-  if (not self)
-    return;
-
-  for (uint32_t x= 0; x < memcached_server_list_count(self); x++)
-  {
-    if (self[x].address_info)
-    {
-      freeaddrinfo(self[x].address_info);
-      self[x].address_info= NULL;
-    }
-  }
-
-  libmemcached_free(self->root, self);
-}
-
 uint32_t memcached_servers_set_count(memcached_server_st *servers, uint32_t count)
 {
   WATCHPOINT_ASSERT(servers);
@@ -344,8 +340,26 @@ uint32_t memcached_server_response_count(memcached_server_instance_st self)
   return self->cursor_active;
 }
 
-const char *memcached_server_error(memcached_server_instance_st ptr)
+const char *memcached_server_type(memcached_server_instance_st ptr)
 {
-  return ptr ?  ptr->cached_server_error : NULL;
-}
+  if (ptr)
+  {
+    switch (ptr->type)
+    {
+    case MEMCACHED_CONNECTION_TCP:
+      return "TCP";
+
+    case MEMCACHED_CONNECTION_UDP:
+      return "UDP";
 
+    case MEMCACHED_CONNECTION_UNIX_SOCKET:
+      return "SOCKET";
+
+    case MEMCACHED_CONNECTION_MAX:
+    case MEMCACHED_CONNECTION_UNKNOWN:
+      break;
+    }
+  }
+
+  return "UNKNOWN";
+}
index 9000454988f7ac99dbc2d27e7c8df0b955139e6d..a45616a1010109f2f814f8682381e0dba98514f0 100644 (file)
@@ -55,7 +55,6 @@ struct memcached_server_st {
   uint32_t number_of_hosts;
   uint32_t cursor_active;
   in_port_t port;
-  int cached_errno;
   memcached_socket_t fd;
   uint32_t io_bytes_sent; /* # bytes sent since last read */
   uint32_t server_failure_counter;
@@ -70,7 +69,6 @@ struct memcached_server_st {
   uint8_t minor_version; // ditto
   memcached_connection_t type;
   char *read_ptr;
-  char *cached_server_error;
   size_t read_buffer_length;
   size_t read_data_length;
   size_t write_buffer_offset;
@@ -79,6 +77,7 @@ struct memcached_server_st {
   time_t next_retry;
   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[NI_MAXHOST];
@@ -160,9 +159,11 @@ LIBMEMCACHED_API
 in_port_t memcached_server_port(memcached_server_instance_st self);
 
 LIBMEMCACHED_API
-const char *memcached_server_error(memcached_server_instance_st ptr);
+const char *memcached_server_type(memcached_server_instance_st ptr);
 
 
+LIBMEMCACHED_LOCAL
+void __server_free(memcached_server_st *);
 
 #ifdef __cplusplus
 } // extern "C"
index 8a76bf392981ca0b1515aa970446b3129b290a6a..4da1996354daee6c8cd802d89e2acfc2b58cf485 100644 (file)
@@ -1,16 +1,44 @@
-/* LibMemcached
- * Copyright (C) 2006-2010 Brian Aker
- * All rights reserved.
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  Libmemcached library
  *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2010 Brian Aker All rights reserved.
  *
- * Summary: 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (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_server_list_st 
 memcached_server_list_append_with_weight(memcached_server_list_st ptr,
@@ -21,13 +49,23 @@ memcached_server_list_append_with_weight(memcached_server_list_st ptr,
   uint32_t count;
   memcached_server_list_st new_host_list;
 
-  if (hostname == NULL || error == NULL)
-    return NULL;
+  memcached_return_t unused;
+  if (error == NULL)
+    error= &unused;
+
+  if (hostname == NULL)
+  {
+    hostname= "localhost";
+  }
 
   if (hostname[0] == '/')
+  {
     port = 0;
-  else if (! port)
+  }
+  else if (not port)
+  {
     port= MEMCACHED_DEFAULT_PORT;
+  }
 
   /* Increment count for hosts */
   count= 1;
@@ -37,18 +75,23 @@ memcached_server_list_append_with_weight(memcached_server_list_st ptr,
   }
 
   new_host_list= (memcached_server_write_instance_st)realloc(ptr, sizeof(memcached_server_st) * count);
-  if (!new_host_list)
+  if (not new_host_list)
   {
-    ptr->cached_errno= errno;
-    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    *error= memcached_set_error(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
     return NULL;
   }
 
   /* @todo Check return type */
-  memcached_server_create_with(NULL, &new_host_list[count-1], hostname, port, weight, port ? MEMCACHED_CONNECTION_TCP : MEMCACHED_CONNECTION_UNIX_SOCKET);
+  if (not __server_create_with(NULL, &new_host_list[count-1], hostname, port, weight, port ? MEMCACHED_CONNECTION_TCP : MEMCACHED_CONNECTION_UNIX_SOCKET))
+  {
+    *error= memcached_set_errno(*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
+    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);
@@ -81,3 +124,17 @@ void memcached_server_list_set(memcached_st *self, memcached_server_st *list)
 {
   self->servers= list;
 }
+
+void memcached_server_list_free(memcached_server_list_st self)
+{
+  if (not self)
+    return;
+
+  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);
+}
index 5a2013e815b9d44a5da236dc0250170ee456527e..6e2ef31f5140452111a66215abf90693a1c58f4b 100644 (file)
@@ -493,6 +493,7 @@ memcached_stat_st *memcached_stat(memcached_st *self, char *args, memcached_retu
 
     stat_instance= stats +x;
 
+    stat_instance->pid= -1;
     stat_instance->root= self;
 
     instance= memcached_server_instance_fetch(self, x);
index c19f7ecc6382f7681d19953a7bc7302e2402d227..ffe7faae78a94b5c7116bec7fe05dc9bdf3e9ea3 100644 (file)
@@ -78,10 +78,14 @@ static inline memcached_return_t memcached_send(memcached_st *ptr,
   }
 
   if (memcached_failed(rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol)))
+  {
     return rc;
+  }
 
-  if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
+  if (memcached_failed(memcached_key_test(*ptr, (const char **)&key, &key_length, 1)))
+  {
     return MEMCACHED_BAD_KEY_PROVIDED;
+  }
 
   uint32_t server_key= memcached_generate_hash_with_redistribution(ptr, group_key, group_key_length);
   memcached_server_write_instance_st instance= memcached_server_instance_fetch(ptr, server_key);
@@ -107,7 +111,7 @@ static inline memcached_return_t memcached_send(memcached_st *ptr,
       check_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
                                     "%s %.*s%.*s %u %llu %lu %llu%s\r\n",
                                     storage_op_string(verb),
-                                    memcached_print_array(ptr->prefix_key),
+                                    memcached_print_array(ptr->_namespace),
                                     (int)key_length, key, flags,
                                     (unsigned long long)expiration, (unsigned long)value_length,
                                     (unsigned long long)cas,
@@ -130,10 +134,10 @@ static inline memcached_return_t memcached_send(memcached_st *ptr,
       memcpy(buffer_ptr, command, strlen(command));
 
       /* Copy in the key prefix, switch to the buffer_ptr */
-      buffer_ptr= (char *)memcpy((char *)(buffer_ptr + strlen(command)), (char *)memcached_array_string(ptr->prefix_key), memcached_array_size(ptr->prefix_key));
+      buffer_ptr= (char *)memcpy((char *)(buffer_ptr + strlen(command)), (char *)memcached_array_string(ptr->_namespace), memcached_array_size(ptr->_namespace));
 
       /* Copy in the key, adjust point if a key prefix was used. */
-      buffer_ptr= (char *)memcpy(buffer_ptr + memcached_array_size(ptr->prefix_key),
+      buffer_ptr= (char *)memcpy(buffer_ptr + memcached_array_size(ptr->_namespace),
                          key, key_length);
       buffer_ptr+= key_length;
       buffer_ptr[0]=  ' ';
@@ -477,7 +481,7 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
 
   request.message.header.request.magic= PROTOCOL_BINARY_REQ;
   request.message.header.request.opcode= get_com_code(verb, noreply);
-  request.message.header.request.keylen= htons((uint16_t)(key_length + memcached_array_size(ptr->prefix_key)));
+  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 || verb == PREPEND_OP)
     send_length -= 8; /* append & prepend does not contain extras! */
@@ -488,7 +492,7 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
     request.message.body.expiration= htonl((uint32_t)expiration);
   }
 
-  request.message.header.request.bodylen= htonl((uint32_t) (key_length + memcached_array_size(ptr->prefix_key) + value_length +
+  request.message.header.request.bodylen= htonl((uint32_t) (key_length + memcached_array_size(ptr->_namespace) + value_length +
                                                             request.message.header.request.extlen));
 
   if (cas)
@@ -513,7 +517,7 @@ static memcached_return_t memcached_send_binary(memcached_st *ptr,
   struct libmemcached_io_vector_st vector[]=
   {
     { send_length, request.bytes },
-    { memcached_array_size(ptr->prefix_key), memcached_array_string(ptr->prefix_key) },
+    { memcached_array_size(ptr->_namespace), memcached_array_string(ptr->_namespace) },
     { key_length, key },
     { value_length, value }
   };
index 6f3b9c1c571a4e5e9ccc5685eb59a6bcb35ec3ea..0e17484055c5e6356073b4458a07d1ce426f4cf1 100644 (file)
@@ -88,7 +88,7 @@ memcached_string_st *memcached_string_create(memcached_st *memc, memcached_strin
   {
     WATCHPOINT_ASSERT(self->options.is_initialized == false);
 
-    self->options.is_allocated= false;
+    memcached_set_allocated(self, false);
   }
   else
   {
@@ -99,7 +99,7 @@ memcached_string_st *memcached_string_create(memcached_st *memc, memcached_strin
       return NULL;
     }
 
-    self->options.is_allocated= true;
+    memcached_set_allocated(self, true);
   }
   self->root= memc;
 
@@ -107,7 +107,10 @@ memcached_string_st *memcached_string_create(memcached_st *memc, memcached_strin
 
   if (memcached_failed(_string_check(self, initial_size)))
   {
-    libmemcached_free(memc, self);
+    if (memcached_is_allocated(self))
+    {
+      libmemcached_free(memc, self);
+    }
 
     return NULL;
   }
index 449b2c1882aded433e194cd63f178bf3163049ba..ea80eb8fc465a85fb38a43820bc598e61e240c27 100644 (file)
@@ -7,6 +7,7 @@ nobase_include_HEADERS+= \
                         libmemcached/memcached_util.h \
                         libmemcached/util.h \
                         libmemcached/util/flush.h \
+                        libmemcached/util/pid.h \
                         libmemcached/util/ping.h \
                         libmemcached/util/pool.h \
                         libmemcached/util/version.h
@@ -15,6 +16,7 @@ endif
 
 libmemcached_libmemcachedutil_la_SOURCES= \
                                          libmemcached/util/flush.cc \
+                                         libmemcached/util/pid.cc \
                                          libmemcached/util/ping.cc \
                                          libmemcached/util/pool.cc \
                                          libmemcached/util/version.cc
diff --git a/libmemcached/util/pid.cc b/libmemcached/util/pid.cc
new file mode 100644 (file)
index 0000000..d9ba79c
--- /dev/null
@@ -0,0 +1,93 @@
+/*  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 <libmemcached/common.h>
+#include <libmemcached/memcached_util.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 (not ret)
+    ret= &unused;
+
+  memcached_st *memc_ptr= memcached_create(NULL);
+  if (not memc_ptr)
+  {
+    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return pid;
+  }
+
+  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 (stat and stat->pid > 0)
+    {
+      pid= stat->pid;
+    }
+    else if (memcached_failed(rc) and rc == MEMCACHED_SOME_ERRORS)
+    {
+      memcached_server_instance_st instance=
+        memcached_server_instance_by_position(memc_ptr, 0);
+
+      if (instance and instance->error_messages)
+      {
+        rc= memcached_server_error_return(instance);
+      }
+    }
+    else if (memcached_success(rc))
+    {
+      rc= MEMCACHED_UNKNOWN_STAT_KEY; // Something went wrong if this happens
+    }
+
+    memcached_stat_free(memc_ptr, stat);
+  }
+  memcached_free(memc_ptr);
+
+  *ret= rc;
+
+  return pid;
+}
+
diff --git a/libmemcached/util/pid.h b/libmemcached/util/pid.h
new file mode 100644 (file)
index 0000000..f2fb748
--- /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
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+pid_t libmemcached_util_getpid(const char *hostname, in_port_t port, memcached_return_t *ret);
+
+#ifdef __cplusplus
+}
+#endif
+
index 37da864925f680b760a6f95f06691c9860aa9d63..839810d4d7478c530cad35811918a022abe42333 100644 (file)
 
 bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_return_t *ret)
 {
+  memcached_return_t unused;
+  if (not ret)
+    ret= &unused;
+
   memcached_st *memc_ptr= memcached_create(NULL);
+  if (not memc_ptr)
+  {
+    *ret= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return false;
+  }
 
   memcached_return_t rc= memcached_server_add(memc_ptr, hostname, port);
   if (memcached_success(rc))
@@ -51,12 +60,19 @@ bool libmemcached_util_ping(const char *hostname, in_port_t port, memcached_retu
     rc= memcached_version(memc_ptr);
   }
 
-  memcached_free(memc_ptr);
-
-  if (ret)
+  if (memcached_failed(rc) and rc == MEMCACHED_SOME_ERRORS)
   {
-    *ret= rc;
+    memcached_server_instance_st instance=
+      memcached_server_instance_by_position(memc_ptr, 0);
+
+    if (instance and instance->error_messages)
+    {
+      rc= memcached_server_error_return(instance);
+    }
   }
+  memcached_free(memc_ptr);
+
+  *ret= rc;
 
-  return rc == MEMCACHED_SUCCESS;
+  return memcached_success(rc);
 }
index 9b00f6de459db2c824762dd068c30654a0c2443d..3874dae5379ad9f6ff3f7e8a84756c41f0712bc4 100644 (file)
@@ -47,4 +47,9 @@
 #include <cstdlib>
 #include <sys/types.h>
 
+#include <cerrno>
+#include <cassert>
+
 #include <libtest/test.hpp>
+
+using namespace libtest;
index c4a3a70247733c9de07c2005f021a002aa4de348..a40868b3c1ba41cc8d0c1dd5ccf250aeb4a803ac 100644 (file)
@@ -16,3 +16,4 @@ enum test_return_t {
 
 
 #define test_failed(__test_return_t) ((__test_return_t) != TEST_SUCCESS)
+#define test_success(__test_return_t) ((__test_return_t) == TEST_SUCCESS)
index df0224675fc23201c817c785e49e741ff4026af6..5ed8020a221066c4c6672730e3d464d89367ba09 100644 (file)
@@ -35,7 +35,7 @@
  *
  */
 
-#include <config.h>
+#include <libtest/common.h>
 
 #include <libtest/failed.h>
 
@@ -68,8 +68,7 @@ void print_failed_test(void)
 {
   for (Failures::iterator iter= failures.begin(); iter != failures.end(); iter++)
   {
-    std::cerr << "\t" << (*iter).collection << " " << (*iter).test << std::endl;
+    Error << "\t" << (*iter).collection << " " << (*iter).test;
   }
-  std::cerr << std::endl;
 }
 
index ff67f20b63b2306da620868f0b7409cceabc1806..dc9bddd95c1be16f7b2b5e8cb74608092659b132 100644 (file)
@@ -1,21 +1,91 @@
-/* uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest, libtest
+ *
+ *  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.
  *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
  */
 
+
 #include <libtest/common.h>
+#include <iostream>
+
+using namespace libtest;
 
-test_return_t Framework::destroy(void* arg)
+static test_return_t _runner_default(test_callback_fn func, void *p)
 {
-  if (_destroy)
+  if (func)
   {
-    return _destroy(arg);
+    return func(p);
   }
 
   return TEST_SUCCESS;
 }
 
+static Runner defualt_runners= {
+  _runner_default,
+  _runner_default,
+  _runner_default
+};
+
+static test_return_t _default_callback(void *p)
+{
+  (void)p;
+
+  return TEST_SUCCESS;
+}
+
+Framework::Framework() :
+  collections(NULL),
+  _create(NULL),
+  _destroy(NULL),
+  collection_startup(_default_callback),
+  collection_shutdown(_default_callback),
+  _on_error(NULL),
+  runner(&defualt_runners),
+  _creators_ptr(NULL)
+{
+}
+
+Framework::~Framework()
+{
+  if (_destroy)
+  {
+    if (test_failed(_destroy(_creators_ptr)))
+    {
+      Error << "Failure in _destroy(), some resources may not have been cleaned up.";
+    }
+  }
+}
+
 test_return_t Framework::Item::flush(void* arg, test_st* run)
 {
   if (run->requires_flush and _flush)
@@ -55,3 +125,14 @@ test_return_t Framework::Item::startup(void* arg)
 
   return TEST_SUCCESS;
 }
+
+void* Framework::create(test_return_t& arg)
+{
+  arg= TEST_SUCCESS;
+  if (_create)
+  {
+    return _creators_ptr= _create(&arg);
+  }
+
+  return NULL;
+}
index 7a58cbeeb94cef276c424af3f94a304772ee651c..1c9a1c1d5ff2e2dc1eabdb26fbcc8c0c129f51d2 100644 (file)
@@ -1,9 +1,40 @@
-/* uTest Copyright (C) 2011 Data Differential, http://datadifferential.com/
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest, libtest
+ *
+ *  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.
  *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
  */
 
+
 #pragma once
 
 /**
@@ -19,17 +50,7 @@ struct Framework {
   test_callback_create_fn *_create;
   test_callback_fn *_destroy;
 
-  void* create(test_return_t* arg)
-  {
-    if (_create)
-    {
-      return _create(arg);
-    }
-
-    return NULL;
-  }
-
-  test_return_t destroy(void*);
+  void* create(test_return_t& arg);
 
   /* This is called a the beginning of any collection run. */
   test_callback_fn *collection_startup;
@@ -127,11 +148,11 @@ struct Framework {
 
   Framework();
 
-  virtual ~Framework()
-  { }
+  virtual ~Framework();
 
   Framework(const Framework&);
 
 private:
   Framework& operator=(const Framework&);
+  void *_creators_ptr;
 };
index 33ed871692f090c1a735fc1c68b12fd0e7e9d661..398037ba9338114da82f1e205098f7fdde3c7014 100644 (file)
 
 LIBUTEST_TMP = ${abs_top_builddir}/tests/var/tmp/
 
+VALGRIND_COMMAND= $(LIBTOOL) --mode=execute valgrind --error-exitcode=1 --leak-check=yes --show-reachable=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE
+
 CLEANFILES+= \
             tests/var/log/* \
+            tests/var/run/* \
             tests/var/tmp/*
 
 noinst_HEADERS+= \
@@ -24,25 +27,36 @@ noinst_HEADERS+= \
                 libtest/failed.h \
                 libtest/framework.h \
                 libtest/get.h \
+                libtest/killpid.h \
                 libtest/runner.h \
                 libtest/server.h \
                 libtest/stats.h \
                 libtest/strerror.h \
                 libtest/test.h \
                 libtest/test.hpp \
-                libtest/visibility.h
+                libtest/visibility.h \
+                libtest/wait.h
 
 noinst_LTLIBRARIES+= libtest/libserver.la
-libtest_libserver_la_SOURCES= libtest/server.c
+libtest_libserver_la_SOURCES= \
+                             libtest/killpid.cc \
+                             libtest/memcached.cc \
+                             libtest/server.cc
 
 noinst_LTLIBRARIES+= libtest/libtest.la
 libtest_libtest_la_SOURCES=\
                           libtest/framework.cc \
                           libtest/test.cc
 libtest_libtest_la_CFLAGS= ${AM_CFLAGS} ${NO_CONVERSION} -DBUILDING_LIBTEST
-libtest_libtest_la_CPPFLAGS= ${AM_CPPFLAGS}
+libtest_libtest_la_CXXFLAGS= ${AM_CXXFLAGS} ${NO_CONVERSION} -DBUILDING_LIBTEST
+
+clearn-var:
+       @rm -f tests/var/log/*
+       @rm -f tests/var/run/*
+       @rm -f tests/var/tmp/*
+
 
-tests/var: tests/var/log tests/var/tmp
+tests/var: tests/var/log tests/var/tmp tests/var/run clearn-var
        $(mkdir_p) tests/var
 
 tests/var/log:
@@ -50,3 +64,16 @@ tests/var/log:
 
 tests/var/tmp:
        $(mkdir_p) tests/var/tmp
+
+tests/var/run:
+       $(mkdir_p) tests/var/run
+
+libtest_unittest_LDADD= \
+                         libtest/libtest.la
+libtest_unittest_SOURCES= \
+                           libtest/unittest.cc
+noinst_PROGRAMS+= libtest/unittest
+check_PROGRAMS+= libtest/unittest
+
+libtest_wait_SOURCES= libtest/wait.cc
+noinst_PROGRAMS+= libtest/wait
diff --git a/libtest/killpid.cc b/libtest/killpid.cc
new file mode 100644 (file)
index 0000000..bacec8f
--- /dev/null
@@ -0,0 +1,123 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest
+ *
+ *  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 <libtest/common.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+
+#include <libtest/killpid.h>
+#include <libtest/stream.h>
+
+using namespace libtest;
+
+bool kill_pid(pid_t pid_arg)
+{
+  if (pid_arg <= 1)
+    return false;
+
+  if ((::kill(pid_arg, SIGTERM) == -1))
+  {
+    switch (errno)
+    {
+    case EPERM:
+      perror(__func__);
+      Error << __func__ << " -> Does someone else have a process running locally for " << int(pid_arg) << "?";
+      return false;
+
+    case ESRCH:
+      perror(__func__);
+      Error << "Process " << int(pid_arg) << " not found.";
+      return false;
+
+    default:
+    case EINVAL:
+      perror(__func__);
+      return false;
+    }
+  }
+
+  int status= 0;
+  pid_t pid= waitpid(pid_arg, &status, 0);
+  if (pid == -1)
+  {
+    switch (errno)
+    {
+    case ECHILD:
+      return true;
+    }
+
+    Error << "Error occured while waitpid(" << strerror(errno) << ") on pid " << int(pid_arg);
+
+    return false;
+  }
+
+  if (WIFEXITED(status))
+    return true;
+
+  if (WCOREDUMP(status))
+    return true;
+
+  return false;
+}
+
+
+void kill_file(const std::string &filename)
+{
+  FILE *fp;
+
+  if (filename.empty())
+    return;
+
+  if ((fp= fopen(filename.c_str(), "r")))
+  {
+    char pid_buffer[1024];
+
+    char *ptr= fgets(pid_buffer, sizeof(pid_buffer), fp);
+    fclose(fp);
+
+    if (ptr)
+    {
+      pid_t pid= (pid_t)atoi(pid_buffer);
+      if (pid != 0)
+      {
+        kill_pid(pid);
+        unlink(filename.c_str()); // If this happens we may be dealing with a dead server that left its pid file.
+      }
+    }
+  }
+}
diff --git a/libtest/killpid.h b/libtest/killpid.h
new file mode 100644 (file)
index 0000000..d67ec94
--- /dev/null
@@ -0,0 +1,42 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest
+ *
+ *  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 kill_pid(pid_t pid_arg);
+
+void kill_file(const std::string &filename);
diff --git a/libtest/memcached.cc b/libtest/memcached.cc
new file mode 100644 (file)
index 0000000..2b49c60
--- /dev/null
@@ -0,0 +1,263 @@
+/*  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.
+ *
+ */
+
+
+/*
+  Startup, and shutdown the memcached servers.
+*/
+
+#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT+10
+
+#include <libtest/common.h>
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <ctime>
+#include <limits.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <iostream>
+
+#include <libmemcached/memcached.h>
+#include <libmemcached/util.h>
+
+#include <libtest/server.h>
+#include <libtest/killpid.h>
+#include <libtest/wait.h>
+
+#define SOCKET_FILE "/tmp/memcached.socket"
+
+static pid_t __getpid(server_st& server)
+{
+  memcached_return_t rc;
+  pid_t pid= libmemcached_util_getpid(server.hostname(), server.port(), &rc);
+  return pid;
+}
+
+static bool __ping(server_st& server)
+{
+  memcached_return_t rc;
+  bool ret= libmemcached_util_ping(server.hostname(), server.port(), &rc);
+  return ret;
+}
+
+static bool cycle_server(server_st  *server)
+{
+  while (1)
+  {
+    if (libmemcached_util_ping(server->hostname(), server->port(), NULL))
+    {
+      // First we try to kill it, and on fail of that we flush it.
+      pid_t pid= libmemcached_util_getpid(server->hostname(), server->port(), NULL);
+
+      if (pid > 0 and kill_pid(pid))
+      {
+        Error << "Killed existing server," << *server << " with pid:" << pid;
+        continue;
+      }
+      else if (libmemcached_util_flush(server->hostname(), server->port(), NULL)) // If we can flush it, we will just use it
+      { 
+        Error << "Found server on port " << int(server->port()) << ", flushed it!";
+        server->set_used();
+        return true;
+      } // No idea what is wrong here, so we need to find a different port
+      else
+      {
+        return false;
+      }
+    }
+
+    break;
+  }
+
+  return true;
+}
+
+bool server_startup(server_startup_st *construct)
+{
+  Logn();
+
+  if (getenv(((char *)"MEMCACHED_SERVERS")))
+  {
+    construct->server_list= getenv(((char *)"MEMCACHED_SERVERS"));
+    Log << "MEMCACHED_SERVERS " << construct->server_list;
+    construct->count= 0;
+  }
+  else
+  {
+    std::string server_config_string;
+
+    uint32_t port_base= 0;
+    for (uint32_t x= 0; x < (construct->count -1); x++)
+    {
+      server_st *server= NULL;
+
+      {
+        char *var;
+        char variable_buffer[1024];
+
+        snprintf(variable_buffer, sizeof(variable_buffer), "LIBMEMCACHED_PORT_%u", x);
+
+        if ((var= getenv(variable_buffer)))
+        {
+          server= new server_st((in_port_t)atoi(var), __getpid, __ping);
+        }
+        else
+        {
+          server= new server_st(in_port_t(x +TEST_PORT_BASE +port_base), __getpid, __ping);
+
+          while (not cycle_server(server))
+          {
+            Error << "Found server " << *server << ", could not flush it, so trying next port.";
+            port_base++;
+            server->set_port(in_port_t(x +TEST_PORT_BASE +port_base));
+          }
+        }
+      }
+
+      if (server->is_used())
+      {
+        Log << "Using server at : " << server;
+      }
+      else
+      {
+        char buffer[FILENAME_MAX];
+        if (x == 0)
+        {
+          snprintf(buffer, sizeof(buffer), "%s -d -t 1 -p %u -U %u -m 128",
+                   MEMCACHED_BINARY, server->port(), server->port());
+        }
+        else
+        {
+          snprintf(buffer, sizeof(buffer), "%s -d -t 1 -p %u -U %u",
+                   MEMCACHED_BINARY, server->port(), server->port());
+        }
+        server->set_command(buffer);
+
+        if (not server->start())
+        {
+          Error << "Failed system(" << buffer << ")";
+          delete server;
+          return false;
+        }
+        Log << "STARTING SERVER: " << buffer << " pid:" << server->pid();
+      }
+      construct->push_server(server);
+
+      if (x == 0)
+      {
+        assert(server->has_port());
+        set_default_port(server->port());
+      }
+
+      char port_str[NI_MAXSERV];
+      snprintf(port_str, sizeof(port_str), "%u", int(server->port()));
+
+      server_config_string+= "--server=";
+      server_config_string+= server->hostname();
+      server_config_string+= ":";
+      server_config_string+= port_str;
+      server_config_string+= " ";
+    }
+
+    // Socket
+    {
+
+      std::string socket_file(SOCKET_FILE);
+      char *var;
+
+      if ((var= getenv("LIBMEMCACHED_SOCKET")))
+      {
+        socket_file= var;
+      }
+
+      server_st *server= new server_st(SOCKET_FILE, __getpid, __ping);
+
+      if (not cycle_server(server))
+      {
+        Error << "Found server " << server << ", could not flush it, failing since socket file is not available.";
+        return false;
+      }
+
+      if (server->is_used())
+      {
+        Log << "Using server at : " << *server;
+      }
+      else
+      {
+        char buffer[FILENAME_MAX];
+        snprintf(buffer, sizeof(buffer), "%s -d -t 1 -s %s", MEMCACHED_BINARY, SOCKET_FILE);
+        server->set_command(buffer);
+
+        if (not server->start())
+        {
+          Error << "Failed system(" << buffer << ")";
+          delete server;
+          return false;
+        }
+        Log << "STARTING SERVER: " << buffer << " pid:" << server->pid();
+      }
+      set_default_socket(server->hostname());
+      construct->push_server(server);
+
+      {
+        server_config_string+= "--socket=\"";
+        server_config_string+= server->hostname();
+        server_config_string+= "\" ";
+      }
+    }
+
+    server_config_string.resize(server_config_string.size() -1); // Remove final space
+    construct->server_list= server_config_string;
+  }
+
+  Logn();
+
+  srandom((unsigned int)time(NULL));
+
+  return true;
+}
+
+void server_shutdown(server_startup_st *construct)
+{
+  if (not construct)
+    return;
+
+  construct->shutdown();
+}
diff --git a/libtest/server.c b/libtest/server.c
deleted file mode 100644 (file)
index dac57c7..0000000
+++ /dev/null
@@ -1,355 +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.
- *
- */
-
-
-/*
-  Startup, and shutdown the memcached servers.
-*/
-
-#define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT+10
-
-#include <config.h>
-
-#include <iso646.h>
-
-#include <assert.h>
-#include <limits.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <time.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <libmemcached/memcached.h>
-#include <libmemcached/util.h>
-
-#include <libtest/server.h>
-
-static struct timespec global_sleep_value= { .tv_sec= 0, .tv_nsec= 50000 };
-
-static void global_sleep(void)
-{
-#ifdef WIN32
-  sleep(1);
-#else
-  nanosleep(&global_sleep_value, NULL);
-#endif
-}
-
-static bool wait_for_file(const char *filename)
-{
-  uint32_t timeout= 6;
-  uint32_t waited;
-  uint32_t this_wait;
-  uint32_t retry;
-
-  for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
-  {
-    if ((! access(filename, R_OK)) || (waited >= timeout))
-    {
-      return true;
-    }
-
-    this_wait= retry * retry / 3 + 1;
-    sleep(this_wait);
-  }
-
-  return false;
-}
-
-static void kill_file(const char *file_buffer)
-{
-  FILE *fp;
-
-  while ((fp= fopen(file_buffer, "r")))
-  {
-    char pid_buffer[1024];
-
-    if (fgets(pid_buffer, sizeof(pid_buffer), fp) != NULL)
-    {
-      pid_t pid= (pid_t)atoi(pid_buffer);
-      if (pid != 0)
-      {
-        if (kill(pid, SIGTERM) == -1)
-        {
-          remove(file_buffer); // If this happens we may be dealing with a dead server that left its pid file.
-        }
-        else
-        {
-          uint32_t counter= 3;
-          while ((kill(pid, 0) == 0) && --counter)
-          {
-            global_sleep();
-          }
-        }
-      }
-    }
-
-    global_sleep();
-
-    fclose(fp);
-  }
-}
-
-void server_startup(server_startup_st *construct)
-{
-  if ((construct->server_list= getenv("MEMCACHED_SERVERS")))
-  {
-    printf("servers %s\n", construct->server_list);
-    construct->servers= memcached_servers_parse(construct->server_list);
-    construct->server_list= NULL;
-    construct->count= 0;
-  }
-  else
-  {
-    {
-      char server_string_buffer[8096];
-      char *end_ptr;
-      end_ptr= server_string_buffer;
-
-      uint32_t port_base= 0;
-      for (uint32_t x= 0; x < construct->count; x++)
-      {
-        int status;
-
-        snprintf(construct->pid_file[x], FILENAME_MAX, "/tmp/memcached.pidXXXXXX");
-        int fd;
-        if ((fd= mkstemp(construct->pid_file[x])) == -1)
-        {
-          perror("mkstemp");
-          return;
-        }
-        close(fd);
-
-        {
-          char *var;
-          char variable_buffer[1024];
-
-          snprintf(variable_buffer, sizeof(variable_buffer), "LIBMEMCACHED_PORT_%u", x);
-
-          if ((var= getenv(variable_buffer)))
-          {
-            construct->port[x]= (in_port_t)atoi(var);
-          }
-          else
-          {
-            do {
-              construct->port[x]= (in_port_t)(x + TEST_PORT_BASE + port_base);
-
-              if (libmemcached_util_ping("localhost", construct->port[x], NULL))
-              {
-                if (libmemcached_util_flush("localhost", construct->port[x], NULL))
-                { 
-                  fprintf(stderr, "Found server on port %d, flushed it!\n", (int)construct->port[x]);
-                  construct->is_used[x]= true;
-                } // If we can flush it, we will just use it
-                else
-                {
-                  fprintf(stderr, "Found server on port %d, could not flush it, so trying next port.\n", (int)construct->port[x]);
-                  port_base++;
-                  construct->port[x]= 0;
-                }
-              }
-            } while (construct->port[x] == 0);
-          }
-        }
-
-        char buffer[FILENAME_MAX];
-        if (x == 0)
-        {
-          snprintf(buffer, sizeof(buffer), "%s -d -P %s -t 1 -p %u -U %u -m 128",
-                   MEMCACHED_BINARY, construct->pid_file[x], construct->port[x], construct->port[x]);
-        }
-        else
-        {
-          snprintf(buffer, sizeof(buffer), "%s -d -P %s -t 1 -p %u -U %u",
-                   MEMCACHED_BINARY, construct->pid_file[x], construct->port[x], construct->port[x]);
-        }
-
-        if (construct->is_used[x])
-        {
-          fprintf(stderr, "USING SERVER: %s\n", buffer);
-        }
-        else
-        {
-          if (libmemcached_util_ping("localhost", construct->port[x], NULL))
-          {
-            fprintf(stderr, "Server on port %u already exists\n", construct->port[x]);
-          }
-          else
-          {
-            status= system(buffer);
-            fprintf(stderr, "STARTING SERVER: %s  status:%d\n", buffer, status);
-          }
-        }
-
-        int count;
-        size_t remaining_length= sizeof(server_string_buffer) - (size_t)(end_ptr -server_string_buffer);
-        count= snprintf(end_ptr, remaining_length,  "localhost:%u,", construct->port[x]);
-
-        if ((size_t)count >= remaining_length || count < 0)
-        {
-          fprintf(stderr, "server names grew to be larger then buffer allowed\n");
-          abort();
-        }
-        end_ptr+= count;
-      }
-      *end_ptr= 0;
-
-
-      for (uint32_t x= 0; x < construct->count; x++)
-      {
-        if (! wait_for_file(construct->pid_file[x]))
-        {
-          abort();
-        }
-      }
-
-      for (uint32_t x= 0; x < construct->count; x++)
-      {
-        uint32_t counter= 3000; // Absurd, just to catch run away process
-
-        if (construct->is_used[x])
-          continue;
-
-        while (construct->pids[x] <= 0  && --counter)
-        {
-          FILE *file= fopen(construct->pid_file[x], "r");
-          if (file)
-          {
-            char pid_buffer[1024];
-            char *found= fgets(pid_buffer, sizeof(pid_buffer), file);
-
-            if (found)
-            {
-              construct->pids[x]= atoi(pid_buffer);
-              fclose(file);
-
-              if (construct->pids[x] > 0)
-                break;
-            }
-            fclose(file);
-          }
-
-          switch (errno)
-          {
-          default:
-            fprintf(stderr, "Could not open pid file %s -> fopen(%s) -> %s:%d\n", construct->pid_file[x], strerror(errno), __FILE__, __LINE__);
-            abort();
-
-          case ENOENT:
-          case EINTR:
-          case EACCES:
-          case EINPROGRESS:
-            break;
-
-          case ENOTCONN:
-            continue;
-          }
-
-          // Safety 3rd, check to see if the file has gone away
-          if (! wait_for_file(construct->pid_file[x]))
-          {
-            abort();
-          }
-        }
-
-        bool was_started= false;
-        if (construct->pids[x] > 0)
-        {
-          counter= 30;
-          while (--counter)
-          {
-            if (kill(construct->pids[x], 0) == 0)
-            {
-              was_started= true;
-              break;
-            }
-            global_sleep();
-          }
-        }
-
-        if (was_started == false)
-        {
-          fprintf(stderr, "Failed to open buffer %s(%d)\n", construct->pid_file[x], construct->pids[x]);
-          for (uint32_t y= 0; y < construct->count; y++)
-          {
-            if (construct->pids[y] > 0)
-              kill(construct->pids[y], SIGTERM);
-          }
-          abort();
-        }
-      }
-
-      construct->server_list= strdup(server_string_buffer);
-    }
-    printf("servers %s\n", construct->server_list);
-    construct->servers= memcached_servers_parse(construct->server_list);
-  }
-
-  assert(construct->servers);
-
-  srandom((unsigned int)time(NULL));
-
-  for (uint32_t x= 0; x < memcached_server_list_count(construct->servers); x++)
-  {
-    printf("\t%s : %d\n", memcached_server_name(&construct->servers[x]), memcached_server_port(&construct->servers[x]));
-    assert(construct->servers[x].fd == -1);
-    assert(construct->servers[x].cursor_active == 0);
-  }
-
-  printf("\n");
-}
-
-void server_shutdown(server_startup_st *construct)
-{
-  if (construct->server_list)
-  {
-    for (uint32_t x= 0; x < construct->count; x++)
-    {
-      if (construct->is_used[x])
-        continue;
-
-      kill_file(construct->pid_file[x]);
-    }
-
-    free(construct->server_list);
-  }
-}
diff --git a/libtest/server.cc b/libtest/server.cc
new file mode 100644 (file)
index 0000000..cb15aee
--- /dev/null
@@ -0,0 +1,197 @@
+/*  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 <config.h>
+#include <iostream>
+#include <cstdlib>
+#include <cassert>
+
+#include <libtest/server.h>
+#include <libtest/killpid.h>
+
+
+std::ostream& operator<<(std::ostream& output, const server_st &arg)
+{
+  if (arg.is_socket())
+  {
+    output << arg.hostname();
+  }
+  else
+  {
+    output << arg.hostname() << ":" << arg.port();
+  }
+  return output;  // for multiple << operators
+}
+
+static void global_sleep(void)
+{
+  static struct timespec global_sleep_value= { 0, 50000 };
+
+#ifdef WIN32
+  sleep(1);
+#else
+  nanosleep(&global_sleep_value, NULL);
+#endif
+}
+
+server_st::server_st(in_port_t port_arg, test_server_getpid *get_pid_arg, test_server_ping *ping_arg) :
+  _used(false),
+  _pid(-1),
+  _port(port_arg),
+  __get_pid(get_pid_arg),
+  __ping(ping_arg),
+  _hostname("localhost")
+{
+  pid_file[0]= 0;
+}
+
+server_st::server_st(const std::string &socket_file, test_server_getpid *get_pid_arg, test_server_ping *ping_arg) :
+  _used(false),
+  _pid(-1),
+  _port(0),
+  __get_pid(get_pid_arg),
+  __ping(ping_arg),
+  _hostname(socket_file)
+{
+  pid_file[0]= 0;
+}
+
+
+server_st::~server_st()
+{
+  if (has_pid())
+  {
+    kill();
+  }
+}
+
+bool server_st::start()
+{
+  assert(not _command.empty());
+  assert(not has_pid());
+
+  if (has_pid())
+    return false;
+
+  if (system(_command.c_str()) == -1)
+    return false;
+
+  int count= 30;
+  while (not ping() and --count)
+  {
+    global_sleep();
+  }
+
+  if (count == 0)
+  {
+    return false;
+  }
+
+  _pid= get_pid();
+
+  return has_pid();
+}
+
+void server_st::reset_pid()
+{
+  pid_file[0]= 0;
+  _pid= -1;
+}
+
+pid_t server_st::pid()
+{
+  if (not has_pid())
+  {
+    _pid= get_pid();
+  }
+
+  return _pid;
+}
+
+
+bool server_st::kill()
+{
+  if (is_used())
+    return false;
+
+  if ((_pid= get_pid()))
+  {
+    kill_pid(_pid);
+    if (pid_file[0])
+    {
+      unlink(pid_file); // If this happens we may be dealing with a dead server that left its pid file.
+    }
+    reset_pid();
+
+    return true;
+  }
+#if 0
+  else if (pid_file[0])
+  {
+    kill_file(pid_file);
+    reset_pid();
+
+    return true;
+  }
+#endif
+
+  return false;
+}
+
+void server_startup_st::push_server(server_st *arg)
+{
+  servers.push_back(arg);
+}
+
+void server_startup_st::shutdown()
+{
+  for (std::vector<server_st *>::iterator iter= servers.begin(); iter != servers.end(); iter++)
+  {
+    if ((*iter)->is_used())
+      continue;
+
+    (*iter)->kill();
+  }
+}
+
+server_startup_st::~server_startup_st()
+{
+  for (std::vector<server_st *>::iterator iter= servers.begin(); iter != servers.end(); iter++)
+  {
+    delete *iter;
+  }
+  servers.clear();
+}
index 581cf8596b30297af084fe554cef729838ac33e8..f3bda21b99fa581b8b0e3ca2a5dc9ab8ae173177 100644 (file)
 
 #pragma once
 
+#include <cstring>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <string>
 #include <unistd.h>
+#include <vector>
 
-/*
-  Server startup and shutdown functions.
-*/
-#ifdef __cplusplus
-extern "C" {
-#endif
+#define SERVERS_TO_CREATE 5
 
-#include <libmemcached/memcached.h>
+struct server_st;
 
-typedef struct server_startup_st server_startup_st;
-#define SERVERS_TO_CREATE 5
+typedef pid_t (test_server_getpid)(server_st &);
+typedef bool (test_server_ping)(server_st &);
+
+struct server_st {
+private:
+  bool _used;
+  pid_t _pid;
+  in_port_t _port;
+  char pid_file[FILENAME_MAX]; // Did we start it, or was it just sitting there?
+  std::string _command;
+  test_server_getpid *__get_pid;
+  test_server_ping *__ping;
+  std::string _hostname;
+
+public:
+  server_st(in_port_t port_arg, test_server_getpid *, test_server_ping *);
+
+  server_st(const std::string &socket_file, test_server_getpid *, test_server_ping *);
+
+  void set_methods(test_server_getpid *get_pid_arg, test_server_ping *ping_arg)
+  {
+    __get_pid= get_pid_arg;
+    __ping= ping_arg;
+  }
+
+  const char *hostname() const
+  {
+    if (_hostname.empty())
+      return "";
+
+    return _hostname.c_str();
+  }
+
+  bool ping()
+  {
+    if (__ping)
+      return __ping(*this);
+
+    return false;
+  }
+
+  pid_t get_pid()
+  {
+    if (__get_pid)
+      return _pid= __get_pid(*this);
+
+    return -1;
+  }
+
+  void set_port(in_port_t arg)
+  {
+    _port= arg;
+  }
+
+  in_port_t port() const
+  {
+    return _port;
+  }
+
+  bool has_port() const
+  {
+    return (_port != 0);
+  }
+
+  void set_command(const char *arg)
+  {
+    _command= arg;
+  }
+
+  void set_used()
+  {
+    _used= true;
+  }
+
+  pid_t pid();
+
+  bool is_used() const
+  {
+    return _used;
+  }
+
+  ~server_st();
+
+  bool has_pid()
+  {
+    return (_pid > 1);
+  }
+
+  bool is_socket() const
+  {
+    return _hostname[0] == '/';
+  }
+
+  bool kill();
+  bool start();
+
+private:
+  void reset_pid();
+};
+
+std::ostream& operator<<(std::ostream& output, const server_st &arg);
 
 struct server_startup_st
 {
   uint8_t count;
   uint8_t udp;
-  memcached_server_st *servers;
-  char *server_list;
-  char pid_file[SERVERS_TO_CREATE][FILENAME_MAX];
-  in_port_t port[SERVERS_TO_CREATE];
-  int pids[SERVERS_TO_CREATE];
-  bool is_used[SERVERS_TO_CREATE]; // Did we start it, or was it just sitting there?
+  std::string server_list;
+  std::vector<server_st *> servers;
+
+  server_startup_st() :
+    count(SERVERS_TO_CREATE),
+    udp(0)
+  { }
+
+  void shutdown();
+  void push_server(server_st *);
+
+  ~server_startup_st();
 };
 
-void server_startup(server_startup_st *construct);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+bool server_startup(server_startup_st *construct);
 void server_shutdown(server_startup_st *construct);
 
 #ifdef __cplusplus
diff --git a/libtest/stream.h b/libtest/stream.h
new file mode 100644 (file)
index 0000000..558b279
--- /dev/null
@@ -0,0 +1,165 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest, libtest
+ *
+ *  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 <iostream>
+#include <cassert>
+#include <sstream>
+#include <ctime>
+#include <ostream>
+
+namespace libtest {
+namespace stream {
+
+namespace detail {
+
+template<class Ch, class Tr, class A>
+  class cerr {
+  private:
+
+  public:
+    typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
+
+  public:
+    void operator()(const stream_buffer &s)
+    {
+      std::cerr << std::endl << s.str() << std::endl;
+    }
+  };
+
+template<class Ch, class Tr, class A>
+  class cout {
+  private:
+
+  public:
+    typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
+
+  public:
+    void operator()(const stream_buffer &s)
+    {
+      std::cout << s.str() << std::endl;
+    }
+  };
+
+template<class Ch, class Tr, class A>
+  class clog {
+  private:
+
+  public:
+    typedef std::basic_ostringstream<Ch, Tr, A> stream_buffer;
+
+  public:
+    void operator()(const stream_buffer &s)
+    {
+      std::cerr << s.str() << std::endl;
+    }
+  };
+
+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;
+    const char *_filename;
+    int _line_number;
+
+  public:
+    log() :
+      _filename(NULL),
+      _line_number(0)
+    { }
+
+    void set_filename(const char *filename, int line_number)
+    {
+      _filename= filename;
+      _line_number= line_number;
+    }
+
+    ~log()
+    {
+      output_policy()(arg);
+    }
+
+  public:
+    template<class T>
+      log &operator<<(const T &x)
+      {
+        if (_filename)
+        {
+          arg << __FILE__ << ":" << __LINE__ << " ";
+          _filename= NULL;
+        }
+        arg << x;
+        return *this;
+      }
+
+  private:
+    typename output_policy::stream_buffer arg;
+  };
+}
+
+class cerr : public detail::log<detail::cerr> {
+public:
+  cerr(const char *filename, int line_number)
+  {
+    set_filename(filename, line_number);
+  }
+};
+
+class clog : public detail::log<detail::clog> {
+public:
+  clog(const char *, int)
+  { }
+};
+
+class cout : public detail::log<detail::cout> {
+public:
+  cout(const char *, int)
+  { }
+};
+
+
+} // namespace stream
+
+#define Error stream::cerr(__FILE__, __LINE__)
+
+#define Out stream::cout(NULL, __LINE__)
+
+#define Log stream::clog(NULL, __LINE__)
+
+#define Logn() stream::clog(NULL, __LINE__) << " "
+
+} // namespace libtest
index ee743983fffa7f73e3422c698212efa495afc816..8beef356610b788bf4b5fc8bf825c7bb9ea8c6ed 100644 (file)
@@ -1,13 +1,43 @@
-/* uTest
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest, libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
  */
 
 
+
+
 #include <libtest/common.h>
 
 #include <cassert>
@@ -22,6 +52,8 @@
 #include <fnmatch.h>
 #include <iostream>
 
+#include <signal.h>
+
 #include <libtest/stats.h>
 
 #ifndef __INTEL_COMPILER
@@ -29,6 +61,7 @@
 #endif
 
 static in_port_t global_port= 0;
+static char global_socket[1024];
 
 in_port_t default_port()
 {
@@ -41,6 +74,22 @@ void set_default_port(in_port_t port)
   global_port= port;
 }
 
+const char *default_socket()
+{
+  assert(global_socket[0]);
+  return global_socket;
+}
+
+bool test_is_local()
+{
+  return (getenv("LIBTEST_LOCAL"));
+}
+
+void set_default_socket(const char *socket)
+{
+  strncpy(global_socket, socket, strlen(socket));
+}
+
 static void stats_print(Stats *stats)
 {
   std::cout << "\tTotal Collections\t\t\t\t" << stats->collection_total << std::endl;
@@ -104,59 +153,109 @@ void create_core(void)
   }
 }
 
+enum shutdown_t {
+  SHUTDOWN_RUNNING,
+  SHUTDOWN_GRACEFUL,
+  SHUTDOWN_FORCED
+};
 
-static test_return_t _runner_default(test_callback_fn func, void *p)
+static Framework *world= NULL;
+static volatile shutdown_t __shutdown= SHUTDOWN_RUNNING;
+pthread_mutex_t shutdown_mutex= PTHREAD_MUTEX_INITIALIZER;
+
+static bool is_shutdown()
+{
+  bool ret;
+  pthread_mutex_lock(&shutdown_mutex);
+  ret= bool(__shutdown != SHUTDOWN_RUNNING);
+  pthread_mutex_unlock(&shutdown_mutex);
+
+  return ret;
+}
+
+static void set_shutdown(shutdown_t arg)
 {
-  if (func)
+  pthread_mutex_lock(&shutdown_mutex);
+  __shutdown= arg;
+  pthread_mutex_unlock(&shutdown_mutex);
+}
+
+static void *sig_thread(void *arg)
+{   
+  sigset_t *set= (sigset_t *) arg;
+
+  while (is_shutdown())
   {
-    return func(p);
+    int sig;
+    int error;
+    while ((error= sigwait(set, &sig)) == EINTR) ;
+
+    switch (sig)
+    {
+    case SIGSEGV:
+    case SIGINT:
+    case SIGABRT:
+      Error << "Signal handling thread got signal " <<  strsignal(sig);
+      set_shutdown(SHUTDOWN_FORCED);
+      break;
+
+    default:
+      Error << "Signal handling thread got unexpected signal " <<  strsignal(sig);
+    case SIGUSR1:
+      break;
+    }
   }
 
-  return TEST_SUCCESS;
+  return NULL;
 }
 
-static Runner defualt_runners= {
-  _runner_default,
-  _runner_default,
-  _runner_default
-};
 
-static test_return_t _default_callback(void *p)
+static void setup_signals(pthread_t& thread)
 {
-  (void)p;
+  sigset_t set;
 
-  return TEST_SUCCESS;
-}
+  sigemptyset(&set);
+  sigaddset(&set, SIGSEGV);
+  sigaddset(&set, SIGABRT);
+  sigaddset(&set, SIGINT);
+  sigaddset(&set, SIGUSR1);
 
-Framework::Framework() :
-  collections(NULL),
-  _create(NULL),
-  _destroy(NULL),
-  collection_startup(_default_callback),
-  collection_shutdown(_default_callback),
-  _on_error(NULL),
-  runner(&defualt_runners)
-{
+  int error;
+  if ((error= pthread_sigmask(SIG_BLOCK, &set, NULL)) != 0)
+  {
+    Error << " died during pthread_sigmask(" << strerror(error) << ")";
+    exit(EXIT_FAILURE);
+  }
+
+  if ((error= pthread_create(&thread, NULL, &sig_thread, (void *) &set)) != 0)
+  {
+    Error << " died during pthread_create(" << strerror(error) << ")";
+    exit(EXIT_FAILURE);
+  }
 }
 
 
 int main(int argc, char *argv[])
 {
-  Framework world;
+  world= new Framework();
 
-  Stats stats;
-
-  get_world(&world);
-
-  if (not world.runner)
+  if (not world)
   {
-    world.runner= &defualt_runners;
+    return EXIT_FAILURE;
   }
 
+  pthread_t thread;
+  setup_signals(thread);
+
+  Stats stats;
+
+  get_world(world);
+
   test_return_t error;
-  void *world_ptr= world.create(&error);
+  void *creators_ptr= world->create(error);
   if (test_failed(error))
   {
+    Error << "create() failed";
     return EXIT_FAILURE;
   }
 
@@ -181,7 +280,7 @@ int main(int argc, char *argv[])
     wildcard= argv[2];
   }
 
-  for (collection_st *next= world.collections; next->name; next++)
+  for (collection_st *next= world->collections; next->name and (not is_shutdown()); next++)
   {
     test_return_t collection_rc= TEST_SUCCESS;
     bool failed= false;
@@ -192,27 +291,26 @@ int main(int argc, char *argv[])
 
     stats.collection_total++;
 
-    collection_rc= world.startup(world_ptr);
+    collection_rc= world->startup(creators_ptr);
 
     if (collection_rc == TEST_SUCCESS and next->pre)
     {
-      collection_rc= world.runner->pre(next->pre, world_ptr);
+      collection_rc= world->runner->pre(next->pre, creators_ptr);
     }
 
     switch (collection_rc)
     {
     case TEST_SUCCESS:
-      std::cerr << std::endl << next->name << std::endl << std::endl;
       break;
 
     case TEST_FATAL:
     case TEST_FAILURE:
-      std::cerr << std::endl << next->name << " [ failed ]" << std::endl << std::endl;
+      Error << next->name << " [ failed ]";
       stats.collection_failed++;
       goto cleanup;
 
     case TEST_SKIPPED:
-      std::cerr << std::endl << next->name << " [ skipping ]" << std::endl << std::endl;
+      Log << next->name << " [ skipping ]";
       stats.collection_skipped++;
       goto cleanup;
 
@@ -220,6 +318,8 @@ int main(int argc, char *argv[])
       test_assert(0, "Allocation failure, or unknown return");
     }
 
+    Log << "Collection: " << next->name;
+
     for (test_st *run= next->tests; run->name; run++)
     {
       struct timeval start_time, end_time;
@@ -227,64 +327,76 @@ int main(int argc, char *argv[])
 
       if (wildcard && fnmatch(wildcard, run->name, 0))
       {
-       continue;
+        continue;
       }
 
-      std::cerr << "\tTesting " << run->name;
-
-      world.item.startup(world_ptr);
-
-      world.item.flush(world_ptr, run);
-
-      world.item.pre(world_ptr);
-
       test_return_t return_code;
-      { // Runner Code
-       gettimeofday(&start_time, NULL);
-       return_code= world.runner->run(run->test_fn, world_ptr);
-       gettimeofday(&end_time, NULL);
-       load_time= timedif(end_time, start_time);
+      if (test_success(return_code= world->item.startup(creators_ptr)))
+      {
+        if (test_success(return_code= world->item.flush(creators_ptr, run)))
+        {
+          // @note pre will fail is SKIPPED is returned
+          if (test_success(return_code= world->item.pre(creators_ptr)))
+          {
+            { // Runner Code
+              gettimeofday(&start_time, NULL);
+              return_code= world->runner->run(run->test_fn, creators_ptr);
+              gettimeofday(&end_time, NULL);
+              load_time= timedif(end_time, start_time);
+            }
+          }
+
+          // @todo do something if post fails
+          (void)world->item.post(creators_ptr);
+        }
+        else
+        {
+          Error << " item.flush(failure)";
+        }
+      }
+      else
+      {
+        Error << " item.startup(failure)";
       }
-
-      world.item.post(world_ptr);
 
       stats.total++;
 
-      std::cerr << "\t\t\t\t\t";
-
       switch (return_code)
       {
       case TEST_SUCCESS:
-       std::cerr << load_time / 1000 << "." << load_time % 1000;
-       stats.success++;
-       break;
+        Log << "\tTesting " << run->name <<  "\t\t\t\t\t" << load_time / 1000 << "." << load_time % 1000 << "[ " << test_strerror(return_code) << " ]";
+        stats.success++;
+        break;
 
       case TEST_FATAL:
       case TEST_FAILURE:
-       stats.failed++;
-       failed= true;
-       break;
+        stats.failed++;
+        failed= true;
+        Error << "\tTesting " << run->name <<  "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
+        break;
 
       case TEST_SKIPPED:
-       stats.skipped++;
-       skipped= true;
-       break;
+        stats.skipped++;
+        skipped= true;
+        Log << "\tTesting " << run->name <<  "\t\t\t\t\t" << "[ " << test_strerror(return_code) << " ]";
+        break;
 
       case TEST_MEMORY_ALLOCATION_FAILURE:
-       test_assert(0, "Memory Allocation Error");
+        test_assert(0, "Memory Allocation Error");
       }
 
-      std::cerr << "[ " << test_strerror(return_code) << " ]" << std::endl;
-
-      if (test_failed(world.on_error(return_code, world_ptr)))
+      if (test_failed(world->on_error(return_code, creators_ptr)))
       {
+        Error << "Failed while running on_error()";
         break;
       }
+
+      Logn();
     }
 
-    if (next->post && world.runner->post)
+    if (next->post and world->runner->post)
     {
-      (void) world.runner->post(next->post, world_ptr);
+      (void) world->runner->post(next->post, creators_ptr);
     }
 
     if (failed == 0 and skipped == 0)
@@ -293,27 +405,34 @@ int main(int argc, char *argv[])
     }
 cleanup:
 
-    world.shutdown(world_ptr);
+    world->shutdown(creators_ptr);
   }
 
-  if (stats.collection_failed || stats.collection_skipped)
+  if (not is_shutdown())
   {
-    std::cerr << std::endl << std::endl <<  "Some test failures and/or skipped test occurred." << std::endl << std::endl;
-#if 0
-    print_failed_test();
-#endif
+    set_shutdown(SHUTDOWN_GRACEFUL);
+    pthread_kill(thread, SIGUSR1);
   }
-  else
+
+  if (__shutdown == SHUTDOWN_FORCED)
   {
-    std::cout << std::endl << std::endl <<  "All tests completed successfully." << std::endl << std::endl;
+    Error << "Tests were aborted.";
   }
-
-  if (test_failed(world.destroy(world_ptr)))
+  else if (stats.collection_failed or stats.collection_skipped)
   {
-    stats.failed++; // We do this to make our exit code return EXIT_FAILURE
+    Error << "Some test failures and/or skipped test occurred.";
+  }
+  else
+  {
+    Log << "All tests completed successfully.";
   }
 
   stats_print(&stats);
 
-  return stats.failed == 0 ? 0 : 1;
+  void *retval;
+  pthread_join(thread, &retval);
+
+  delete world;
+
+  return stats.failed == 0 and __shutdown == SHUTDOWN_GRACEFUL ? EXIT_SUCCESS : EXIT_FAILURE;
 }
index c36572ea00776867f7b30601506b0b8ccd2eccb5..4665043e9e72fbd539c85f69d09e24bed83c1051 100644 (file)
@@ -7,6 +7,10 @@
 
 #pragma once
 
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
 /**
   A structure describing the test case.
 */
@@ -16,16 +20,14 @@ struct test_st {
   test_callback_fn *test_fn;
 };
 
-#define TEST_STRINGIFY(x) #x
-#define TEST_TOSTRING(x) TEST_STRINGIFY(x)
-#define TEST_AT __FILE__ ":" TEST_TOSTRING(__LINE__)
-
+LIBTEST_API
+bool test_is_local(void);
 
 #define test_assert_errno(A) \
 do \
 { \
   if ((A)) { \
-    fprintf(stderr, "\nAssertion failed at %s:%d: ", __FILE__, __LINE__);\
+    fprintf(stderr, "\n%s:%d: Assertion failed for %s: ", __FILE__, __LINE__, __func__);\
     perror(#A); \
     fprintf(stderr, "\n"); \
     create_core(); \
@@ -37,7 +39,7 @@ do \
 do \
 { \
   if ((A)) { \
-    fprintf(stderr, "\nAssertion, %s(%s), failed at %s:%d: ", (B), #A, __FILE__, __LINE__);\
+    fprintf(stderr, "\n%s:%d: Assertion failed %s, with message %s, in %s", __FILE__, __LINE__, (B), #A, __func__ );\
     fprintf(stderr, "\n"); \
     create_core(); \
     assert((A)); \
@@ -48,7 +50,7 @@ do \
 do \
 { \
   if (! (A)) { \
-    fprintf(stderr, "\nAssertion failed at %s:%d: %s\n", __FILE__, __LINE__, #A);\
+    fprintf(stderr, "\n%s:%d: Assertion \"%s\" failed, in %s\n", __FILE__, __LINE__, #A, __func__);\
     create_core(); \
     return TEST_FAILURE; \
   } \
@@ -58,7 +60,7 @@ do \
 do \
 { \
   if (! (A)) { \
-    fprintf(stderr, "\nAssertion failed at %s:%d: %s\n", __FILE__, __LINE__, #A);\
+    fprintf(stderr, "\n%s:%d: Assertion \"%s\" failed, in %s\n", __FILE__, __LINE__, #A, __func__);\
     create_core(); \
     return TEST_FAILURE; \
   } \
@@ -68,7 +70,7 @@ do \
 do \
 { \
   if (! (A)) { \
-    fprintf(stderr, "\nAssertion failed at %s:%d: \"%s\" received \"%s\"\n", __FILE__, __LINE__, #A, (B));\
+    fprintf(stderr, "\n%s:%d: Assertion \"%s\" failed, received \"%s\"\n", __FILE__, __LINE__, #A, (B));\
     create_core(); \
     return TEST_FAILURE; \
   } \
@@ -87,7 +89,7 @@ do \
 do \
 { \
   if (1) { \
-    fprintf(stderr, "\nFailed at %s:%d: %s\n", __FILE__, __LINE__, #A);\
+    fprintf(stderr, "\n%s:%d: Failed with %s, in %s\n", __FILE__, __LINE__, #A, __func__);\
     create_core(); \
     return TEST_FAILURE; \
   } \
@@ -98,7 +100,7 @@ do \
 do \
 { \
   if ((A)) { \
-    fprintf(stderr, "\nAssertion failed in %s:%d: %s\n", __FILE__, __LINE__, #A);\
+    fprintf(stderr, "\n%s:%d: Assertion failed %s, in %s\n", __FILE__, __LINE__, #A, __func__);\
     create_core(); \
     return TEST_FAILURE; \
   } \
@@ -108,7 +110,7 @@ do \
 do \
 { \
   if ((A)) { \
-    fprintf(stderr, "\nAssertion failed at %s:%d: %s with %s\n", __FILE__, __LINE__, #A, (B));\
+    fprintf(stderr, "\n%s:%d: Assertion failed %s with %s\n", __FILE__, __LINE__, #A, (B));\
     create_core(); \
     return TEST_FAILURE; \
   } \
@@ -160,3 +162,12 @@ do \
   } \
 } while (0)
 
+#define test_return_if(__test_return_t) \
+do \
+{ \
+  if ((__test_return_t) != TEST_SUCCESS) \
+  { \
+    return __test_return_t; \
+  } \
+} while (0)
+
index 5953f82c3d36a8e4701eb8225a17290effcd8757..71cd707f4f612f6cfe72b5418deb222d2f537fa0 100644 (file)
@@ -1,12 +1,41 @@
-/* uTest
- * Copyright (C) 2011 Data Differential, http://datadifferential.com/
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest, libtest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  Copyright (C) 2006-2009 Brian Aker
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
  */
 
+
 /*
   Structures for generic tests.
 */
@@ -28,6 +57,7 @@
 #include <libtest/collection.h>
 #include <libtest/framework.h>
 #include <libtest/get.h>
+#include <libtest/stream.h>
 
 #pragma once
 
@@ -37,6 +67,12 @@ LIBTEST_API
 LIBTEST_API
   void set_default_port(in_port_t port);
 
+LIBTEST_API
+  const char* default_socket();
+
+LIBTEST_API
+  void set_default_socket(const char *socket);
+
 #ifdef __cplusplus
 #define test_literal_param(X) (X), (static_cast<size_t>((sizeof(X) - 1)))
 #else
diff --git a/libtest/unittest.cc b/libtest/unittest.cc
new file mode 100644 (file)
index 0000000..e0df62f
--- /dev/null
@@ -0,0 +1,87 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest self unit test.
+ *
+ *  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 <config.h>
+#include <libtest/test.hpp>
+
+static test_return_t test_success_test(void *)
+{
+  return TEST_SUCCESS;
+}
+
+static test_return_t local_test(void *)
+{
+  char buffer[sizeof("LIBTEST_LOCAL=1")];
+
+  snprintf(buffer, sizeof(buffer), "%s", "LIBTEST_LOCAL=1");
+  test_compare(0, putenv(buffer));
+
+  test_true(test_is_local());
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t local_not_test(void *)
+{
+  test_compare(0, unsetenv("LIBTEST_LOCAL"));
+
+  test_false(test_is_local());
+
+  return TEST_SUCCESS;
+}
+
+test_st tests_log[] ={
+  {"TEST_SUCCESS", 0, test_success_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}
+};
+
+collection_st collection[] ={
+  {"return values", 0, 0, tests_log},
+  {"local", 0, 0, local_log},
+  {0, 0, 0, 0}
+};
+
+void get_world(Framework *arg)
+{
+  arg->collections= collection;
+}
diff --git a/libtest/wait.cc b/libtest/wait.cc
new file mode 100644 (file)
index 0000000..9326591
--- /dev/null
@@ -0,0 +1,54 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <config.h>
+
+#include <cstdlib>
+#include <libtest/wait.h>
+
+int main(int argc, char *argv[])
+{
+  if (argc == 2)
+  {
+    libtest::Wait wait(argv[1]);
+
+    if (wait.successful())
+      return EXIT_SUCCESS;
+  }
+
+  return EXIT_FAILURE;
+}
diff --git a/libtest/wait.h b/libtest/wait.h
new file mode 100644 (file)
index 0000000..33c4db5
--- /dev/null
@@ -0,0 +1,78 @@
+/*  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
+ * 
+ *  uTest
+ *
+ *  Copyright (C) 2011 Data Differential, http://datadifferential.com/
+ *  All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are
+ *  met:
+ *
+ *      * Redistributions of source code must retain the above copyright
+ *  notice, this list of conditions and the following disclaimer.
+ *
+ *      * Redistributions in binary form must reproduce the above
+ *  copyright notice, this list of conditions and the following disclaimer
+ *  in the documentation and/or other materials provided with the
+ *  distribution.
+ *
+ *      * The names of its contributors may not be used to endorse or
+ *  promote products derived from this software without specific prior
+ *  written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#pragma once
+
+#include <unistd.h>
+#include <string>
+
+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;
+
+    for (waited= 0, retry= 1; ; retry++, waited+= this_wait)
+    {
+      if ((not access(filename.c_str(), R_OK)) or (waited >= timeout))
+      {
+        _successful= true;
+        break;
+      }
+
+      this_wait= retry * retry / 3 + 1;
+      sleep(this_wait);
+    }
+  }
+
+  bool successful() const
+  {
+    return _successful;
+  }
+
+private:
+  bool _successful;
+};
+
+} // namespace libtest
diff --git a/m4/pandora_have_libboost_date_time.m4 b/m4/pandora_have_libboost_date_time.m4
deleted file mode 100644 (file)
index 71c3efe..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-dnl Copyright (C) 2010 Monty Taylor
-dnl This file is free software; Monty Taylor
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-AC_DEFUN([_PANDORA_SEARCH_BOOST_DATE_TIME],[
-  AC_REQUIRE([AC_LIB_PREFIX])
-  AC_REQUIRE([ACX_PTHREAD])
-
-  dnl --------------------------------------------------------------------
-  dnl  Check for Boost.Date_Time
-  dnl --------------------------------------------------------------------
-
-  AC_LANG_PUSH(C++)
-  AC_LIB_HAVE_LINKFLAGS(boost_date_time-mt,,[
-    #include <boost/date_time.hpp>
-  ],[
-    boost::gregorian::date weekstart(2002,2,1);
-  ])
-  AS_IF([test "x${ac_cv_libboost_date_time_mt}" = "xno"],[
-    AC_LIB_HAVE_LINKFLAGS(boost_date_time,,[
-      #include <boost/date_time.hpp>
-    ],[
-      boost::gregorian::date weekstart(2002,2,1);
-    ])
-  ])
-  AC_LANG_POP()
-  
-  AM_CONDITIONAL(HAVE_BOOST_DATE_TIME,
-    [test "x${ac_cv_libboost_date_time}" = "xyes" -o "x${ac_cv_libboost_date_time_mt}" = "xyes"])
-  BOOST_LIBS="${BOOST_LIBS} ${LTLIBBOOST_DATE_TIME_MT} ${LTLIBBOOST_DATE_TIME}"
-  AC_SUBST(BOOST_LIBS) 
-])
-
-AC_DEFUN([PANDORA_HAVE_BOOST_DATE_TIME],[
-  PANDORA_HAVE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_DATE_TIME($1)
-])
-
-AC_DEFUN([PANDORA_REQUIRE_BOOST_DATE_TIME],[
-  PANDORA_REQUIRE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_DATE_TIME($1)
-  AS_IF([test "x${ac_cv_libboost_date_time}" = "xno" -a "x${ac_cv_libboost_date_time_mt}" = "xno"],
-      AC_MSG_ERROR([Boost.Date_Time is required for ${PACKAGE}]))
-])
-
diff --git a/m4/pandora_have_libboost_filesystem.m4 b/m4/pandora_have_libboost_filesystem.m4
deleted file mode 100644 (file)
index ea6953e..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-dnl Copyright (C) 2010 Monty Taylor
-dnl This file is free software; Monty Taylor
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-AC_DEFUN([_PANDORA_SEARCH_BOOST_FILESYSTEM],[
-  AC_REQUIRE([AC_LIB_PREFIX])
-
-  dnl --------------------------------------------------------------------
-  dnl  Check for Boost.Filesystem
-  dnl --------------------------------------------------------------------
-
-  AC_LANG_PUSH(C++)
-  AC_LIB_HAVE_LINKFLAGS(boost_filesystem-mt,boost_system-mt,[
-    #include <boost/filesystem.hpp>
-  ],[
-    boost::filesystem::path my_path("some_dir/file.txt");
-  ])
-  AS_IF([test "x${ac_cv_libboost_filesystem_mt}" = "xno"],[
-    AC_LIB_HAVE_LINKFLAGS(boost_filesystem,boost_system,[
-      #include <boost/filesystem.hpp>
-    ],[
-      boost::filesystem::path my_path("some_dir/file.txt");
-    ])
-  ])
-  AC_LANG_POP()
-  
-  AM_CONDITIONAL(HAVE_BOOST_FILESYSTEM,
-    [test "x${ac_cv_libboost_filesystem}" = "xyes" -o "x${ac_cv_libboost_filesystem_mt}" = "xyes"])
-  BOOST_LIBS="${BOOST_LIBS} ${LTLIBBOOST_FILESYSTEM_MT} ${LTLIBBOOST_FILESYSTEM}"
-  AC_DEFINE([BOOST_FILESYSTEM_DEPRECATED], [1],
-            [Use the v2 interface until we can stop using old versions])
-  AC_SUBST(BOOST_LIBS) 
-])
-
-AC_DEFUN([PANDORA_HAVE_BOOST_FILESYSTEM],[
-  PANDORA_HAVE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_FILESYSTEM($1)
-])
-
-AC_DEFUN([PANDORA_REQUIRE_BOOST_FILESYSTEM],[
-  PANDORA_REQUIRE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_FILESYSTEM($1)
-  AS_IF([test "x${ac_cv_libboost_filesystem}" = "xno" -a "x${ac_cv_libboost_filesystem_mt}" = "xno"],
-      AC_MSG_ERROR([Boost.Filesystem is required for ${PACKAGE}]))
-])
-
diff --git a/m4/pandora_have_libboost_iostreams.m4 b/m4/pandora_have_libboost_iostreams.m4
deleted file mode 100644 (file)
index e9ac7b6..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-dnl Copyright (C) 2010 Andrew Hutchings
-dnl This file is free software; Andrew Hutchings
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-AC_DEFUN([_PANDORA_SEARCH_BOOST_IOSTREAMS],[
-  AC_REQUIRE([AC_LIB_PREFIX])
-
-  dnl --------------------------------------------------------------------
-  dnl  Check for Boost.Iostreams
-  dnl --------------------------------------------------------------------
-
-  AC_LANG_PUSH(C++)
-  AC_LIB_HAVE_LINKFLAGS(boost_iostreams-mt,,[
-    #include <boost/iostreams/stream.hpp>
-    #include <boost/iostreams/device/array.hpp>
-  ],[
-    const char* input= "hello world";
-    boost::iostreams::stream<boost::iostreams::array_source> in(input, strlen(input));
-  ])
-  AS_IF([test "x${ac_cv_libboost_iostreams_mt}" = "xno"],[
-    AC_LIB_HAVE_LINKFLAGS(boost_iostreams,,[
-      #include <boost/iostreams/stream.hpp>
-      #include <boost/iostreams/device/array.hpp>
-    ],[
-      const char* input= "hello world";
-      boost::iostreams::stream<boost::iostreams::array_source> in(input, strlen(input));
-    ])
-  ])
-  AC_LANG_POP()
-  
-  AM_CONDITIONAL(HAVE_BOOST_IOSTREAMS,
-    [test "x${ac_cv_libboost_iostreams}" = "xyes" -o "x${ac_cv_libboost_iostreams_mt}" = "xyes"])
-  BOOST_LIBS="${BOOST_LIBS} ${LTLIBBOOST_IOSTREAMS_MT} ${LTLIBBOOST_IOSTREAMS}"
-  AC_SUBST(BOOST_LIBS) 
-])
-
-AC_DEFUN([PANDORA_HAVE_BOOST_IOSTREAMS],[
-  PANDORA_HAVE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_IOSTREAMS($1)
-])
-
-AC_DEFUN([PANDORA_REQUIRE_BOOST_IOSTREAMS],[
-  PANDORA_REQUIRE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_IOSTREAMS($1)
-  AS_IF([test "x${ac_cv_libboost_iostreams}" = "xno" -a "x${ac_cv_libboost_iostreams_mt}" = "xno"],
-      AC_MSG_ERROR([Boost.Iostreams is required for ${PACKAGE}]))
-])
-
diff --git a/m4/pandora_have_libboost_options.m4 b/m4/pandora_have_libboost_options.m4
deleted file mode 100644 (file)
index 43fc03f..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-dnl Copyright (C) 2010 Monty Taylor
-dnl This file is free software; Monty Taylor
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-AC_DEFUN([_PANDORA_SEARCH_BOOST_PROGRAM_OPTIONS],[
-  AC_REQUIRE([AC_LIB_PREFIX])
-
-  dnl --------------------------------------------------------------------
-  dnl  Check for boost::program_options
-  dnl --------------------------------------------------------------------
-
-  AC_LANG_PUSH(C++)
-  AC_LIB_HAVE_LINKFLAGS(boost_program_options-mt,,[
-    #include <boost/program_options.hpp>
-  ],[
-    boost::program_options::options_description d;
-    d.add_options()("a","some option");
-  ])
-  AS_IF([test "x${ac_cv_libboost_program_options_mt}" = "xno"],[
-    AC_LIB_HAVE_LINKFLAGS(boost_program_options,,[
-      #include <boost/program_options.hpp>
-    ],[
-      boost::program_options::options_description d;
-      d.add_options()("a","some option");
-    ])
-  ])
-  AC_LANG_POP()
-  
-  AM_CONDITIONAL(HAVE_BOOST_PROGRAM_OPTIONS,
-    [test "x${ac_cv_libboost_program_options}" = "xyes" -o "x${ac_cv_libboost_program_options_mt}" = "xyes"])
-  BOOST_LIBS="${BOOST_LIBS} ${LTLIBBOOST_PROGRAM_OPTIONS} ${LTLIBBOOST_PROGRAM_OPTIONS_MT}"
-  AC_SUBST(BOOST_LIBS) 
-])
-
-AC_DEFUN([PANDORA_HAVE_BOOST_PROGRAM_OPTIONS],[
-  PANDORA_HAVE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_PROGRAM_OPTIONS($1)
-])
-
-AC_DEFUN([PANDORA_REQUIRE_BOOST_PROGRAM_OPTIONS],[
-  PANDORA_REQUIRE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_PROGRAM_OPTIONS($1)
-  AS_IF([test "x${ac_cv_libboost_program_options}" = "xno" -a "x${ac_cv_libboost_program_options_mt}" = "xno"],
-      AC_MSG_ERROR([boost::program_options is required for ${PACKAGE}]))
-])
-
diff --git a/m4/pandora_have_libboost_regex.m4 b/m4/pandora_have_libboost_regex.m4
deleted file mode 100644 (file)
index 50a496a..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-dnl Copyright (C) 2010 Andrew Hutchings
-dnl This file is free software; Andrew Hutchings
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-AC_DEFUN([_PANDORA_SEARCH_BOOST_REGEX],[
-  AC_REQUIRE([AC_LIB_PREFIX])
-  AC_REQUIRE([ACX_PTHREAD])
-
-  dnl --------------------------------------------------------------------
-  dnl  Check for boost::regex
-  dnl --------------------------------------------------------------------
-
-  save_CFLAGS="${CFLAGS}"
-  save_CXXFLAGS="${CXXFLAGS}"
-  CFLAGS="${PTHREAD_CFLAGS} ${CFLAGS}"
-  CXXFLAGS="${PTHREAD_CFLAGS} ${CXXFLAGS}"
-
-  AC_LANG_PUSH(C++)
-  AC_LIB_HAVE_LINKFLAGS(boost_regex-mt,,[
-    #include <boost/regex.hpp>
-  ],[
-    boost::regex test_regex("drizzle");
-  ])
-  AS_IF([test "x${ac_cv_libboost_regex_mt}" = "xno"],[
-    AC_LIB_HAVE_LINKFLAGS(boost_regex,,[
-      #include <boost/regex.hpp>
-    ],[
-      boost::regex test_regex("drizzle");
-    ])
-  ])
-  AC_LANG_POP()
-  CFLAGS="${save_CFLAGS}"
-  CXXFLAGS="${save_CXXFLAGS}"
-
-  
-  AM_CONDITIONAL(HAVE_BOOST_REGEX,
-    [test "x${ac_cv_libboost_regex}" = "xyes" -o "x${ac_cv_libboost_regex_mt}" = "xyes"])
-  BOOST_LIBS="${BOOST_LIBS} ${LTLIBBOOST_REGEX_MT} ${LTLIBBOOST_REGEX}"
-  AC_SUBST(BOOST_LIBS) 
-])
-
-AC_DEFUN([PANDORA_HAVE_BOOST_REGEX],[
-  PANDORA_HAVE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_REGEX($1)
-])
-
-AC_DEFUN([PANDORA_REQUIRE_BOOST_REGEX],[
-  PANDORA_REQUIRE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_REGEX($1)
-  AS_IF([test "x${ac_cv_libboost_regex}" = "xno" -a "x${ac_cv_libboost_regex_mt}" = "xno"],
-      AC_MSG_ERROR([boost::regex is required for ${PACKAGE}]))
-])
-
diff --git a/m4/pandora_have_libboost_test.m4 b/m4/pandora_have_libboost_test.m4
deleted file mode 100644 (file)
index 7a526c0..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-dnl Copyright (C) 2011 Andrew Hutchings
-dnl This file is free software; Andrew Hutchings
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-AC_DEFUN([_PANDORA_SEARCH_BOOST_TEST],[
-  AC_REQUIRE([AC_LIB_PREFIX])
-
-  dnl --------------------------------------------------------------------
-  dnl  Check for boost::test
-  dnl --------------------------------------------------------------------
-
-  AC_LANG_PUSH(C++)
-  AC_LIB_HAVE_LINKFLAGS(boost_unit_test_framework-mt,,[
-    #include <boost/test/unit_test.hpp>
-  ],[
-    boost::unit_test::unit_test_log.set_threshold_level(boost::unit_test::log_messages);
-  ])
-  AS_IF([test "x${ac_cv_libboost_unit_test_framework_mt}" = "xno"],[
-    AC_LIB_HAVE_LINKFLAGS(boost_unit_test_framework,,[
-      #include <boost/test/unit_test.hpp>
-    ],[
-      boost::unit_test::unit_test_log.set_threshold_level(boost::unit_test::log_messages);
-    ])
-  ])
-  AC_LANG_POP()
-  
-  AM_CONDITIONAL(HAVE_BOOST_TEST,
-    [test "x${ac_cv_libboost_unit_test_framework}" = "xyes" -o "x${ac_cv_libboost_unit_test_framework_mt}" = "xyes"])
-  BOOST_LIBS="${BOOST_LIBS} ${LTLIBBOOST_TEST_MT} ${LTLIBBOOST_TEST}"
-  AC_SUBST(BOOST_LIBS) 
-])
-
-AC_DEFUN([PANDORA_HAVE_BOOST_TEST],[
-  PANDORA_HAVE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_TEST($1)
-])
-
-AC_DEFUN([PANDORA_REQUIRE_BOOST_TEST],[
-  PANDORA_REQUIRE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_TEST($1)
-  AS_IF([test "x${ac_cv_libboost_unit_test_framework}" = "xno" -a "x${ac_cv_libboost_unit_test_framework_mt}" = "xno"],
-      AC_MSG_ERROR([boost::test is required for ${PACKAGE}]))
-])
-
diff --git a/m4/pandora_have_libboost_thread.m4 b/m4/pandora_have_libboost_thread.m4
deleted file mode 100644 (file)
index e3359fb..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-dnl Copyright (C) 2010 Monty Taylor
-dnl This file is free software; Monty Taylor
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-AC_DEFUN([_PANDORA_SEARCH_BOOST_THREAD],[
-  AC_REQUIRE([AC_LIB_PREFIX])
-  AC_REQUIRE([ACX_PTHREAD])
-
-  dnl --------------------------------------------------------------------
-  dnl  Check for boost::thread
-  dnl --------------------------------------------------------------------
-
-  save_CFLAGS="${CFLAGS}"
-  save_CXXFLAGS="${CXXFLAGS}"
-  CFLAGS="${PTHREAD_CFLAGS} ${CFLAGS}"
-  CXXFLAGS="${PTHREAD_CFLAGS} ${CXXFLAGS}"
-
-  AC_LANG_PUSH(C++)
-  AC_LIB_HAVE_LINKFLAGS(boost_thread-mt,,[
-    #include <boost/thread.hpp>
-  ],[
-    boost::thread id;
-  ])
-  AS_IF([test "x${ac_cv_libboost_thread_mt}" = "xno"],[
-    AC_LIB_HAVE_LINKFLAGS(boost_thread,,[
-      #include <boost/thread.hpp>
-    ],[
-      boost::thread id;
-    ])
-  ])
-  AC_LANG_POP()
-  CFLAGS="${save_CFLAGS}"
-  CXXFLAGS="${save_CXXFLAGS}"
-
-  
-  AM_CONDITIONAL(HAVE_BOOST_THREAD,
-    [test "x${ac_cv_libboost_thread}" = "xyes" -o "x${ac_cv_libboost_thread_mt}" = "xyes"])
-  BOOST_LIBS="${BOOST_LIBS} ${LTLIBBOOST_THREAD_MT} ${LTLIBBOOST_THREAD}"
-  AC_SUBST(BOOST_LIBS) 
-])
-
-AC_DEFUN([PANDORA_HAVE_BOOST_THREAD],[
-  PANDORA_HAVE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_THREAD($1)
-])
-
-AC_DEFUN([PANDORA_REQUIRE_BOOST_THREAD],[
-  PANDORA_REQUIRE_BOOST($1)
-  _PANDORA_SEARCH_BOOST_THREAD($1)
-  AS_IF([test "x${ac_cv_libboost_thread}" = "xno" -a "x${ac_cv_libboost_thread_mt}" = "xno"],
-      AC_MSG_ERROR([boost::thread is required for ${PACKAGE}]))
-])
-
index a525b95e3dd8cc0eabbd36735f97faaf31c74554..af692c6b43a67ffa387f7f298db25b0d825616db 100644 (file)
@@ -12,7 +12,7 @@
 /*
   Sample test application.
 */
-#include "config.h"
+#include <libtest/common.h>
 
 #include <libmemcached/memcached.h>
 #include <libmemcached/watchpoint.h>
@@ -30,7 +30,6 @@
 #include <clients/execute.h>
 
 #include <libtest/server.h>
-#include <libtest/test.hpp>
 
 /* Number of items generated for tests */
 #define GLOBAL_COUNT 100000
index 8f57e4c5ec7776bd6ffed3904ad4d3d3f5790840..666fa4d6ca0735fdea94d068c29b2abb88bf9241 100644 (file)
  *
  */
 
+#include <libtest/common.h>
+
 #include <libmemcached/memcached.h>
 #include <libmemcached/is.h>
 
-#include <libtest/test.hpp>
-
 #include "tests/basic.h"
 
 #include <cstring>
index fd0b00f47d74d6588bcdefaa6dd25b43b28da1ae..f84af7596e25759e9e55847508208793cb1cba37 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * An example file showing the usage of the C++ libmemcached interface.
  */
+#include <config.h>
 
 #include <vector>
 #include <string>
diff --git a/tests/cycle.cc b/tests/cycle.cc
new file mode 100644 (file)
index 0000000..493126b
--- /dev/null
@@ -0,0 +1,169 @@
+/*  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.
+ *
+ */
+
+
+/*
+  Test that we are cycling the servers we are creating during testing.
+*/
+
+#include <libtest/common.h>
+
+#include <libmemcached/common.h>
+#include <libmemcached/is.h>
+#include <libmemcached/util.h>
+
+#include <iostream>
+
+
+#include <libtest/server.h>
+
+#define SERVERS_TO_CREATE 5
+
+#ifndef __INTEL_COMPILER
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#endif
+
+static test_return_t alive(memcached_st *memc)
+{
+  test_true(memc);
+  test_true(memcached_is_allocated(memc));
+  for (uint32_t x= 0; x < memcached_server_count(memc); ++x)
+  {
+    memcached_server_instance_st instance= memcached_server_instance_by_position(memc, x);
+    test_true(instance);
+
+    test_true(libmemcached_util_ping(memcached_server_name(instance),
+                                     memcached_server_port(instance), NULL));
+  }
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t valid(memcached_st *memc)
+{
+  test_true(memc);
+  test_true(memcached_is_allocated(memc));
+
+  for (uint32_t x= 0; x < memcached_server_count(memc); ++x)
+  {
+    memcached_server_instance_st instance= memcached_server_instance_by_position(memc, x);
+    test_true(instance);
+
+    pid_t pid= libmemcached_util_getpid(memcached_server_name(instance),
+                                        memcached_server_port(instance), NULL);
+    test_true(pid != -1);
+  }
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t kill_test(memcached_st *)
+{
+  static struct timespec global_sleep_value= { 2, 0 };
+
+#ifdef WIN32
+  sleep(1);
+#else
+  nanosleep(&global_sleep_value, NULL);
+#endif
+
+  return TEST_SUCCESS;
+}
+
+test_st ping_tests[] ={
+  {"alive", true, (test_callback_fn*)alive },
+  {0, 0, 0}
+};
+
+test_st getpid_tests[] ={
+  {"valid", true, (test_callback_fn*)valid },
+  {0, 0, 0}
+};
+
+test_st kill_tests[] ={
+  {"kill", true, (test_callback_fn*)kill_test },
+  {0, 0, 0}
+};
+
+collection_st collection[] ={
+  {"libmemcached_util_ping()", 0, 0, ping_tests},
+  {"libmemcached_util_getpid()", 0, 0, getpid_tests},
+  {"kill", 0, 0, kill_tests},
+  {0, 0, 0, 0}
+};
+
+#if 0
+static server_startup_st *world_create(test_return_t *error)
+{
+  server_startup_st *servers= new server_startup_st();
+
+  server_startup(servers);
+
+  *error= TEST_SUCCESS;
+
+  return servers;
+}
+
+static test_return_t world_destroy(server_startup_st *servers)
+{
+  server_shutdown(servers);
+  delete servers;
+
+  return TEST_SUCCESS;
+}
+#endif
+
+
+#include "tests/libmemcached_world.h"
+
+void get_world(Framework *world)
+{
+  world->collections= collection;
+
+  world->_create= (test_callback_create_fn*)world_create;
+  world->_destroy= (test_callback_fn*)world_destroy;
+
+  world->item._startup= (test_callback_fn*)world_test_startup;
+  world->item.set_pre((test_callback_fn*)world_pre_run);
+  world->item.set_post((test_callback_fn*)world_post_run);
+  world->_on_error= (test_callback_error_fn*)world_on_error;
+
+  world->collection_startup= (test_callback_fn*)world_container_startup;
+  world->collection_shutdown= (test_callback_fn*)world_container_shutdown;
+
+  world->runner= &defualt_libmemcached_runner;
+}
+
index eebc7d06e5fe1f0478d97b5036caff281ba18066..ab40b6392706fa9e4a7276dedb893cf389f2d6b6 100644 (file)
  *
  */
 
-#include <config.h>
+#include <libtest/common.h>
 
 #include <cassert>
 
-#include <libtest/test.hpp>
 #include <libmemcached/memcached.h>
 #include <tests/deprecated.h>
 
@@ -50,13 +49,16 @@ test_return_t server_list_null_test(memcached_st *ptr)
   (void)ptr;
 
   server_list= memcached_server_list_append_with_weight(NULL, NULL, 0, 0, NULL);
-  test_true(server_list == NULL);
+  test_true(server_list);
+  memcached_server_list_free(server_list);
 
   server_list= memcached_server_list_append_with_weight(NULL, "localhost", 0, 0, NULL);
-  test_true(server_list == NULL);
+  test_true(server_list);
+  memcached_server_list_free(server_list);
 
   server_list= memcached_server_list_append_with_weight(NULL, NULL, 0, 0, &rc);
-  test_true(server_list == NULL);
+  test_true(server_list);
+  memcached_server_list_free(server_list);
 
   return TEST_SUCCESS;
 }
@@ -64,7 +66,7 @@ test_return_t server_list_null_test(memcached_st *ptr)
 // Look for memory leak
 test_return_t regression_bug_728286(memcached_st *)
 {
-  memcached_server_st *servers = memcached_servers_parse("1.2.3.4:99");
+  memcached_server_st *servers= memcached_servers_parse("1.2.3.4:99");
   assert(servers);
   memcached_server_free(servers);
 
index 09a01eb47a98b4acfa40c92bd14bc0f09fbb7598..ad4e2c8372055842d1116a1990711155814013bc 100644 (file)
  *
  */
 
-#include <config.h>
+#include <libtest/common.h>
 
 #define BUILDING_LIBMEMCACHED
 
 #include <libmemcached/memcached.h>
 #include <libmemcached/is.h>
 
-#include <libtest/test.hpp>
-
 #include <tests/error_conditions.h>
 
 test_return_t memcached_increment_MEMCACHED_NO_SERVERS(memcached_st *)
index e3130786f2606aa9844b8b0ec0fc9ff61df078f1..aa38a8654733d082eb80ae27999e74f073bbd528 100644 (file)
@@ -2,9 +2,7 @@
   C++ to libhashkit
 */
 
-#include <config.h>
-
-#include <libtest/test.hpp>
+#include <libtest/common.h>
 
 #include <cstdio>
 #include <cstdlib>
index 98396df5fa79dc4359fea411bb409b1c4d358589..42abcb620ff24541e1790ffdc42967f4198dca80 100644 (file)
@@ -35,7 +35,7 @@
  *
  */
 
-#include "config.h"
+#include <libtest/common.h>
 
 #include <assert.h>
 #include <stdio.h>
@@ -44,8 +44,6 @@
 
 #include <libhashkit/hashkit.h>
 
-#include <libtest/test.hpp>
-
 #include "hash_results.h"
 
 static hashkit_st global_hashk;
index 7ce21a1279f394e3bc4dec93e2ced4431a68a981..557e4419f796334253e441b386d07cb6393bff92 100644 (file)
@@ -13,8 +13,6 @@ TESTS_LDADDS= \
              libtest/libserver.la \
              libtest/libtest.la
 
-VALGRIND_COMMAND= $(LIBTOOL) --mode=execute valgrind --leak-check=yes --show-reachable=yes --track-fds=yes --malloc-fill=A5 --free-fill=DE
-
 DEBUG_COMMAND= $(LIBTOOL) --mode=execute gdb
 
 PAHOLE_COMMAND= $(LIBTOOL) --mode=execute pahole
@@ -34,6 +32,7 @@ noinst_HEADERS+= \
                 tests/ketama_test_cases.h \
                 tests/ketama_test_cases_spy.h \
                 tests/libmemcached_world.h \
+                tests/namespace.h \
                 tests/parser.h \
                 tests/deprecated.h \
                 tests/pool.h \
@@ -45,19 +44,28 @@ noinst_HEADERS+= \
 
 noinst_PROGRAMS+= \
                  tests/atomsmasher \
+                 tests/cycle \
                  tests/hash_plus \
-                 tests/startservers \
                  tests/testapp \
                  tests/testhashkit \
                  tests/testplus \
                  tests/testudp
 
+# Cycle should always run first
+tests_cycle_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
+tests_cycle_SOURCES= tests/cycle.cc
+tests_cycle_DEPENDENCIES= $(TESTS_LDADDS)
+tests_cycle_LDADD= $(tests_cycle_DEPENDENCIES)
+check_PROGRAMS+= tests/cycle
+
+
 tests_testapp_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
 tests_testapp_SOURCES= \
                       tests/basic.cc \
                       tests/deprecated.cc \
                       tests/error_conditions.cc \
                       tests/mem_functions.cc \
+                      tests/namespace.cc \
                       tests/parser.cc \
                       tests/pool.cc \
                       tests/print.cc \
@@ -77,6 +85,7 @@ tests_testapp_LDADD= \
                     $(TESTS_LDADDS) \
                     libhashkit/libhashkit.la \
                     libmemcached/libmemcachedinternal.la
+check_PROGRAMS+= tests/testapp
 
 tests_testplus_SOURCES= tests/plus.cpp
 tests_testplus_CXXFLAGS = $(AM_CXXFLAGS) $(NO_EFF_CXX)
@@ -84,25 +93,23 @@ tests_testplus_DEPENDENCIES= $(TESTS_LDADDS)
 tests_testplus_LDADD= $(tests_testplus_DEPENDENCIES) $(LIBSASL)
 check_PROGRAMS+= tests/testplus
 
-tests_atomsmasher_SOURCES= tests/atomsmasher.cc
-tests_atomsmasher_SOURCES+= clients/generator.cc clients/execute.cc
+tests_atomsmasher_SOURCES= \
+                          tests/atomsmasher.cc \
+                          clients/generator.cc \
+                          clients/execute.cc
 tests_atomsmasher_DEPENDENCIES= $(TESTS_LDADDS)
-
 tests_atomsmasher_LDADD= $(tests_atomsmasher_DEPENDENCIES) $(LIBSASL)
 
 tests_testudp_CFLAGS= $(AM_CFLAGS) $(NO_CONVERSION) $(NO_STRICT_ALIASING)
 tests_testudp_SOURCES= tests/mem_udp.cc
 tests_testudp_DEPENDENCIES= $(TESTS_LDADDS)
-
 tests_testudp_LDADD= $(tests_testudp_DEPENDENCIES) $(LIBSASL)
-
-tests_startservers_SOURCES= tests/start.cc
-tests_startservers_DEPENDENCIES= $(TESTS_LDADDS)
-tests_startservers_LDADD= $(tests_startservers_DEPENDENCIES) $(LIBSASL)
+check_PROGRAMS+= tests/testudp
 
 tests_testhashkit_SOURCES = tests/hashkit_functions.cc
 tests_testhashkit_DEPENDENCIES = libtest/libtest.la libhashkit/libhashkit.la
 tests_testhashkit_LDADD = $(tests_testhashkit_DEPENDENCIES)
+check_PROGRAMS+= tests/testhashkit
 
 tests_hash_plus_SOURCES= tests/hash_plus.cc
 tests_hash_plus_CXXFLAGS= $(AM_CXXFLAGS) $(NO_EFF_CXX)
@@ -112,10 +119,10 @@ check_PROGRAMS+= tests/hash_plus
 
 test: check
 
-check-local: tests/var $(TEST_DOCS) test-mem test-hash memcapable
+check-local: tests/var $(TEST_DOCS) memcapable
        @echo "Tests completed"
 
-test-x: check-local test-plus test-memcat test-memcp test-memrm test-memerror test-memdump test-memflush test-memstat
+test-x: tests/var test-plus test-memcat test-memcp test-memrm test-memerror test-memdump test-memflush test-memstat
        @echo "Tests completed"
 
 memcapable: clients/memcapable
@@ -240,30 +247,35 @@ TESTPLUS_COMMAND= tests/testplus $(COLLECTION) $(SUITE)
 
 HASHPLUS_COMMAND= tests/hashplus $(COLLECTION) $(SUITE)
 
+CYCLE_COMMAND= tests/cycle $(COLLECTION) $(SUITE)
+
 ATOM_COMMAND= tests/atomsmasher $(COLLECTION) $(SUITE)
 
 UDP_COMMAND= tests/testudp $(COLLECTION) $(SUITE)
 
 HASH_COMMAND= tests/testhashkit $(COLLECTION) $(SUITE)
 
-test-mem: tests/testapp
+test-mem: tests/var tests/testapp
        $(MEM_COMMAND)
 
-test-udp: tests/testudp
+test-udp: tests/var tests/testudp
        $(UDP_COMMAND)
 
-test-atom: tests/atomsmasher
+test-atom: tests/var tests/atomsmasher
        $(ATOM_COMMAND)
 
-test-plus: tests/testplus
+test-plus: tests/var tests/testplus
        $(TESTPLUS_COMMAND)
 
-test-hash: tests/testhashkit
+test-hash: tests/var tests/testhashkit
        $(HASH_COMMAND)
 
-test-hashplus: tests/hashplus
+test-hashplus: tests/var tests/hashplus
        $(HASHPLUS_COMMAND)
 
+test-cycle: tests/var tests/cycle
+       $(CYCLE_COMMAND)
+
 pahole-mem: tests/testapp
        $(PAHOLE_COMMAND)  $(MEM_COMMAND)
 
@@ -285,9 +297,15 @@ gdb-hash: tests/testhashkit
 gdb-hashplus: tests/hashplus
        $(DEBUG_COMMAND) $(HASHPLUS_COMMAND)
 
+gdb-cycle: tests/cycle
+       $(DEBUG_COMMAND) $(CYCLE_COMMAND)
+
 gdb-memslap: clients/memslap
        $(DEBUG_COMMAND)  $(MEMSLAP_COMMAND)
 
+valgrind-cycle: tests/cycle
+       $(VALGRIND_COMMAND)  $(CYCLE_COMMAND)
+
 valgrind-mem: tests/testapp
        $(VALGRIND_COMMAND)  $(MEM_COMMAND)
 
index fc0b6ae8a8dad12ec3d830a16f8e942d16d04735..dfdddbefe00796336603fa2af813c8c9ef42eef8 100644 (file)
@@ -9,9 +9,9 @@
  *
  */
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#pragma once
+
+#include <cassert>
 
 /* The structure we use for the test system */
 struct libmemcached_test_container_st
@@ -23,11 +23,13 @@ struct libmemcached_test_container_st
   libmemcached_test_container_st() :
     parent(NULL),
     memc(NULL)
-  {
-    memset(&construct, 0, sizeof(server_startup_st));
-  }
+  { }
 };
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Prototypes for functions we will pass to test framework */
 libmemcached_test_container_st *world_create(test_return_t *error);
 test_return_t world_test_startup(libmemcached_test_container_st *);
@@ -38,8 +40,6 @@ test_return_t world_post_run(libmemcached_test_container_st *);
 test_return_t world_on_error(test_return_t, libmemcached_test_container_st *);
 test_return_t world_destroy(libmemcached_test_container_st *);
 
-static libmemcached_test_container_st global_container;
-
 /**
   @note generic shutdown/startup for libmemcached tests.
 */
@@ -48,29 +48,30 @@ test_return_t world_container_shutdown(libmemcached_test_container_st *container
 
 libmemcached_test_container_st *world_create(test_return_t *error)
 {
-  global_container.construct.count= SERVERS_TO_CREATE;
-  global_container.construct.udp= 0;
-  server_startup(&global_container.construct);
-
-  if (not global_container.construct.servers)
+  libmemcached_test_container_st *global_container= new libmemcached_test_container_st();
+  if (not server_startup(&global_container->construct))
   {
     *error= TEST_FAILURE;
-    server_shutdown(&global_container.construct);
     return NULL;
   }
 
   *error= TEST_SUCCESS;
 
-  return &global_container;
+  return global_container;
 }
 
 test_return_t world_container_startup(libmemcached_test_container_st *container)
 {
-  container->parent= memcached_create(NULL);
-  test_true((container->parent != NULL));
+  char buffer[BUFSIZ];
 
-  test_compare(MEMCACHED_SUCCESS,
-              memcached_server_push(container->parent, container->construct.servers));
+  test_compare_got(MEMCACHED_SUCCESS,
+                   libmemcached_check_configuration(container->construct.server_list.c_str(), container->construct.server_list.size(),
+                                                    buffer, sizeof(buffer)),
+                   buffer);
+
+  assert(not container->parent);
+  container->parent= memcached(container->construct.server_list.c_str(), container->construct.server_list.size());
+  test_true(container->parent);
 
   return TEST_SUCCESS;
 }
@@ -85,14 +86,18 @@ test_return_t world_container_shutdown(libmemcached_test_container_st *container
 
 test_return_t world_test_startup(libmemcached_test_container_st *container)
 {
+  assert(container);
+  assert(not container->memc);
+  assert(container->parent);
   container->memc= memcached_clone(NULL, container->parent);
-  test_true((container->memc != NULL));
+  test_true(container->memc);
 
   return TEST_SUCCESS;
 }
 
 test_return_t world_flush(libmemcached_test_container_st *container)
 {
+  assert(container->memc);
   memcached_flush(container->memc, 0);
   memcached_quit(container->memc);
 
@@ -101,6 +106,7 @@ test_return_t world_flush(libmemcached_test_container_st *container)
 
 test_return_t world_pre_run(libmemcached_test_container_st *container)
 {
+  assert(container->memc);
   for (uint32_t loop= 0; loop < memcached_server_list_count(container->memc->servers); loop++)
   {
     memcached_server_instance_st instance=
@@ -124,6 +130,7 @@ test_return_t world_post_run(libmemcached_test_container_st *container)
 test_return_t world_on_error(test_return_t test_state, libmemcached_test_container_st *container)
 {
   (void)test_state;
+  assert(container->memc);
   memcached_free(container->memc);
   container->memc= NULL;
 
@@ -133,8 +140,6 @@ test_return_t world_on_error(test_return_t test_state, libmemcached_test_contain
 test_return_t world_destroy(libmemcached_test_container_st *container)
 {
   server_startup_st *construct= &container->construct;
-  memcached_server_st *servers= container->construct.servers;
-  memcached_server_list_free(servers);
 
   server_shutdown(construct);
 
@@ -142,6 +147,8 @@ test_return_t world_destroy(libmemcached_test_container_st *container)
   sasl_done();
 #endif
 
+  delete container;
+
   return TEST_SUCCESS;
 }
 
@@ -150,6 +157,8 @@ static test_return_t _runner_default(libmemcached_test_callback_fn func, libmemc
 {
   if (func)
   {
+    assert(container);
+    assert(container->memc);
     return func(container->memc);
   }
   else
index c1bb70fec58505773a7b3360e9cc9cce5f414cb7..f70dbba432db281a3b457c3326f72b584fc7e8be 100644 (file)
@@ -35,6 +35,7 @@
  *
  */
 
+#include <libtest/common.h>
 
 /*
   Test cases
@@ -44,8 +45,6 @@
 // !NEVER use common.h, always use memcached.h in your own apps
 #include <libmemcached/common.h>
 
-#include <stdint.h>
-
 #include <cassert>
 #include <memory>
 #include <signal.h>
@@ -67,6 +66,7 @@
 #include "tests/deprecated.h"
 #include "tests/parser.h"
 #include "tests/pool.h"
+#include "tests/namespace.h"
 #include "tests/string.h"
 #include "tests/replication.h"
 #include "tests/basic.h"
@@ -330,7 +330,7 @@ static test_return_t clone_test(memcached_st *memc)
       test_true(memc_clone->flags.verify_key == memc->flags.verify_key);
       test_true(memc_clone->ketama.weighted == memc->ketama.weighted);
       test_true(memc_clone->flags.binary_protocol == memc->flags.binary_protocol);
-      test_true(memc_clone->flags.hash_with_prefix_key == memc->flags.hash_with_prefix_key);
+      test_true(memc_clone->flags.hash_with_namespace == memc->flags.hash_with_namespace);
       test_true(memc_clone->flags.no_reply == memc->flags.no_reply);
       test_true(memc_clone->flags.use_udp == memc->flags.use_udp);
       test_true(memc_clone->flags.auto_eject_hosts == memc->flags.auto_eject_hosts);
@@ -880,7 +880,7 @@ static test_return_t bad_key_test(memcached_st *memc)
        binary protocol
     */
     test_compare(MEMCACHED_SUCCESS, 
-                 memcached_callback_set(memc_clone, MEMCACHED_CALLBACK_PREFIX_KEY, NULL));
+                 memcached_callback_set(memc_clone, MEMCACHED_CALLBACK_NAMESPACE, NULL));
 
     char *longkey= (char *)malloc(max_keylen + 1);
     if (longkey)
@@ -1136,30 +1136,28 @@ static test_return_t get_test3(memcached_st *memc)
 
 static test_return_t get_test4(memcached_st *memc)
 {
-  memcached_return_t rc;
   const char *key= "foo";
-  char *value;
   size_t value_length= 8191;
-  char *string;
-  size_t string_length;
-  uint32_t flags;
-  uint32_t x;
 
-  value = (char*)malloc(value_length);
+  char *value= (char*)malloc(value_length);
   test_true(value);
 
-  for (x= 0; x < value_length; x++)
+  for (uint32_t x= 0; x < value_length; x++)
+  {
     value[x] = (char) (x % 127);
+  }
 
-  rc= memcached_set(memc, key, strlen(key),
-                    value, value_length,
-                    (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+  memcached_return_t rc= memcached_set(memc, key, strlen(key),
+                                       value, value_length,
+                                       (time_t)0, (uint32_t)0);
+  test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
 
-  for (x= 0; x < 10; x++)
+  for (uint32_t x= 0; x < 10; x++)
   {
-    string= memcached_get(memc, key, strlen(key),
-                          &string_length, &flags, &rc);
+    uint32_t flags;
+    size_t string_length;
+    char *string= memcached_get(memc, key, strlen(key),
+                                &string_length, &flags, &rc);
 
     test_compare(MEMCACHED_SUCCESS, rc);
     test_true(string);
@@ -1253,7 +1251,10 @@ static test_return_t mget_end(memcached_st *memc)
     test_compare(MEMCACHED_SUCCESS, rc);
     int val = 0;
     if (key_length == 4)
+    {
       val= 1;
+    }
+
     test_compare(string_length, strlen(values[val]));
     test_true(strncmp(values[val], string, string_length) == 0);
     free(string);
@@ -1304,47 +1305,53 @@ static test_return_t stats_servername_test(memcached_st *memc)
 static test_return_t increment_test(memcached_st *memc)
 {
   uint64_t new_number;
-  memcached_return_t rc;
-  const char *key= "number";
-  const char *value= "0";
 
-  rc= memcached_set(memc, key, strlen(key),
-                    value, strlen(value),
-                    (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_set(memc, 
+                             test_literal_param("number"),
+                             test_literal_param("0"),
+                             (time_t)0, (uint32_t)0));
 
-  rc= memcached_increment(memc, key, strlen(key),
-                          1, &new_number);
-  test_compare(MEMCACHED_SUCCESS, rc);
-  test_true(new_number == 1);
+  memcached_return_t rc;
+  test_compare_got(MEMCACHED_SUCCESS, 
+                   rc= memcached_increment(memc,
+                                           test_literal_param("number"),
+                                           1, &new_number),
+                   memcached_strerror(NULL, rc));
+  test_compare(1, new_number);
 
-  rc= memcached_increment(memc, key, strlen(key),
-                          1, &new_number);
-  test_compare(MEMCACHED_SUCCESS, rc);
-  test_true(new_number == 2);
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_increment(memc,
+                                   test_literal_param("number"),
+                                   1, &new_number));
+  test_compare(2, new_number);
 
   return TEST_SUCCESS;
 }
 
 static test_return_t increment_with_initial_test(memcached_st *memc)
 {
-  if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) != 0)
-  {
-    uint64_t new_number;
-    memcached_return_t rc;
-    const char *key= "number";
-    uint64_t initial= 0;
+  test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
 
-    rc= memcached_increment_with_initial(memc, key, strlen(key),
-                                         1, initial, 0, &new_number);
-    test_compare(MEMCACHED_SUCCESS, rc);
-    test_true(new_number == initial);
+  uint64_t new_number;
+  uint64_t initial= 0;
+
+  test_compare(MEMCACHED_SUCCESS, memcached_flush_buffers(memc));
+
+  memcached_return_t rc;
+  test_compare_got(MEMCACHED_SUCCESS, 
+                   rc= memcached_increment_with_initial(memc,
+                                                        test_literal_param("number"),
+                                                        1, initial, 0, &new_number),
+                   memcached_strerror(NULL, rc));
+  test_compare(new_number, initial);
+
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_increment_with_initial(memc,
+                                                test_literal_param("number"),
+                                                1, initial, 0, &new_number));
+  test_compare(new_number, (initial + 1));
 
-    rc= memcached_increment_with_initial(memc, key, strlen(key),
-                                         1, initial, 0, &new_number);
-    test_compare(MEMCACHED_SUCCESS, rc);
-    test_true(new_number == (initial + 1));
-  }
   return TEST_SUCCESS;
 }
 
@@ -1352,46 +1359,50 @@ static test_return_t decrement_test(memcached_st *memc)
 {
   uint64_t new_number;
   memcached_return_t rc;
-  const char *key= "number";
   const char *value= "3";
 
-  rc= memcached_set(memc, key, strlen(key),
+  rc= memcached_set(memc,
+                    test_literal_param("number"),
                     value, strlen(value),
                     (time_t)0, (uint32_t)0);
   test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
 
-  rc= memcached_decrement(memc, key, strlen(key),
-                          1, &new_number);
-  test_compare(MEMCACHED_SUCCESS, rc);
-  test_true(new_number == 2);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_decrement(memc,
+                                   test_literal_param("number"),
+                                   1, &new_number));
+  test_compare(new_number, 2);
 
-  rc= memcached_decrement(memc, key, strlen(key),
-                          1, &new_number);
-  test_compare(MEMCACHED_SUCCESS, rc);
-  test_true(new_number == 1);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_decrement(memc,
+                                   test_literal_param("number"),
+                                   1, &new_number));
+  test_compare(new_number, 1);
 
   return TEST_SUCCESS;
 }
 
 static test_return_t decrement_with_initial_test(memcached_st *memc)
 {
-  if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) != 0)
-  {
-    uint64_t new_number;
-    memcached_return_t rc;
-    const char *key= "number";
-    uint64_t initial= 3;
+  test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
 
-    rc= memcached_decrement_with_initial(memc, key, strlen(key),
-                                         1, initial, 0, &new_number);
-    test_compare(MEMCACHED_SUCCESS, rc);
-    test_true(new_number == initial);
+  uint64_t new_number;
+  uint64_t initial= 3;
+
+  test_compare(MEMCACHED_SUCCESS, memcached_flush_buffers(memc));
+
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_decrement_with_initial(memc,
+                                                test_literal_param("number"),
+                                                1, initial, 0, &new_number));
+  test_compare(new_number, initial);
+
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_decrement_with_initial(memc,
+                                                test_literal_param("number"),
+                                                1, initial, 0, &new_number));
+  test_compare(new_number, (initial - 1));
 
-    rc= memcached_decrement_with_initial(memc, key, strlen(key),
-                                         1, initial, 0, &new_number);
-    test_compare(MEMCACHED_SUCCESS, rc);
-    test_true(new_number == (initial - 1));
-  }
   return TEST_SUCCESS;
 }
 
@@ -1407,43 +1418,43 @@ static test_return_t increment_by_key_test(memcached_st *memc)
                            key, strlen(key),
                            value, strlen(value),
                            (time_t)0, (uint32_t)0);
-  test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
+  test_true(rc == MEMCACHED_SUCCESS or rc == MEMCACHED_BUFFERED);
 
-  rc= memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key),
-                                 1, &new_number);
-  test_compare(MEMCACHED_SUCCESS, rc);
-  test_true(new_number == 1);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key),
+                                          1, &new_number));
+  test_compare(new_number, 1);
 
-  rc= memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key),
-                                 1, &new_number);
-  test_compare(MEMCACHED_SUCCESS, rc);
-  test_true(new_number == 2);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_increment_by_key(memc, master_key, strlen(master_key), key, strlen(key),
+                                          1, &new_number));
+  test_compare(new_number, 2);
 
   return TEST_SUCCESS;
 }
 
 static test_return_t increment_with_initial_by_key_test(memcached_st *memc)
 {
-  if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) != 0)
-  {
-    uint64_t new_number;
-    memcached_return_t rc;
-    const char *master_key= "foo";
-    const char *key= "number";
-    uint64_t initial= 0;
+  test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
 
-    rc= memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key),
-                                                key, strlen(key),
-                                                1, initial, 0, &new_number);
-    test_compare(MEMCACHED_SUCCESS, rc);
-    test_true(new_number == initial);
+  uint64_t new_number;
+  memcached_return_t rc;
+  const char *master_key= "foo";
+  const char *key= "number";
+  uint64_t initial= 0;
+
+  rc= memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key),
+                                              key, strlen(key),
+                                              1, initial, 0, &new_number);
+  test_compare(MEMCACHED_SUCCESS, rc);
+  test_true(new_number == initial);
+
+  rc= memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key),
+                                              key, strlen(key),
+                                              1, initial, 0, &new_number);
+  test_compare(MEMCACHED_SUCCESS, rc);
+  test_true(new_number == (initial + 1));
 
-    rc= memcached_increment_with_initial_by_key(memc, master_key, strlen(master_key),
-                                                key, strlen(key),
-                                                1, initial, 0, &new_number);
-    test_compare(MEMCACHED_SUCCESS, rc);
-    test_true(new_number == (initial + 1));
-  }
   return TEST_SUCCESS;
 }
 
@@ -1451,52 +1462,53 @@ static test_return_t decrement_by_key_test(memcached_st *memc)
 {
   uint64_t new_number;
   memcached_return_t rc;
-  const char *master_key= "foo";
-  const char *key= "number";
   const char *value= "3";
 
-  rc= memcached_set_by_key(memc, master_key, strlen(master_key),
-                           key, strlen(key),
+  rc= memcached_set_by_key(memc,
+                           test_literal_param("foo"),
+                           test_literal_param("number"),
                            value, strlen(value),
                            (time_t)0, (uint32_t)0);
   test_true(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
 
-  rc= memcached_decrement_by_key(memc, master_key, strlen(master_key),
-                                 key, strlen(key),
-                                 1, &new_number);
-  test_compare(MEMCACHED_SUCCESS, rc);
-  test_true(new_number == 2);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_decrement_by_key(memc,
+                                          test_literal_param("foo"),
+                                          test_literal_param("number"),
+                                          1, &new_number));
+  test_compare(new_number, 2);
 
-  rc= memcached_decrement_by_key(memc, master_key, strlen(master_key),
-                                 key, strlen(key),
-                                 1, &new_number);
-  test_compare(MEMCACHED_SUCCESS, rc);
-  test_true(new_number == 1);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_decrement_by_key(memc,
+                                          test_literal_param("foo"),
+                                          test_literal_param("number"),
+                                          1, &new_number));
+  test_compare(new_number, 1);
 
   return TEST_SUCCESS;
 }
 
 static test_return_t decrement_with_initial_by_key_test(memcached_st *memc)
 {
-  if (memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) != 0)
-  {
-    uint64_t new_number;
-    const char *master_key= "foo";
-    const char *key= "number";
-    uint64_t initial= 3;
+  test_skip(true, memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL));
 
-    test_compare(MEMCACHED_SUCCESS,
-                 memcached_decrement_with_initial_by_key(memc, master_key, strlen(master_key),
-                                                         key, strlen(key),
-                                                         1, initial, 0, &new_number));
-    test_compare(new_number, initial);
+  uint64_t new_number;
+  uint64_t initial= 3;
+
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_decrement_with_initial_by_key(memc,
+                                                       test_literal_param("foo"),
+                                                       test_literal_param("number"),
+                                                       1, initial, 0, &new_number));
+  test_compare(new_number, initial);
+
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_decrement_with_initial_by_key(memc,
+                                                       test_literal_param("foo"),
+                                                       test_literal_param("number"),
+                                                       1, initial, 0, &new_number));
+  test_compare(new_number, (initial - 1));
 
-    test_compare(MEMCACHED_SUCCESS,
-                 memcached_decrement_with_initial_by_key(memc, master_key, strlen(master_key),
-                                                         key, strlen(key),
-                                                         1, initial, 0, &new_number));
-    test_compare(new_number, (initial - 1));
-  }
   return TEST_SUCCESS;
 }
 
@@ -1565,10 +1577,10 @@ static test_return_t mget_result_test(memcached_st *memc)
     test_true(results);
     test_true(&results_obj == results);
     test_compare(MEMCACHED_SUCCESS, rc);
-    test_compare(memcached_result_key_length(results), memcached_result_length(results));
     test_memcmp(memcached_result_key_value(results),
                 memcached_result_value(results),
                 memcached_result_length(results));
+    test_compare(memcached_result_key_length(results), memcached_result_length(results));
   }
 
   memcached_result_free(&results_obj);
@@ -1614,7 +1626,7 @@ static test_return_t mget_result_alloc_test(memcached_st *memc)
   {
     test_true(results);
     test_compare(MEMCACHED_SUCCESS, rc);
-    test_true(memcached_result_key_length(results) == memcached_result_length(results));
+    test_compare(memcached_result_key_length(results), memcached_result_length(results));
     test_memcmp(memcached_result_key_value(results),
                 memcached_result_value(results),
                 memcached_result_length(results));
@@ -1713,8 +1725,11 @@ static test_return_t mget_test(memcached_st *memc)
   {
     test_true(return_value);
     test_compare(MEMCACHED_SUCCESS, rc);
-    test_true(return_key_length == return_value_length);
-    test_memcmp(return_value, return_key, return_value_length);
+    if (not memc->_namespace)
+    {
+      test_compare(return_key_length, return_value_length);
+      test_memcmp(return_value, return_key, return_value_length);
+    }
     free(return_value);
     x++;
   }
@@ -2895,19 +2910,14 @@ static test_return_t user_supplied_bug17(memcached_st *memc)
   From Andrei on IRC
 */
 
-static test_return_t user_supplied_bug19(memcached_st *not_used)
+static test_return_t user_supplied_bug19(memcached_st *)
 {
-  memcached_st *memc;
-  const memcached_server_st *server;
   memcached_return_t res;
 
-  (void)not_used;
+  memcached_st *memc= memcached(test_literal_param("--server=localhost:11311/?100 --server=localhost:11312/?100"));
 
-  memc= memcached_create(NULL);
-  memcached_server_add_with_weight(memc, "localhost", 11311, 100);
-  memcached_server_add_with_weight(memc, "localhost", 11312, 100);
-
-  server= memcached_server_by_key(memc, "a", 1, &res);
+  const memcached_server_st *server= memcached_server_by_key(memc, "a", 1, &res);
+  test_true(server);
 
   memcached_free(memc);
 
@@ -3901,38 +3911,38 @@ static void *my_calloc(const memcached_st *ptr, size_t nelem, const size_t size,
 #endif
 }
 
-static test_return_t set_prefix(memcached_st *memc)
+static test_return_t selection_of_namespace_tests(memcached_st *memc)
 {
   memcached_return_t rc;
   const char *key= "mine";
   char *value;
 
   /* Make sure be default none exists */
-  value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc);
+  value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc);
   test_compare_got(MEMCACHED_FAILURE, rc, memcached_strerror(NULL, rc));
 
   /* Test a clean set */
-  rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, (void *)key);
-  test_compare_got(MEMCACHED_SUCCESS, rc , memcached_last_error_message(memc));
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, (void *)key));
 
-  value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc);
+  value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc);
   test_true(value);
   test_memcmp(value, key, 4);
   test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
 
   /* Test that we can turn it off */
-  rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, NULL);
-  test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, NULL));
 
-  value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc);
+  value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc);
   test_false(value);
   test_compare_got(MEMCACHED_FAILURE, rc, memcached_strerror(NULL, rc));
 
   /* Now setup for main test */
-  rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, (void *)key);
-  test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, (void *)key));
 
-  value= (char *)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc);
+  value= (char *)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc);
   test_true(value);
   test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
   test_memcmp(value, key, 4);
@@ -3942,10 +3952,10 @@ static test_return_t set_prefix(memcached_st *memc)
     char long_key[255];
     memset(long_key, 0, 255);
 
-    rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, NULL);
-    test_compare(MEMCACHED_SUCCESS, rc);
+    test_compare(MEMCACHED_SUCCESS,
+                 memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, NULL));
 
-    value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_PREFIX_KEY, &rc);
+    value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc);
     test_false(value);
     test_true(rc == MEMCACHED_FAILURE);
     test_true(value == NULL);
@@ -3953,27 +3963,55 @@ static test_return_t set_prefix(memcached_st *memc)
     /* Test a long key for failure */
     /* TODO, extend test to determine based on setting, what result should be */
     strncpy(long_key, "Thisismorethentheallottednumberofcharacters", sizeof(long_key));
-    rc= memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, long_key);
-    //test_compare(MEMCACHED_BAD_KEY_PROVIDED, rc);
-    test_compare(MEMCACHED_SUCCESS, rc);
+    test_compare(MEMCACHED_SUCCESS, 
+                 memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, long_key));
 
     /* Now test a key with spaces (which will fail from long key, since bad key is not set) */
     strncpy(long_key, "This is more then the allotted number of characters", sizeof(long_key));
-    test_compare(MEMCACHED_BAD_KEY_PROVIDED,
-                 memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, long_key));
+    test_compare(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? MEMCACHED_SUCCESS : MEMCACHED_BAD_KEY_PROVIDED,
+                 memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, long_key));
 
     /* Test for a bad prefix, but with a short key */
-    test_compare(MEMCACHED_SUCCESS,
-                 memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_VERIFY_KEY, 1));
+    test_compare_got(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? MEMCACHED_INVALID_ARGUMENTS : MEMCACHED_SUCCESS,
+                     rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_VERIFY_KEY, 1),
+                     memcached_strerror(NULL, rc));
 
-    strncpy(long_key, "dog cat", sizeof(long_key));
-    test_compare(MEMCACHED_BAD_KEY_PROVIDED,
-                 memcached_callback_set(memc, MEMCACHED_CALLBACK_PREFIX_KEY, long_key));
+    test_compare(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) ? MEMCACHED_SUCCESS : MEMCACHED_BAD_KEY_PROVIDED,
+                 memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, "dog cat"));
   }
 
   return TEST_SUCCESS;
 }
 
+static test_return_t set_namespace(memcached_st *memc)
+{
+  memcached_return_t rc;
+  const char *key= "mine";
+  char *value;
+
+  /* Make sure be default none exists */
+  value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc);
+  test_compare_got(MEMCACHED_FAILURE, rc, memcached_strerror(NULL, rc));
+
+  /* Test a clean set */
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_callback_set(memc, MEMCACHED_CALLBACK_NAMESPACE, (void *)key));
+
+  value= (char*)memcached_callback_get(memc, MEMCACHED_CALLBACK_NAMESPACE, &rc);
+  test_true(value);
+  test_memcmp(value, key, 4);
+  test_compare_got(MEMCACHED_SUCCESS, rc, memcached_strerror(NULL, rc));
+
+  return TEST_SUCCESS;
+}
+
+static test_return_t set_namespace_and_binary(memcached_st *memc)
+{
+  test_return_if(pre_binary(memc));
+  test_return_if(set_namespace(memc));
+
+  return TEST_SUCCESS;
+}
 
 #ifdef MEMCACHED_ENABLE_DEPRECATED
 static test_return_t deprecated_set_memory_alloc(memcached_st *memc)
@@ -4112,7 +4150,7 @@ static test_return_t check_for_1_2_3(memcached_st *memc)
     memcached_server_instance_by_position(memc, 0);
 
   if ((instance->major_version >= 1 && (instance->minor_version == 2 && instance->micro_version >= 4))
-      || instance->minor_version > 2)
+      or instance->minor_version > 2)
   {
     return TEST_SUCCESS;
   }
@@ -4122,17 +4160,17 @@ static test_return_t check_for_1_2_3(memcached_st *memc)
 
 static test_return_t pre_unix_socket(memcached_st *memc)
 {
-  memcached_return_t rc;
   struct stat buf;
 
   memcached_servers_reset(memc);
+  const char *socket_file= default_socket();
 
-  if (stat("/tmp/memcached.socket", &buf))
-    return TEST_SKIPPED;
+  test_skip(0, stat(socket_file, &buf));
 
-  rc= memcached_server_add_unix_socket_with_weight(memc, "/tmp/memcached.socket", 0);
+  test_compare(MEMCACHED_SUCCESS,
+               memcached_server_add_unix_socket_with_weight(memc, socket_file, 0));
 
-  return ( rc == MEMCACHED_SUCCESS ? TEST_SUCCESS : TEST_FAILURE );
+  return TEST_SUCCESS;
 }
 
 static test_return_t pre_nodelay(memcached_st *memc)
@@ -4832,26 +4870,18 @@ static test_return_t memcached_get_hashkit_test (memcached_st *memc)
   We are testing the error condition when we connect to a server via memcached_get()
   but find that the server is not available.
 */
-static test_return_t memcached_get_MEMCACHED_ERRNO(memcached_st *memc)
+static test_return_t memcached_get_MEMCACHED_ERRNO(memcached_st *)
 {
-  (void)memc;
-  memcached_st *tl_memc_h;
-
   const char *key= "MemcachedLives";
   size_t len;
   uint32_t flags;
   memcached_return rc;
-  char *value;
 
   // Create a handle.
-  tl_memc_h= memcached_create(NULL);
-  memcached_server_st *servers= memcached_servers_parse("localhost:9898,localhost:9899"); // This server should not exist
-  test_true(servers);
-  memcached_server_push(tl_memc_h, servers);
-  memcached_server_list_free(servers);
+  memcached_st *tl_memc_h= memcached(test_literal_param("--server=localhost:9898 --server=localhost:9899")); // This server should not exist
 
   // See if memcached is reachable.
-  value= memcached_get(tl_memc_h, key, strlen(key), &len, &flags, &rc);
+  char *value= memcached_get(tl_memc_h, key, strlen(key), &len, &flags, &rc);
 
   test_false(value);
   test_compare(0, len);
@@ -5526,6 +5556,9 @@ static test_return_t test_verbosity(memcached_st *memc)
 
 static test_return_t test_server_failure(memcached_st *memc)
 {
+  if (memcached_server_count(memc) < 2)
+    return TEST_SKIPPED;
+
   memcached_server_instance_st instance= memcached_server_instance_by_position(memc, 0);
 
   memcached_st *local_memc= memcached_create(NULL);
@@ -5561,7 +5594,12 @@ static test_return_t test_server_failure(memcached_st *memc)
 
 static test_return_t test_cull_servers(memcached_st *memc)
 {
-  uint32_t count = memcached_server_count(memc);
+  uint32_t count= memcached_server_count(memc);
+
+  if (count < 2)
+  {
+    return TEST_SKIPPED;
+  }
 
   // Do not do this in your code, it is not supported.
   memc->servers[1].options.is_dead= true;
@@ -6422,11 +6460,12 @@ test_st parser_tests[] ={
   {"libmemcached_check_configuration_with_filename", 0, (test_callback_fn*)libmemcached_check_configuration_with_filename_test },
   {"number_options", 0, (test_callback_fn*)parser_number_options_test },
   {"randomly generated options", 0, (test_callback_fn*)random_statement_build_test },
-  {"prefix_key", 0, (test_callback_fn*)parser_key_prefix_test },
+  {"namespace", 0, (test_callback_fn*)parser_key_prefix_test },
   {"server", 0, (test_callback_fn*)server_test },
   {"bad server strings", 0, (test_callback_fn*)servers_bad_test },
   {"server with weights", 0, (test_callback_fn*)server_with_weight_test },
   {"parsing servername, port, and weight", 0, (test_callback_fn*)test_hostname_port_weight },
+  {"--socket=", 0, (test_callback_fn*)test_parse_socket },
   {0, 0, (test_callback_fn*)0}
 };
 
@@ -6435,6 +6474,12 @@ test_st virtual_bucket_tests[] ={
   {0, 0, (test_callback_fn*)0}
 };
 
+test_st namespace_tests[] ={
+  {"basic tests", true, (test_callback_fn*)selection_of_namespace_tests },
+  {"increment", true, (test_callback_fn*)memcached_increment_namespace },
+  {0, 0, (test_callback_fn*)0}
+};
+
 collection_st collection[] ={
 #if 0
   {"hash_sanity", 0, 0, hash_sanity},
@@ -6467,14 +6512,17 @@ collection_st collection[] ={
   {"deprecated_memory_allocators", (test_callback_fn*)deprecated_set_memory_alloc, 0, tests},
 #endif
   {"memory_allocators", (test_callback_fn*)set_memory_alloc, 0, tests},
-  {"prefix", (test_callback_fn*)set_prefix, 0, tests},
+  {"namespace", (test_callback_fn*)set_namespace, 0, tests},
+  {"namespace(BINARY)", (test_callback_fn*)set_namespace_and_binary, 0, tests},
+  {"specific namespace", 0, 0, namespace_tests},
+  {"specific namespace(BINARY)", (test_callback_fn*)pre_binary, 0, namespace_tests},
   {"sasl_auth", (test_callback_fn*)pre_sasl, 0, sasl_auth_tests },
   {"sasl", (test_callback_fn*)pre_sasl, 0, tests },
   {"version_1_2_3", (test_callback_fn*)check_for_1_2_3, 0, version_1_2_3},
   {"string", 0, 0, string_tests},
   {"result", 0, 0, result_tests},
   {"async", (test_callback_fn*)pre_nonblock, 0, async_tests},
-  {"async_binary", (test_callback_fn*)pre_nonblock_binary, 0, async_tests},
+  {"async(BINARY)", (test_callback_fn*)pre_nonblock_binary, 0, async_tests},
   {"Cal Haldenbrand's tests", 0, 0, haldenbrand_tests},
   {"user", 0, 0, user_tests},
   {"generate", 0, 0, generate_tests},
index 8153e8ef074f3c167adcf1ce9497fcfc3cdebc10..2a82482f9feaca230428cf84b52c2d01a9c4ae5a 100644 (file)
@@ -10,9 +10,9 @@
   Sample test application.
 */
 
-#include "config.h"
+#include <libtest/common.h>
 
-#include "libmemcached/common.h"
+#include <libmemcached/common.h>
 
 #include <assert.h>
 #include <stdio.h>
@@ -27,7 +27,6 @@
 #include <time.h>
 
 #include <libtest/server.h>
-#include <libtest/test.hpp>
 
 #define SERVERS_TO_CREATE 5
 
diff --git a/tests/namespace.cc b/tests/namespace.cc
new file mode 100644 (file)
index 0000000..54cc130
--- /dev/null
@@ -0,0 +1,104 @@
+/*  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.
+ *
+ */
+
+#include <libtest/common.h>
+#include <libmemcached/memcached.h>
+#include <tests/namespace.h>
+
+test_return_t memcached_increment_namespace(memcached_st *memc)
+{
+  uint64_t new_number;
+
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_set(memc, 
+                             test_literal_param("number"),
+                             test_literal_param("0"),
+                             (time_t)0, (uint32_t)0));
+
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_increment(memc,
+                                   test_literal_param("number"),
+                                   1, &new_number));
+  test_compare(1, new_number);
+
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_increment(memc,
+                                   test_literal_param("number"),
+                                   1, &new_number));
+  test_compare(2, new_number);
+
+  memcached_st *clone= memcached_clone(NULL, memc);
+
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_callback_set(clone, MEMCACHED_CALLBACK_NAMESPACE, "all_your_bases"));
+
+  test_compare(MEMCACHED_NOTFOUND, 
+               memcached_increment(clone,
+                                   test_literal_param("number"),
+                                   1, &new_number));
+
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_add(clone, 
+                             test_literal_param("number"),
+                             test_literal_param("10"),
+                             (time_t)0, (uint32_t)0));
+
+  char *value= memcached_get(clone, 
+                             test_literal_param("number"),
+                             0, 0, 0);
+  test_true(value);
+  test_compare(2, strlen(value));
+  test_strcmp("10", value);
+  free(value);
+
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_increment(clone,
+                                   test_literal_param("number"),
+                                   1, &new_number));
+  test_compare(11, new_number);
+
+  test_compare(MEMCACHED_SUCCESS, 
+               memcached_increment(memc,
+                                   test_literal_param("number"),
+                                   1, &new_number));
+  test_compare(3, new_number);
+
+  memcached_free(clone);
+
+  return TEST_SUCCESS;
+}
+
diff --git a/tests/namespace.h b/tests/namespace.h
new file mode 100644 (file)
index 0000000..600da6d
--- /dev/null
@@ -0,0 +1,41 @@
+/*  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
+
+LIBTEST_INTERNAL_API
+test_return_t memcached_increment_namespace(memcached_st *memc);
index ad6020486b331cb54b0c81c9d0a5d6eaf2eb9b25..f1020ff45f6471f15412218bf4e9295687a16b2f 100644 (file)
@@ -35,7 +35,7 @@
  *
  */
 
-#include <config.h>
+#include <libtest/common.h>
 
 #include <vector>
 #include <iostream>
@@ -43,8 +43,6 @@
 #include <cerrno>
 #include <cassert>
 
-#include <libtest/test.hpp>
-
 #define BUILDING_LIBMEMCACHED
 // !NEVER use common.h, always use memcached.h in your own apps
 #include <libmemcached/common.h>
@@ -237,24 +235,20 @@ scanner_variable_t hash_strings[]= {
 };
 
 
-static test_return_t _test_option(scanner_variable_t *scanner, bool test_true= true)
+static test_return_t _test_option(scanner_variable_t *scanner, bool test_true_opt= true)
 {
-  (void)test_true;
-
   for (scanner_variable_t *ptr= scanner; ptr->type != NIL; ptr++)
   {
-    memcached_st *memc;
-    memc= memcached(ptr->option.c_str, ptr->option.size);
-    if (test_true)
+    memcached_st *memc= memcached(ptr->option.c_str, ptr->option.size);
+    if (test_true_opt)
     {
+      char buffer[2048];
       if (not memc)
       {
-        char buffer[2048];
-        memcached_return_t rc= libmemcached_check_configuration(ptr->option.c_str, ptr->option.size, buffer, sizeof(buffer));
-        std::cerr << "About error for " << memcached_strerror(NULL, rc) << " : " << buffer << std::endl;
+        libmemcached_check_configuration(ptr->option.c_str, ptr->option.size, buffer, sizeof(buffer));
       }
 
-      test_true(memc);
+      test_true_got(memc, buffer);
 
       if (ptr->check_func)
       {
@@ -549,6 +543,65 @@ test_return_t test_hostname_port_weight(memcached_st *)
   return TEST_SUCCESS;
 }
 
+struct socket_weight_t {
+  const char *socket;
+  size_t weight;
+};
+
+static memcached_return_t dump_socket_information(const memcached_st *,
+                                                  const memcached_server_st *instance,
+                                                  void *context)
+{
+  socket_weight_t *check= (socket_weight_t *)context;
+
+  if (strcmp(memcached_server_name(instance), check->socket))
+  {
+    std::cerr << std::endl << __FILE__ << ":" << __LINE__ << " " << memcached_server_name(instance) << " != " << check->socket << std::endl;
+    return MEMCACHED_FAILURE;
+  }
+
+  if (instance->weight == check->weight)
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  return MEMCACHED_FAILURE;
+}
+
+test_return_t test_parse_socket(memcached_st *)
+{
+  char buffer[BUFSIZ];
+
+  memcached_server_fn callbacks[]= { dump_socket_information };
+  {
+    test_compare_got(MEMCACHED_SUCCESS,
+                     libmemcached_check_configuration(test_literal_param("--socket=\"/tmp/foo\""), buffer, sizeof(buffer)),
+                     buffer);
+
+    memcached_st *memc= memcached(test_literal_param("--socket=\"/tmp/foo\""));
+    test_true(memc);
+    socket_weight_t check= { "/tmp/foo", 1 };
+    test_compare(MEMCACHED_SUCCESS,
+                 memcached_server_cursor(memc, callbacks, &check, 1));
+    memcached_free(memc);
+  }
+
+  {
+    test_compare_got(MEMCACHED_SUCCESS,
+                     libmemcached_check_configuration(test_literal_param("--socket=\"/tmp/foo\"/?23"), buffer, sizeof(buffer)),
+                     buffer);
+
+    memcached_st *memc= memcached(test_literal_param("--socket=\"/tmp/foo\"/?23"));
+    test_true(memc);
+    socket_weight_t check= { "/tmp/foo", 23 };
+    test_compare(MEMCACHED_SUCCESS,
+                 memcached_server_cursor(memc, callbacks, &check, 1));
+    memcached_free(memc);
+  }
+
+  return TEST_SUCCESS;
+}
+
 /*
   By setting the timeout value to zero, we force poll() to return immediatly.
 */
index dac1a691337332f2eb481a75e0e35961f0a76f21..11b5368fe1ffa0b779e0a1fe438bca2426d22934 100644 (file)
@@ -104,6 +104,9 @@ test_return_t regression_bug_71231153_connect(memcached_st *);
 LIBTEST_INTERNAL_API
 test_return_t regression_bug_71231153_poll(memcached_st *);
 
+LIBTEST_INTERNAL_API
+test_return_t test_parse_socket(memcached_st *);
+
 #ifdef __cplusplus
 }
 #endif
index f67fcf27ab99acd59b008854901b63264acf13aa..460166f544fd9685ab7e1787db772f445ef1cee8 100644 (file)
@@ -114,15 +114,16 @@ test_return_t basic_master_key_test(memcached_st *original)
 
   populate_vector(value, value_set);
 
-  foo.setByKey(master_key_a, key, value, 0, 0);
-  foo.getByKey(master_key_a, key, test_value);
+  test_true(foo.setByKey(master_key_a, key, value, 0, 0));
+  test_true(foo.getByKey(master_key_a, key, test_value));
 
-  test_true((memcmp(&value[0], &test_value[0], value.size()) == 0));
+  test_compare(value.size(), test_value.size());
+  test_memcmp(&value[0], &test_value[0], value.size());
 
   test_value.clear();
 
-  foo.getByKey(master_key_b, key, test_value);
-  test_true((memcmp(&value[0], &test_value[0], value.size()) == 0));
+  test_false(foo.getByKey(master_key_b, key, test_value));
+  test_compare(0, test_value.size());
 
   return TEST_SUCCESS;
 }
@@ -134,7 +135,7 @@ memcached_return_t callback_counter(const memcached_st *,
 {
   unsigned int *counter= static_cast<unsigned int *>(context);
 
-  *counter= *counter + 1;
+  *counter= *counter +1;
 
   return MEMCACHED_SUCCESS;
 }
@@ -175,7 +176,7 @@ test_return_t mget_test(memcached_st *original)
 
   test_true(memc.mget(keys));
   size_t count= 0;
-  while ((mc_rc= memc.fetch(return_key, return_value)) == MEMCACHED_SUCCESS)
+  while (memcached_success(mc_rc= memc.fetch(return_key, return_value)))
   {
     test_compare(return_key.length(), return_value.size());
     test_memcmp(&return_value[0], return_key.c_str(), return_value.size());
index 9e1d94f745d2c5f786b1ce848c97a71db248304f..8f2a1587a69fc1dce1fffb90cd79f8acc704d877 100644 (file)
@@ -35,9 +35,7 @@
  *
  */
 
-#include <config.h>
-
-#include <libtest/test.hpp>
+#include <libtest/common.h>
 
 #include <vector>
 #include <iostream>
index b3c8d066dc3648645296c6afedf955a10eba7510..f4e597f3898b09aeb1a131c72b6401d5fb09ee59 100644 (file)
  *
  */
 
-#include <config.h>
+#include <libtest/common.h>
 
 #include <iostream>
 
 #include <libmemcached/memcached.h>
-#include <libtest/test.hpp>
 
 #include "tests/print.h"
 
index 3e4476c5e026bc2d7218a197747fae3a1ad8f0ca..330f7bf753c2fb4049ad0b4f87d70714bec5c4a8 100644 (file)
  *
  */
 
-#include <config.h>
+#include <libtest/common.h>
 
-#include <libtest/test.hpp>
-#include "libmemcached/common.h"
+#include <libmemcached/common.h>
 #include <tests/replication.h>
 
 test_return_t replication_set_test(memcached_st *memc)
diff --git a/tests/start.cc b/tests/start.cc
deleted file mode 100644 (file)
index 1f5d43e..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary:
- *
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <libtest/server.h>
-
-int main(void)
-{
-  server_startup_st construct;
-
-  memset(&construct, 0, sizeof(server_startup_st));
-
-  construct.count= 4;
-
-  server_startup(&construct);
-
-  return EXIT_SUCCESS;
-}
index 4048d91c31e1d84020bcd6b87f6e87ae9755304f..ea7ba59243653a3990fc915d27ea29328c7a9d16 100644 (file)
@@ -35,6 +35,9 @@
  *
  */
 
+// We let libmemcached/common.h define config since we are looking at
+// library internals.
+
 #define BUILDING_LIBMEMCACHED
 
 #include <libmemcached/common.h>
index 1714600ef21517c279b25d9a80af837bcf5aa2fb..9ae7d6f1c21d96d52bdf6a51e294ecf5323f8bc1 100644 (file)
@@ -35,9 +35,8 @@
  *
  */
 
-#include <config.h>
+#include <libtest/common.h>
 
-#include <libtest/test.hpp>
 #include <tests/virtual_buckets.h>
 
 #include <libmemcached/memcached.h>