Merge Monty
authorBrian Aker <brian@gir-3.local>
Sun, 21 Jun 2009 15:51:17 +0000 (08:51 -0700)
committerBrian Aker <brian@gir-3.local>
Sun, 21 Jun 2009 15:51:17 +0000 (08:51 -0700)
1  2 
config/bootstrap
libmemcached/memcached_behavior.c
libmemcached/memcached_delete.c
libmemcached/memcached_get.c
libmemcached/memcached_storage.c
tests/function.c

diff --combined config/bootstrap
index d62ca6ba87f7cbc9afe7be5d40a1f55d82778dcb,0000000000000000000000000000000000000000..43095ae43fc325fee46b416c1cbc7eaa98fbd607
mode 100755,000000..120000
--- /dev/null
@@@ -1,106 -1,0 +1,1 @@@
- #!/usr/bin/env bash
- # Taken from lighthttpd server (BSD). Thanks Jan!
- # Run this to generate all the initial makefiles, etc.
- die() { echo "$@"; exit 1; }
- # LIBTOOLIZE=${LIBTOOLIZE:-libtoolize}
- LIBTOOLIZE_FLAGS=" --automake --copy --force"
- # ACLOCAL=${ACLOCAL:-aclocal}
- ACLOCAL_FLAGS="-I m4"
- # AUTOHEADER=${AUTOHEADER:-autoheader}
- # AUTOMAKE=${AUTOMAKE:-automake}
- AUTOMAKE_FLAGS="--add-missing --copy --force"
- # AUTOCONF=${AUTOCONF:-autoconf}
- ARGV0=$0
- ARGS="$@"
- run() {
-       echo "$ARGV0: running \`$@' $ARGS"
-       $@ $ARGS
- }
- ## jump out if one of the programs returns 'false'
- set -e
- ## We do not currently support glibtoolize
- if test x$LIBTOOLIZE = x; then
-   if test \! "x`which glibtoolize 2> /dev/null | grep -v '^no'`" = x; then
-     LIBTOOLIZE=glibtoolize
-   elif test \! "x`which libtoolize-1.5 2> /dev/null | grep -v '^no'`" = x; then
-     LIBTOOLIZE=libtoolize-1.5
-   elif test \! "x`which libtoolize 2> /dev/null | grep -v '^no'`" = x; then
-     LIBTOOLIZE=libtoolize
-   else 
-     echo "libtoolize 1.5.x wasn't found, exiting"; exit 0
-   fi
- fi
- ## suse has aclocal and aclocal-1.9
- if test x$ACLOCAL = x; then
-   if test \! "x`which aclocal-1.10 2> /dev/null | grep -v '^no'`" = x; then
-     ACLOCAL=aclocal-1.10
-   elif test \! "x`which aclocal-1.9 2> /dev/null | grep -v '^no'`" = x; then
-     ACLOCAL=aclocal-1.9
-   elif test \! "x`which aclocal19 2> /dev/null | grep -v '^no'`" = x; then
-     ACLOCAL=aclocal19
-   elif test \! "x`which aclocal 2> /dev/null | grep -v '^no'`" = x; then
-     ACLOCAL=aclocal
-   else 
-     echo "automake 1.9.x (aclocal) wasn't found, exiting"; exit 0
-   fi
- fi
- if test x$AUTOMAKE = x; then
-   if test \! "x`which automake-1.10 2> /dev/null | grep -v '^no'`" = x; then
-     AUTOMAKE=automake-1.10
-   elif test \! "x`which automake-1.9 2> /dev/null | grep -v '^no'`" = x; then
-     AUTOMAKE=automake-1.9
-   elif test \! "x`which automake19 2> /dev/null | grep -v '^no'`" = x; then
-     AUTOMAKE=automake19
-   elif test \! "x`which automake 2> /dev/null | grep -v '^no'`" = x; then
-     AUTOMAKE=automake
-   else 
-     echo "automake 1.9.x wasn't found, exiting"; exit 0
-   fi
- fi
- ## macosx has autoconf-2.59 and autoconf-2.60
- if test x$AUTOCONF = x; then
-   if test \! "x`which autoconf-2.59 2> /dev/null | grep -v '^no'`" = x; then
-     AUTOCONF=autoconf-2.59
-   elif test \! "x`which autoconf259 2> /dev/null | grep -v '^no'`" = x; then
-     AUTOCONF=autoconf259
-   elif test \! "x`which autoconf 2> /dev/null | grep -v '^no'`" = x; then
-     AUTOCONF=autoconf
-   else 
-     echo "autoconf 2.59+ wasn't found, exiting"; exit 0
-   fi
- fi
- if test x$AUTOHEADER = x; then
-   if test \! "x`which autoheader-2.59 2> /dev/null | grep -v '^no'`" = x; then
-     AUTOHEADER=autoheader-2.59
-   elif test \! "x`which autoheader259 2> /dev/null | grep -v '^no'`" = x; then
-     AUTOHEADER=autoheader259
-   elif test \! "x`which autoheader 2> /dev/null | grep -v '^no'`" = x; then
-     AUTOHEADER=autoheader
-   else 
-     echo "autoconf 2.59+ (autoheader) wasn't found, exiting"; exit 0
-   fi
- fi
- # --force means overwrite ltmain.sh script if it already exists 
- run $LIBTOOLIZE $LIBTOOLIZE_FLAGS || die "Can't execute libtoolize"
- run $ACLOCAL $ACLOCAL_FLAGS || die "Can't execute aclocal"
- run $AUTOHEADER || die "Can't execute autoheader"
- # --add-missing instructs automake to install missing auxiliary files
- # and --force to overwrite them if they already exist
- run $AUTOMAKE $AUTOMAKE_FLAGS  || die "Can't execute automake"
- run $AUTOCONF || die "Can't execute autoconf"
++autorun.sh
index 974bda56db46eb8d0cb3711c5a768a2fc5e8f816,ed295d95e9647706982c736696db3e9c57ad1fb4..3634dce83a214e3e9a632197e5752d02a646a3d0
@@@ -24,9 -24,6 +24,9 @@@ memcached_return memcached_behavior_set
  {
    switch (flag)
    {
 +  case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
 +    ptr->number_of_replicas= (uint32_t)data;
 +    break;
    case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK:
      ptr->io_msg_watermark= (int32_t)data;
      break;
    case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
      set_behavior_flag(ptr, MEM_AUTO_EJECT_HOSTS, data);
      break;
+   default:
+     /* Shouldn't get here */
+     WATCHPOINT_ASSERT(flag);
+     break;
    }
  
    return MEMCACHED_SUCCESS;
@@@ -172,8 -173,6 +176,8 @@@ uint64_t memcached_behavior_get(memcach
  
    switch (flag)
    {
 +  case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
 +    return ptr->number_of_replicas;
    case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK:
      return ptr->io_msg_watermark;
    case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK:
    case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
      temp_flag= MEM_AUTO_EJECT_HOSTS;
      break;
+   default:
+     WATCHPOINT_ASSERT(flag);
+     break;
    }
  
    WATCHPOINT_ASSERT(temp_flag); /* Programming mistake if it gets this far */
index 93b1eb7a1a6f7e95415e20976881b7f598046a29,f2fab3221a53cca25203b936d100d86460c5a259..5e2a0132338aa8a5ce9c9ab394d2ec620a29be21
@@@ -1,5 -1,4 +1,5 @@@
  #include "common.h"
 +#include "memcached/protocol_binary.h"
  
  memcached_return memcached_delete(memcached_st *ptr, const char *key, size_t key_length,
                                    time_t expiration)
@@@ -118,34 -117,14 +118,34 @@@ static inline memcached_return binary_d
        memcached_io_write(&ptr->hosts[server_key], NULL, 0, 1);
    }
    
 +  memcached_return rc= MEMCACHED_SUCCESS;
 +
    if ((memcached_do(&ptr->hosts[server_key], request.bytes, 
                      sizeof(request.bytes), 0) != MEMCACHED_SUCCESS) ||
        (memcached_io_write(&ptr->hosts[server_key], key, 
                            key_length, flush) == -1)) 
    {
      memcached_io_reset(&ptr->hosts[server_key]);
 -    return MEMCACHED_WRITE_FAILURE;
 +    rc= MEMCACHED_WRITE_FAILURE;
 +  }
 +
 +  unlikely (ptr->number_of_replicas > 0) 
 +  {
 +    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
 +
-     for (int x= 0; x < ptr->number_of_replicas; ++x)
++    for (uint32_t x= 0; x < ptr->number_of_replicas; ++x)
 +    {
 +      ++server_key;
 +      if (server_key == ptr->number_of_hosts)
 +        server_key= 0;
 +  
 +      memcached_server_st* server= &ptr->hosts[server_key];
 +      if ((memcached_do(server, (const char*)request.bytes, 
 +                        sizeof(request.bytes), 0) != MEMCACHED_SUCCESS) ||
 +          (memcached_io_write(server, key, key_length, flush) == -1))
 +         memcached_io_reset(server);
 +    }
    }
  
 -  return MEMCACHED_SUCCESS;
 +  return rc;
  }
index 0209b283ab1129ec5b53347e91d1420ca2366e36,05b317a6268b79d19b5a711d49dfb05cf4dc3cb1..e91db4cf363854f3aa363691c23ece90b274c8ac
@@@ -143,6 -143,12 +143,6 @@@ memcached_return memcached_mget_by_key(
    if ((ptr->flags & MEM_VERIFY_KEY) && (memcached_key_test(keys, key_length, number_of_keys) == MEMCACHED_BAD_KEY_PROVIDED))
      return MEMCACHED_BAD_KEY_PROVIDED;
  
 -  if (ptr->flags & MEM_SUPPORT_CAS)
 -  {
 -    get_command= "gets ";
 -    get_command_length= 5;
 -  }
 -
    if (master_key && master_key_length)
    {
      if ((ptr->flags & MEM_VERIFY_KEY) && (memcached_key_test((char **)&master_key, &master_key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
      return binary_mget_by_key(ptr, master_server_key, is_master_key_set, keys, 
                                key_length, number_of_keys);
  
 +  if (ptr->flags & MEM_SUPPORT_CAS)
 +  {
 +    get_command= "gets ";
 +    get_command_length= 5;
 +  }
 +
    /* 
      If a server fails we warn about errors and start all over with sending keys
      to the server.
    return rc;
  }
  
 -static memcached_return binary_mget_by_key(memcached_st *ptr, 
 +static memcached_return simple_binary_mget(memcached_st *ptr,
                                             unsigned int master_server_key,
                                             bool is_master_key_set,
                                             char **keys, size_t *key_length, 
  
    return rc;
  }
-   for (int replica = 0; replica <= ptr->number_of_replicas; ++replica)
 +
 +static memcached_return replication_binary_mget(memcached_st *ptr,
 +                                             uint32_t* hash, bool* dead_servers,
 +                                             char **keys, size_t *key_length,
 +                                             unsigned int number_of_keys)
 +{
 +  memcached_return rc= MEMCACHED_NOTFOUND;
 +  uint32_t x;
 +
 +  int flush= number_of_keys == 1;
 +
-     for (uint32_t x= 0; x < number_of_keys; ++x)
++  for (uint32_t replica= 0; replica <= ptr->number_of_replicas; ++replica)
 +  {
 +    bool success= true;    
 +    
-           for (uint32_t x= 0; x < number_of_keys; ++x)
++    for (x= 0; x < number_of_keys; ++x)
 +    {
 +      if (hash[x] == ptr->number_of_hosts)
 +        continue; /* Already successfully sent */
 +
 +      uint32_t server= hash[x] + replica;
 +      while (server >= ptr->number_of_hosts)
 +        server -= ptr->number_of_hosts;
 +
 +      if (dead_servers[server])
 +        continue;
 +
 +      if (memcached_server_response_count(&ptr->hosts[server]) == 0)
 +      {
 +        rc= memcached_connect(&ptr->hosts[server]);
 +        if (rc != MEMCACHED_SUCCESS)
 +        {
 +          memcached_io_reset(&ptr->hosts[server]);
 +          dead_servers[server]= true;
 +          success= false;
 +          continue;
 +        }
 +      }
 +
 +      protocol_binary_request_getk request= {.bytes= {0}};
 +      request.message.header.request.magic= PROTOCOL_BINARY_REQ;
 +      if (number_of_keys == 1)
 +        request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
 +      else
 +        request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETKQ;
 +
 +      request.message.header.request.keylen= htons((uint16_t)key_length[x]);
 +      request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
 +      request.message.header.request.bodylen= htonl(key_length[x]);
 +
 +      if ((memcached_io_write(&ptr->hosts[server], request.bytes,
 +                              sizeof(request.bytes), 0) == -1) ||
 +          (memcached_io_write(&ptr->hosts[server], keys[x],
 +                              key_length[x], flush) == -1))
 +      {
 +        memcached_io_reset(&ptr->hosts[server]);
 +        dead_servers[server]= true;
 +        success= false;
 +        continue;
 +      }
 +      memcached_server_response_increment(&ptr->hosts[server]);
 +    }
 +
 +    if (number_of_keys > 1)
 +    {
 +      /*
 +       * Send a noop command to flush the buffers
 +       */
 +      protocol_binary_request_noop request= {.bytes= {0}};
 +      request.message.header.request.magic= PROTOCOL_BINARY_REQ;
 +      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_NOOP;
 +      request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
 +
 +      for (x= 0; x < ptr->number_of_hosts; x++)
 +        if (memcached_server_response_count(&ptr->hosts[x]))
 +        {
 +          if (memcached_io_write(&ptr->hosts[x], request.bytes,
 +                                 sizeof(request.bytes), 1) == -1)
 +          {
 +            memcached_io_reset(&ptr->hosts[x]);
 +            dead_servers[x]= true;
 +            success= false;
 +          }
 +          memcached_server_response_increment(&ptr->hosts[x]);
 +
 +          /* mark all of the messages bound for this server as sent! */
++          for (x= 0; x < number_of_keys; ++x)
 +            if (hash[x] == x)
 +              hash[x]= ptr->number_of_hosts;
 +        }
 +    }
 +
 +    if (success)
 +      break;
 +  }
 +
 +  return rc;
 +}
 +
 +static memcached_return binary_mget_by_key(memcached_st *ptr,
 +                                           unsigned int master_server_key,
 +                                           bool is_master_key_set,
 +                                           char **keys, size_t *key_length,
 +                                           unsigned int number_of_keys)
 +{
 +  memcached_return rc;
 +
 +  if (ptr->number_of_replicas == 0) 
 +  {
 +    rc= simple_binary_mget(ptr, master_server_key, is_master_key_set,
 +                           keys, key_length, number_of_keys);
 +  } 
 +  else 
 +  {
 +    uint32_t* hash;
 +    bool* dead_servers;
 +
 +    hash= ptr->call_malloc(ptr, sizeof(uint32_t) * number_of_keys);
 +    dead_servers= ptr->call_calloc(ptr, ptr->number_of_hosts, sizeof(bool));
 +
 +    if (hash == NULL || dead_servers == NULL)
 +    {
 +      ptr->call_free(ptr, hash);
 +      ptr->call_free(ptr, dead_servers);
 +      return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
 +    }
 +
 +    if (is_master_key_set)
 +      for (unsigned int x= 0; x < number_of_keys; x++)
 +        hash[x]= master_server_key;
 +    else
 +      for (unsigned int x= 0; x < number_of_keys; x++)
 +        hash[x]= memcached_generate_hash(ptr, keys[x], key_length[x]);
 +
 +    rc= replication_binary_mget(ptr, hash, dead_servers, keys, 
 +                                key_length, number_of_keys);
 +
 +    ptr->call_free(ptr, hash);
 +    ptr->call_free(ptr, dead_servers);
 +
 +    return MEMCACHED_SUCCESS;
 +  }
 +
 +  return rc;
 +}
index 713f831d2c4fe399cfddd8443e4b453a5a2ea5ca,dd7e23b0ddf2d8d99610b9b04687edefa841d78e..b950dc92f45e8bebc02a052636533019714987d5
@@@ -37,14 -37,12 +37,14 @@@ static char *storage_op_string(memcache
      return "cas ";
    default:
      return "tosserror"; /* This is impossible, fixes issue for compiler warning in VisualStudio */
-   };
+   }
  
    /* NOTREACHED */
  }
  
 -static memcached_return memcached_send_binary(memcached_server_st* server, 
 +static memcached_return memcached_send_binary(memcached_st *ptr,
 +                                              const char *master_key, 
 +                                              size_t master_key_length,
                                                const char *key, 
                                                size_t key_length, 
                                                const char *value, 
@@@ -82,14 -80,13 +82,14 @@@ static inline memcached_return memcache
    if ((ptr->flags & MEM_VERIFY_KEY) && (memcached_key_test((char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
      return MEMCACHED_BAD_KEY_PROVIDED;
  
 -  server_key= memcached_generate_hash(ptr, master_key, master_key_length);
 -
    if (ptr->flags & MEM_BINARY_PROTOCOL)
 -    return memcached_send_binary(&ptr->hosts[server_key], key, key_length, 
 -                                 value, value_length, expiration, 
 +    return memcached_send_binary(ptr, master_key, master_key_length,
 +                                 key, key_length,
 +                                 value, value_length, expiration,
                                   flags, cas, verb);
  
 +  server_key= memcached_generate_hash(ptr, master_key, master_key_length);
 +
    if (cas)
      write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
                             "%s %s%.*s %u %llu %zu %llu%s\r\n", 
@@@ -384,6 -381,9 +384,9 @@@ static inline uint8_t get_com_code(memc
      case PREPEND_OP:
        ret=PROTOCOL_BINARY_CMD_PREPENDQ;
        break;
+     default:
+       WATCHPOINT_ASSERT(verb);
+       break;
      }
    else
      switch (verb)
      case PREPEND_OP:
        ret=PROTOCOL_BINARY_CMD_PREPEND;
        break;
+     default:
+       WATCHPOINT_ASSERT(verb);
+       break;
      }
  
     return ret;
  
  
  
 -static memcached_return memcached_send_binary(memcached_server_st* server, 
 -                                              const char *key, 
 +static memcached_return memcached_send_binary(memcached_st *ptr,
 +                                              const char *master_key, 
 +                                              size_t master_key_length,
 +                                              const char *key,
                                                size_t key_length, 
                                                const char *value, 
                                                size_t value_length, 
    char flush;
    protocol_binary_request_set request= {.bytes= {0}};
    size_t send_length= sizeof(request.bytes);
 +  uint32_t server_key= memcached_generate_hash(ptr, master_key, 
 +                                               master_key_length);
 +  memcached_server_st *server= &ptr->hosts[server_key];
    bool noreply= server->root->flags & MEM_NOREPLY;
  
    request.message.header.request.magic= PROTOCOL_BINARY_REQ;
      memcached_io_reset(server);
      return MEMCACHED_WRITE_FAILURE;
    }
 -  
 +
 +  unlikely (verb == SET_OP && ptr->number_of_replicas > 0) 
 +  {
 +    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_SETQ;
 +
-     for (int x= 0; x < ptr->number_of_replicas; ++x)
++    for (uint32_t x= 0; x < ptr->number_of_replicas; x++)
 +    {
 +      ++server_key;
 +      if (server_key == ptr->number_of_hosts)
 +        server_key= 0;
 +
 +      memcached_server_st *srv= &ptr->hosts[server_key];
 +      if ((memcached_do(srv, (const char*)request.bytes, 
 +                        send_length, 0) != MEMCACHED_SUCCESS) ||
 +          (memcached_io_write(srv, key, key_length, 0) == -1) ||
 +          (memcached_io_write(srv, value, value_length, flush) == -1))
 +        memcached_io_reset(server);
 +    }
 +  }
 +
    if (flush == 0)
      return MEMCACHED_BUFFERED;
  
diff --combined tests/function.c
index 5f83e1ea2a16a05d8f5133c189aff8a212fbe172,fcf5b51104008b27b905923d8bec0103ff78565a..c505b1118088247d28f67aca9449ba6ab0079bcf
@@@ -94,7 -94,7 +94,7 @@@ static test_return  server_sort_test(me
  
    for (x= 0; x < TEST_PORT_COUNT; x++)
    {
-     test_ports[x]= random() % 64000;
+     test_ports[x]= (uint32_t)random() % 64000;
      rc= memcached_server_add_with_weight(local_memc, "localhost", test_ports[x], 0);
      assert(local_memc->number_of_hosts == x + 1);
      assert(local_memc->hosts[0].count == x+1);
@@@ -165,7 -165,7 +165,7 @@@ static test_return  server_unsort_test(
  
    for (x= 0; x < TEST_PORT_COUNT; x++)
    {
-     test_ports[x]= random() % 64000;
+     test_ports[x]= (uint32_t)(random() % 64000);
      rc= memcached_server_add_with_weight(local_memc, "localhost", test_ports[x], 0);
      assert(local_memc->number_of_hosts == x+1);
      assert(local_memc->hosts[0].count == x+1);
@@@ -200,65 -200,64 +200,64 @@@ static test_return  clone_test(memcache
  {
    /* All null? */
    {
-     memcached_st *clone;
-     clone= memcached_clone(NULL, NULL);
-     assert(clone);
-     memcached_free(clone);
+     memcached_st *memc_clone;
+     memc_clone= memcached_clone(NULL, NULL);
+     assert(memc_clone);
+     memcached_free(memc_clone);
    }
  
    /* Can we init from null? */
    {
-     memcached_st *clone;
-     clone= memcached_clone(NULL, memc);
-     assert(clone);
-     assert(clone->call_free == memc->call_free);
-     assert(clone->call_malloc == memc->call_malloc);
-     assert(clone->call_realloc == memc->call_realloc);
-     assert(clone->call_calloc == memc->call_calloc);
-     assert(clone->connect_timeout == memc->connect_timeout);
-     assert(clone->delete_trigger == memc->delete_trigger);
-     assert(clone->distribution == memc->distribution);
-     assert(clone->flags == memc->flags);
-     assert(clone->get_key_failure == memc->get_key_failure);
-     assert(clone->hash == memc->hash);
-     assert(clone->hash_continuum == memc->hash_continuum);
-     assert(clone->io_bytes_watermark == memc->io_bytes_watermark);
-     assert(clone->io_msg_watermark == memc->io_msg_watermark);
-     assert(clone->io_key_prefetch == memc->io_key_prefetch);
-     assert(clone->on_cleanup == memc->on_cleanup);
-     assert(clone->on_clone == memc->on_clone);
-     assert(clone->poll_timeout == memc->poll_timeout);
-     assert(clone->rcv_timeout == memc->rcv_timeout);
-     assert(clone->recv_size == memc->recv_size);
-     assert(clone->retry_timeout == memc->retry_timeout);
-     assert(clone->send_size == memc->send_size);
-     assert(clone->server_failure_limit == memc->server_failure_limit);
-     assert(clone->snd_timeout == memc->snd_timeout);
-     assert(clone->user_data == memc->user_data);
-     assert(clone->number_of_replicas == memc->number_of_replicas);
-     memcached_free(clone);
+     memcached_st *memc_clone;
+     memc_clone= memcached_clone(NULL, memc);
+     assert(memc_clone);
+     assert(memc_clone->call_free == memc->call_free);
+     assert(memc_clone->call_malloc == memc->call_malloc);
+     assert(memc_clone->call_realloc == memc->call_realloc);
+     assert(memc_clone->call_calloc == memc->call_calloc);
+     assert(memc_clone->connect_timeout == memc->connect_timeout);
+     assert(memc_clone->delete_trigger == memc->delete_trigger);
+     assert(memc_clone->distribution == memc->distribution);
+     assert(memc_clone->flags == memc->flags);
+     assert(memc_clone->get_key_failure == memc->get_key_failure);
+     assert(memc_clone->hash == memc->hash);
+     assert(memc_clone->hash_continuum == memc->hash_continuum);
+     assert(memc_clone->io_bytes_watermark == memc->io_bytes_watermark);
+     assert(memc_clone->io_msg_watermark == memc->io_msg_watermark);
+     assert(memc_clone->io_key_prefetch == memc->io_key_prefetch);
+     assert(memc_clone->on_cleanup == memc->on_cleanup);
+     assert(memc_clone->on_clone == memc->on_clone);
+     assert(memc_clone->poll_timeout == memc->poll_timeout);
+     assert(memc_clone->rcv_timeout == memc->rcv_timeout);
+     assert(memc_clone->recv_size == memc->recv_size);
+     assert(memc_clone->retry_timeout == memc->retry_timeout);
+     assert(memc_clone->send_size == memc->send_size);
+     assert(memc_clone->server_failure_limit == memc->server_failure_limit);
+     assert(memc_clone->snd_timeout == memc->snd_timeout);
+     assert(memc_clone->user_data == memc->user_data);
+     memcached_free(memc_clone);
    }
  
    /* Can we init from struct? */
    {
      memcached_st declared_clone;
-     memcached_st *clone;
+     memcached_st *memc_clone;
      memset(&declared_clone, 0 , sizeof(memcached_st));
-     clone= memcached_clone(&declared_clone, NULL);
-     assert(clone);
-     memcached_free(clone);
+     memc_clone= memcached_clone(&declared_clone, NULL);
+     assert(memc_clone);
+     memcached_free(memc_clone);
    }
  
    /* Can we init from struct? */
    {
      memcached_st declared_clone;
-     memcached_st *clone;
+     memcached_st *memc_clone;
      memset(&declared_clone, 0 , sizeof(memcached_st));
-     clone= memcached_clone(&declared_clone, memc);
-     assert(clone);
-     memcached_free(clone);
+     memc_clone= memcached_clone(&declared_clone, memc);
+     assert(memc_clone);
+     memcached_free(memc_clone);
    }
  
    return 0;
  
  static test_return userdata_test(memcached_st *memc)
  {
-   void* foo;
+   void* foo= NULL;
    assert(memcached_set_user_data(memc, foo) == NULL);
    assert(memcached_get_user_data(memc) == foo);
    assert(memcached_set_user_data(memc, NULL) == foo);
@@@ -658,29 -657,29 +657,29 @@@ static test_return  bad_key_test(memcac
    char *string;
    size_t string_length;
    uint32_t flags;
-   memcached_st *clone;
+   memcached_st *memc_clone;
    unsigned int set= 1;
    size_t max_keylen= 0xffff;
  
-   clone= memcached_clone(NULL, memc);
-   assert(clone);
+   memc_clone= memcached_clone(NULL, memc);
+   assert(memc_clone);
  
-   rc= memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_VERIFY_KEY, set);
+   rc= memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_VERIFY_KEY, set);
    assert(rc == MEMCACHED_SUCCESS);
  
    /* All keys are valid in the binary protocol (except for length) */
-   if (memcached_behavior_get(clone, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == 0) 
+   if (memcached_behavior_get(memc_clone, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == 0) 
    {
-     string= memcached_get(clone, key, strlen(key),
+     string= memcached_get(memc_clone, key, strlen(key),
                            &string_length, &flags, &rc);
      assert(rc == MEMCACHED_BAD_KEY_PROVIDED);
      assert(string_length ==  0);
      assert(!string);
  
      set= 0;
-     rc= memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_VERIFY_KEY, set);
+     rc= memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_VERIFY_KEY, set);
      assert(rc == MEMCACHED_SUCCESS);
-     string= memcached_get(clone, key, strlen(key),
+     string= memcached_get(memc_clone, key, strlen(key),
                            &string_length, &flags, &rc);
      assert(rc == MEMCACHED_NOTFOUND);
      assert(string_length ==  0);
      char *keys[] = { "GoodKey", "Bad Key", "NotMine" };
      size_t key_lengths[] = { 7, 7, 7 };
      set= 1;
-     rc= memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_VERIFY_KEY, set);
+     rc= memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_VERIFY_KEY, set);
      assert(rc == MEMCACHED_SUCCESS);
  
-     rc= memcached_mget(clone, keys, key_lengths, 3);
+     rc= memcached_mget(memc_clone, keys, key_lengths, 3);
      assert(rc == MEMCACHED_BAD_KEY_PROVIDED);
  
-     rc= memcached_mget_by_key(clone, "foo daddy", 9, keys, key_lengths, 1);
+     rc= memcached_mget_by_key(memc_clone, "foo daddy", 9, keys, key_lengths, 1);
      assert(rc == MEMCACHED_BAD_KEY_PROVIDED);
  
      max_keylen= 250;
         memcached server is updated to allow max size length of the keys in the
         binary protocol
      */
-     rc= memcached_callback_set(clone, MEMCACHED_CALLBACK_PREFIX_KEY, NULL);
+     rc= memcached_callback_set(memc_clone, MEMCACHED_CALLBACK_PREFIX_KEY, NULL);
      assert(rc == MEMCACHED_SUCCESS);
  
      char *longkey= malloc(max_keylen + 1);
      if (longkey != NULL) 
      {
        memset(longkey, 'a', max_keylen + 1);
-       string= memcached_get(clone, longkey, max_keylen,
+       string= memcached_get(memc_clone, longkey, max_keylen,
                              &string_length, &flags, &rc);
        assert(rc == MEMCACHED_NOTFOUND);
        assert(string_length ==  0);
        assert(!string);
  
-       string= memcached_get(clone, longkey, max_keylen + 1,
+       string= memcached_get(memc_clone, longkey, max_keylen + 1,
                              &string_length, &flags, &rc);
        assert(rc == MEMCACHED_BAD_KEY_PROVIDED);
        assert(string_length ==  0);
  
    /* Make sure zero length keys are marked as bad */
    set= 1;
-   rc= memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_VERIFY_KEY, set);
+   rc= memcached_behavior_set(memc_clone, MEMCACHED_BEHAVIOR_VERIFY_KEY, set);
    assert(rc == MEMCACHED_SUCCESS);
-   string= memcached_get(clone, key, 0,
+   string= memcached_get(memc_clone, key, 0,
                          &string_length, &flags, &rc);
    assert(rc == MEMCACHED_BAD_KEY_PROVIDED);
    assert(string_length ==  0);
    assert(!string);
  
-   memcached_free(clone);
+   memcached_free(memc_clone);
  
    return 0;
  }
@@@ -1036,8 -1035,8 +1035,8 @@@ static test_return get_test5(memcached_
  static test_return  stats_servername_test(memcached_st *memc)
  {
    memcached_return rc;
-   memcached_stat_st stat;
-   rc= memcached_stat_servername(&stat, NULL,
+   memcached_stat_st memc_stat;
+   rc= memcached_stat_servername(&memc_stat, NULL,
                                   memc->hosts[0].hostname, 
                                   memc->hosts[0].port);
  
@@@ -1367,10 -1366,10 +1366,10 @@@ static test_return  get_stats_keys(memc
  {
   char **list;
   char **ptr;
-  memcached_stat_st stat;
+  memcached_stat_st memc_stat;
   memcached_return rc;
  
-  list= memcached_stat_get_keys(memc, &stat, &rc);
+  list= memcached_stat_get_keys(memc, &memc_stat, &rc);
   assert(rc == MEMCACHED_SUCCESS);
   for (ptr= list; *ptr; ptr++)
     assert(*ptr);
@@@ -1398,24 -1397,24 +1397,24 @@@ static test_return  get_stats(memcached
   char **list;
   char **ptr;
   memcached_return rc;
-  memcached_stat_st *stat;
+  memcached_stat_st *memc_stat;
  
-  stat= memcached_stat(memc, NULL, &rc);
+  memc_stat= memcached_stat(memc, NULL, &rc);
   assert(rc == MEMCACHED_SUCCESS);
  
   assert(rc == MEMCACHED_SUCCESS);
-  assert(stat);
+  assert(memc_stat);
  
   for (x= 0; x < memcached_server_count(memc); x++)
   {
-    list= memcached_stat_get_keys(memc, stat+x, &rc);
+    list= memcached_stat_get_keys(memc, memc_stat+x, &rc);
     assert(rc == MEMCACHED_SUCCESS);
     for (ptr= list; *ptr; ptr++);
  
     free(list);
   }
  
-  memcached_stat_free(NULL, stat);
+  memcached_stat_free(NULL, memc_stat);
  
    return 0;
  }
@@@ -1452,7 -1451,7 +1451,7 @@@ static test_return  add_host_test(memca
    return 0;
  }
  
- static memcached_return  clone_test_callback(memcached_st *parent __attribute__((unused)), memcached_st *clone __attribute__((unused)))
+ static memcached_return  clone_test_callback(memcached_st *parent __attribute__((unused)), memcached_st *memc_clone __attribute__((unused)))
  {
    return MEMCACHED_SUCCESS;
  }
@@@ -1553,9 -1552,6 +1552,9 @@@ static test_return  behavior_test(memca
    value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE);
    assert(value > 0);
  
 +  value= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS);
 +  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, value + 1);
 +  assert((value + 1) == memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS));
    return 0;
  }
  
@@@ -1585,12 -1581,12 +1584,12 @@@ static test_return  user_supplied_bug1(
    {
      unsigned int j= 0;
  
-     size= (rand() % ( 5 * 1024 ) ) + 400;
+     size= (uint32_t)(rand() % ( 5 * 1024 ) ) + 400;
      memset(randomstuff, 0, 6 * 1024);
      assert(size < 6 * 1024); /* Being safe here */
  
      for (j= 0 ; j < size ;j++) 
-       randomstuff[j] = (char) (rand() % 26) + 97;
+       randomstuff[j] = (signed char) ((rand() % 26) + 97);
  
      total += size;
      sprintf(key, "%d", x);
@@@ -1802,7 -1798,7 +1801,7 @@@ static test_return  user_supplied_bug5(
    char insert_data[VALUE_SIZE_BUG5];
  
    for (x= 0; x < VALUE_SIZE_BUG5; x++)
-     insert_data[x]= rand();
+     insert_data[x]= (signed char)rand();
  
    memcached_flush(memc, 0);
    value= memcached_get(memc, keys[0], key_length[0],
@@@ -1860,7 -1856,7 +1859,7 @@@ static test_return  user_supplied_bug6(
    char insert_data[VALUE_SIZE_BUG5];
  
    for (x= 0; x < VALUE_SIZE_BUG5; x++)
-     insert_data[x]= rand();
+     insert_data[x]= (signed char)rand();
  
    memcached_flush(memc, 0);
    value= memcached_get(memc, keys[0], key_length[0],
@@@ -1914,7 -1910,7 +1913,7 @@@ static test_return  user_supplied_bug8(
  {
    memcached_return rc;
    memcached_st *mine;
-   memcached_st *clone;
+   memcached_st *memc_clone;
  
    memcached_server_st *servers;
    char *server_list= "memcache1.memcache.bk.sapo.pt:11211, memcache1.memcache.bk.sapo.pt:11212, memcache1.memcache.bk.sapo.pt:11213, memcache1.memcache.bk.sapo.pt:11214, memcache2.memcache.bk.sapo.pt:11211, memcache2.memcache.bk.sapo.pt:11212, memcache2.memcache.bk.sapo.pt:11213, memcache2.memcache.bk.sapo.pt:11214";
    memcached_server_list_free(servers);
  
    assert(mine);
-   clone= memcached_clone(NULL, mine);
+   memc_clone= memcached_clone(NULL, mine);
  
    memcached_quit(mine);
-   memcached_quit(clone);
+   memcached_quit(memc_clone);
  
  
    memcached_free(mine);
-   memcached_free(clone);
+   memcached_free(memc_clone);
  
    return 0;
  }
@@@ -1955,7 -1951,7 +1954,7 @@@ static test_return  user_supplied_bug7(
    char insert_data[VALUE_SIZE_BUG5];
  
    for (x= 0; x < VALUE_SIZE_BUG5; x++)
-     insert_data[x]= rand();
+     insert_data[x]= (signed char)rand();
  
    memcached_flush(memc, 0);
  
@@@ -2036,7 -2032,7 +2035,7 @@@ static test_return  user_supplied_bug10
    char *value;
    size_t value_length= 512;
    unsigned int x;
-   int key_len= 3;
+   size_t key_len= 3;
    memcached_return rc;
    unsigned int set= 1;
    memcached_st *mclone= memcached_clone(NULL, memc);
    memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_NO_BLOCK, set);
    memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_TCP_NODELAY, set);
    timeout= 2;
-   memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, timeout);
+   memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_POLL_TIMEOUT,
+                          (uint64_t)timeout);
  
    value = (char*)malloc(value_length * sizeof(char));
  
@@@ -2078,7 -2075,7 +2078,7 @@@ static test_return  user_supplied_bug11
    char *value;
    size_t value_length= 512;
    unsigned int x;
-   int key_len= 3;
+   size_t key_len= 3;
    memcached_return rc;
    unsigned int set= 1;
    int32_t timeout;
    memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_NO_BLOCK, set);
    memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_TCP_NODELAY, set);
    timeout= -1;
-   memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, timeout);
+   memcached_behavior_set(mclone, MEMCACHED_BEHAVIOR_POLL_TIMEOUT,
+                          (size_t)timeout);
  
    timeout= (int32_t)memcached_behavior_get(mclone, MEMCACHED_BEHAVIOR_POLL_TIMEOUT);
  
@@@ -2195,7 -2193,7 +2196,7 @@@ static test_return  user_supplied_bug13
   */
  static test_return  user_supplied_bug14(memcached_st *memc)
  {
-   int setter= 1;
+   size_t setter= 1;
    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_TCP_NODELAY, setter);
    memcached_return rc;
    char *key= "foo";
@@@ -2388,7 -2386,7 +2389,7 @@@ static test_return user_supplied_bug20(
  static test_return user_supplied_bug18(memcached_st *trash)
  {
    memcached_return rc;
-   int value;
+   uint64_t value;
    int x;
    memcached_server_st *server_pool;
    memcached_st *memc;
@@@ -2700,7 -2698,7 +2701,7 @@@ static test_return  generate_data_with_
  }
  static test_return  generate_buffer_data(memcached_st *memc)
  {
-   int latch= 0;
+   size_t latch= 0;
  
    latch= 1;
    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, latch);
@@@ -2713,12 -2711,12 +2714,12 @@@ static test_return  get_read_count(memc
  {
    unsigned int x;
    memcached_return rc;
-   memcached_st *clone;
+   memcached_st *memc_clone;
  
-   clone= memcached_clone(NULL, memc);
-   assert(clone);
+   memc_clone= memcached_clone(NULL, memc);
+   assert(memc_clone);
  
-   memcached_server_add_with_weight(clone, "localhost", 6666, 0);
+   memcached_server_add_with_weight(memc_clone, "localhost", 6666, 0);
  
    {
      char *return_value;
  
      for (x= count= 0; x < global_count; x++)
      {
-       return_value= memcached_get(clone, global_keys[x], global_keys_length[x],
+       return_value= memcached_get(memc_clone, global_keys[x], global_keys_length[x],
                                    &return_value_length, &flags, &rc);
        if (rc == MEMCACHED_SUCCESS)
        {
      fprintf(stderr, "\t%u -> %u", global_count, count);
    }
  
-   memcached_free(clone);
+   memcached_free(memc_clone);
  
    return 0;
  }
@@@ -2852,7 -2850,7 +2853,7 @@@ static test_return  delete_generate(mem
  
  static test_return  delete_buffer_generate(memcached_st *memc)
  {
-   int latch= 0;
+   size_t latch= 0;
    unsigned int x;
  
    latch= 1;
@@@ -2908,15 -2906,15 +2909,15 @@@ static memcached_return  pre_nonblock(m
  static memcached_return  pre_nonblock_binary(memcached_st *memc)
  {
    memcached_return rc= MEMCACHED_FAILURE;
-   memcached_st *clone;
+   memcached_st *memc_clone;
  
-   clone= memcached_clone(NULL, memc);
-   assert(clone);
+   memc_clone= memcached_clone(NULL, memc);
+   assert(memc_clone);
    // The memcached_version needs to be done on a clone, because the server
    // will not toggle protocol on an connection.
-   memcached_version(clone);
+   memcached_version(memc_clone);
  
-   if (clone->hosts[0].major_version >= 1 && clone->hosts[0].minor_version > 2) 
+   if (memc_clone->hosts[0].major_version >= 1 && memc_clone->hosts[0].minor_version > 2) 
    {
      memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, 0);
      rc = memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
      assert(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == 1);
    }
  
-   memcached_free(clone);
+   memcached_free(memc_clone);
    return rc;
  }
  
@@@ -3032,43 -3030,25 +3033,43 @@@ static memcached_return  pre_behavior_k
  static memcached_return  pre_binary(memcached_st *memc)
  {
    memcached_return rc= MEMCACHED_FAILURE;
-   memcached_st *clone;
+   memcached_st *memc_clone;
  
-   clone= memcached_clone(NULL, memc);
-   assert(clone);
+   memc_clone= memcached_clone(NULL, memc);
+   assert(memc_clone);
    // The memcached_version needs to be done on a clone, because the server
    // will not toggle protocol on an connection.
-   memcached_version(clone);
+   memcached_version(memc_clone);
  
-   if (clone->hosts[0].major_version >= 1 && clone->hosts[0].minor_version > 2) 
+   if (memc_clone->hosts[0].major_version >= 1 && memc_clone->hosts[0].minor_version > 2) 
    {
      rc = memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL, 1);
      assert(rc == MEMCACHED_SUCCESS);
      assert(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL) == 1);
    }
  
-   memcached_free(clone);
+   memcached_free(memc_clone);
    return rc;
  }
  
 +static memcached_return pre_replication(memcached_st *memc)
 +{
 +  memcached_return rc= MEMCACHED_FAILURE;
 +  if (pre_binary(memc) == MEMCACHED_SUCCESS) 
 +  {
 +    /*
 +     * Make sure that we store the item on all servers 
 +     * (master + replicas == number of servers) 
 +     */
 +    rc= memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 
 +                               memc->number_of_hosts - 1);
 +    assert(rc == MEMCACHED_SUCCESS);
 +    assert(memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS) == memc->number_of_hosts - 1);
 +  }
 +
 +  return rc;
 +}
 +
  static void my_free(memcached_st *ptr __attribute__((unused)), void *mem)
  {
    free(mem);
@@@ -3311,13 -3291,13 +3312,13 @@@ static memcached_return  pre_settimer(m
  
  static memcached_return  poll_timeout(memcached_st *memc)
  {
-   int32_t timeout;
+   size_t timeout;
  
    timeout= 100;
  
    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, timeout);
  
-   timeout= (int32_t)memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT);
+   timeout= memcached_behavior_get(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT);
  
    assert(timeout == 100);
  
@@@ -3342,7 -3322,7 +3343,7 @@@ static test_return noreply_test(memcach
      for (int x=0; x < 100; ++x)
      {
        char key[10];
-       size_t len= sprintf(key, "%d", x);
+       size_t len= (size_t)sprintf(key, "%d", x);
        switch (count)
        {
        case 0:
        case 4:
          ret=memcached_prepend(memc, key, len, key, len, 0, 0);
          break;
+       default:
+         assert(count);
+         break;
        }
        assert(ret == MEMCACHED_SUCCESS || ret == MEMCACHED_BUFFERED);
      }
      */
      int no_msg=0;
      for (uint32_t x=0; x < memc->number_of_hosts; ++x)
-       no_msg+=memc->hosts[x].cursor_active;
+       no_msg+=(int)(memc->hosts[x].cursor_active);
  
      assert(no_msg == 0);
      assert(memcached_flush_buffers(memc) == MEMCACHED_SUCCESS);
      for (int x=0; x < 100; ++x)
      {
        char key[10];
-       size_t len= sprintf(key, "%d", x);
+       size_t len= (size_t)sprintf(key, "%d", x);
        size_t length;
        uint32_t flags;
        char* value=memcached_get(memc, key, strlen(key),
        case 4:
          assert(length == len * 3);
          break;
+       default:
+         assert(count);
+         break;
        }
        free(value);
      }
  static test_return analyzer_test(memcached_st *memc)
  {
    memcached_return rc;
-   memcached_stat_st *stat;
+   memcached_stat_st *memc_stat;
    memcached_analysis_st *report;
  
-   stat= memcached_stat(memc, NULL, &rc);
+   memc_stat= memcached_stat(memc, NULL, &rc);
    assert(rc == MEMCACHED_SUCCESS);
-   assert(stat);
+   assert(memc_stat);
  
-   report= memcached_analyze(memc, stat, &rc);  
+   report= memcached_analyze(memc, memc_stat, &rc);  
    assert(rc == MEMCACHED_SUCCESS);
    assert(report);
  
    free(report);
-   memcached_stat_free(NULL, stat);
+   memcached_stat_free(NULL, memc_stat);
  
    return TEST_SUCCESS;
  }
@@@ -3564,177 -3550,6 +3571,179 @@@ static test_return connection_pool_test
  }
  #endif
  
-   for (int host= 0; host < memc->number_of_hosts; ++host) {
 +static test_return replication_set_test(memcached_st *memc)
 +{
 +  memcached_return rc;
 +  memcached_st *clone= memcached_clone(NULL, memc);
 +  memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 0);
 +
 +  rc= memcached_set(memc, "bubba", 5, "0", 1, 0, 0);
 +  assert(rc == MEMCACHED_SUCCESS);
 +
 +  /*
 +  ** "bubba" should now be stored on all of our servers. We don't have an
 +  ** easy to use API to address each individual server, so I'll just iterate
 +  ** through a bunch of "master keys" and I should most likely hit all of the
 +  ** servers...
 +  */
 +  for (int x= 'a'; x <= 'z'; ++x)
 +  {
 +    char key[2]= { [0]= (char)x };
 +    size_t len;
 +    uint32_t flags;
 +    char *val= memcached_get_by_key(clone, key, 1, "bubba", 5, 
 +                                    &len, &flags, &rc);
 +    assert(rc == MEMCACHED_SUCCESS);
 +    assert(val != NULL);
 +    free(val);
 +  }
 +
 +  memcached_free(clone);
 +
 +  return TEST_SUCCESS;
 +}
 +
 +static test_return replication_get_test(memcached_st *memc)
 +{
 +  memcached_return rc;
 +
 +  /*
 +   * Don't do the following in your code. I am abusing the internal details
 +   * within the library, and this is not a supported interface.
 +   * This is to verify correct behavior in the library
 +   */
-   for (int host= 0; host < clone->number_of_hosts; ++host) 
++  for (uint32_t host= 0; host < memc->number_of_hosts; ++host) 
++  {
 +    memcached_st *clone= memcached_clone(NULL, memc);
 +    clone->hosts[host].port= 0;
 +
 +    for (int x= 'a'; x <= 'z'; ++x)
 +    {
 +      char key[2]= { [0]= (char)x };
 +      size_t len;
 +      uint32_t flags;
 +      char *val= memcached_get_by_key(clone, key, 1, "bubba", 5, 
 +                                      &len, &flags, &rc);
 +      assert(rc == MEMCACHED_SUCCESS);
 +      assert(val != NULL);
 +      free(val);
 +    }
 +
 +    memcached_free(clone);
 +  }
 +
 +  return TEST_SUCCESS;
 +}
 +
 +static test_return replication_mget_test(memcached_st *memc)
 +{
 +  memcached_return rc;
 +  memcached_st *clone= memcached_clone(NULL, memc);
 +  memcached_behavior_set(clone, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, 0);
 +
 +  char *keys[]= { "bubba", "key1", "key2", "key3" };
 +  size_t len[]= { 5, 4, 4, 4 };
 +
 +  for (int x=0; x< 4; ++x)
 +  {
 +    rc= memcached_set(memc, keys[x], len[x], "0", 1, 0, 0);
 +    assert(rc == MEMCACHED_SUCCESS);
 +  }
 +
 +  /*
 +   * Don't do the following in your code. I am abusing the internal details
 +   * within the library, and this is not a supported interface.
 +   * This is to verify correct behavior in the library
 +   */
 +  memcached_result_st result_obj;
-     memcached_st *clone= memcached_clone(NULL, memc);
-     clone->hosts[host].port= 0;
++  for (uint32_t host= 0; host < clone->number_of_hosts; host++) 
 +  {
-       rc= memcached_mget_by_key(clone, key, 1, keys, len, 4);
++    memcached_st *new_clone= memcached_clone(NULL, memc);
++    new_clone->hosts[host].port= 0;
 +
 +    for (int x= 'a'; x <= 'z'; ++x)
 +    {
 +      char key[2]= { [0]= (char)x };
 +
-       memcached_result_st *results= memcached_result_create(clone, &result_obj);
++      rc= memcached_mget_by_key(new_clone, key, 1, keys, len, 4);
 +      assert(rc == MEMCACHED_SUCCESS);
 +
-       while ((results= memcached_fetch_result(clone, &result_obj, &rc)) != NULL)
++      memcached_result_st *results= memcached_result_create(new_clone, &result_obj);
 +      assert(results);
 +
 +      int hits= 0;
-     memcached_free(clone);
++      while ((results= memcached_fetch_result(new_clone, &result_obj, &rc)) != NULL)
 +      {
 +        hits++;
 +      }
 +      assert(hits == 4);
 +      memcached_result_free(&result_obj);
 +    }
 +
-   int hash= memcached_generate_hash(memc, keys[0], len[0]);
-   for (int x= 0; x < (repl + 1); ++x) {
++    memcached_free(new_clone);
 +  }
 +
 +  return TEST_SUCCESS;
 +}
 +
 +static test_return replication_delete_test(memcached_st *memc)
 +{
 +  memcached_return rc;
 +  memcached_st *clone= memcached_clone(NULL, memc);
 +  /* Delete the items from all of the servers except 1 */
 +  uint64_t repl= memcached_behavior_get(memc,
 +                                        MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS);
 +  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS, --repl);
 +
 +  char *keys[]= { "bubba", "key1", "key2", "key3" };
 +  size_t len[]= { 5, 4, 4, 4 };
 +
 +  for (int x=0; x< 4; ++x)
 +  {
 +    rc= memcached_delete_by_key(memc, keys[0], len[0], keys[x], len[x], 0);
 +    assert(rc == MEMCACHED_SUCCESS);
 +  }
 +
 +  /*
 +   * Don't do the following in your code. I am abusing the internal details
 +   * within the library, and this is not a supported interface.
 +   * This is to verify correct behavior in the library
 +   */
-   for (int host= 0; host < clone->number_of_hosts; ++host) 
++  uint32_t hash= memcached_generate_hash(memc, keys[0], len[0]);
++  for (uint32_t x= 0; x < (repl + 1); ++x) 
++  {
 +    clone->hosts[hash].port= 0;
 +    if (++hash == clone->number_of_hosts)
 +      hash= 0;
 +  }
 +
 +  memcached_result_st result_obj;
++  for (uint32_t host= 0; host < clone->number_of_hosts; ++host) 
 +  {
 +    for (int x= 'a'; x <= 'z'; ++x)
 +    {
 +      char key[2]= { [0]= (char)x };
 +
 +      rc= memcached_mget_by_key(clone, key, 1, keys, len, 4);
 +      assert(rc == MEMCACHED_SUCCESS);
 +
 +      memcached_result_st *results= memcached_result_create(clone, &result_obj);
 +      assert(results);
 +
 +      int hits= 0;
 +      while ((results= memcached_fetch_result(clone, &result_obj, &rc)) != NULL)
 +      {
 +        ++hits;
 +      }
 +      assert(hits == 4);
 +      memcached_result_free(&result_obj);
 +    }
 +  }
 +  memcached_free(clone);
 +
 +  return TEST_SUCCESS;
 +}
 +
  static void increment_request_id(uint16_t *id)
  {
    (*id)++;
@@@ -3747,7 -3562,6 +3756,7 @@@ static uint16_t *get_udp_request_ids(me
    uint16_t *ids= malloc(sizeof(uint16_t) * memc->number_of_hosts);
    assert(ids != NULL);
    unsigned int x;
 +
    for (x= 0; x < memc->number_of_hosts; x++)
      ids[x]= get_udp_datagram_request_id((struct udp_datagram_header_st *) memc->hosts[x].write_buffer);
  
@@@ -3759,7 -3573,6 +3768,7 @@@ static test_return post_udp_op_check(me
    unsigned int x;
    memcached_server_st *cur_server = memc->hosts;
    uint16_t *cur_req_ids = get_udp_request_ids(memc);
 +
    for (x= 0; x < memc->number_of_hosts; x++)
    {
      assert(cur_server[x].cursor_active == 0);
    }
    free(expected_req_ids);
    free(cur_req_ids);
 +
    return TEST_SUCCESS;
  }
  
@@@ -3789,7 -3601,6 +3798,7 @@@ static memcached_return init_udp(memcac
    memcpy(servers, memc->hosts, sizeof(memcached_server_st) * num_hosts);
    for (x= 0; x < num_hosts; x++)
      memcached_server_free(&memc->hosts[x]);
 +
    memc->number_of_hosts= 0;
    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_USE_UDP, 1);
    for (x= 0; x < num_hosts; x++)
      assert(memcached_server_add_udp(memc, servers[x].hostname, servers[x].port) == MEMCACHED_SUCCESS);
      assert(memc->hosts[x].write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH);
    }
 +
    return MEMCACHED_SUCCESS;
  }
  
@@@ -4445,14 -4255,6 +4454,14 @@@ test_st user_tests[] =
    {0, 0, 0}
  };
  
 +test_st replication_tests[]= {
 +  {"set", 1, replication_set_test },
 +  {"get", 0, replication_get_test },
 +  {"mget", 0, replication_mget_test },
 +  {"delete", 0, replication_delete_test },
 +  {0, 0, 0}
 +};
 +
  test_st generate_tests[] ={
    {"generate_pairs", 1, generate_pairs },
    {"generate_data", 1, generate_data },
@@@ -4557,7 -4359,6 +4566,7 @@@ collection_st collection[] =
    {"consistent_ketama", pre_behavior_ketama, 0, consistent_tests},
    {"consistent_ketama_weighted", pre_behavior_ketama_weighted, 0, consistent_weighted_tests},
    {"test_hashes", 0, 0, hash_tests},
 +  {"replication", pre_replication, 0, replication_tests},
    {0, 0, 0, 0}
  };