Mass rename to simplify names.
authorBrian Aker <brian@gir.tangent.org>
Wed, 16 Dec 2009 23:01:10 +0000 (15:01 -0800)
committerBrian Aker <brian@gir.tangent.org>
Wed, 16 Dec 2009 23:01:10 +0000 (15:01 -0800)
Do you know how many times I get annoyed on a daily basis that I can't use
tabs on the command line? Yeah... should have done this a while ago.

90 files changed:
libmemcached/Makefile.am
libmemcached/allocators.c [new file with mode: 0644]
libmemcached/analyze.c [new file with mode: 0644]
libmemcached/auto.c [new file with mode: 0644]
libmemcached/behavior.c [new file with mode: 0644]
libmemcached/behavior.h [new file with mode: 0644]
libmemcached/callback.c [new file with mode: 0644]
libmemcached/callback.h [new file with mode: 0644]
libmemcached/common.h
libmemcached/connect.c [new file with mode: 0644]
libmemcached/constants.h [new file with mode: 0644]
libmemcached/delete.c [new file with mode: 0644]
libmemcached/do.c [new file with mode: 0644]
libmemcached/dump.c [new file with mode: 0644]
libmemcached/fetch.c [new file with mode: 0644]
libmemcached/flush.c [new file with mode: 0644]
libmemcached/flush_buffers.c [new file with mode: 0644]
libmemcached/get.c [new file with mode: 0644]
libmemcached/get.h [new file with mode: 0644]
libmemcached/hash.c [new file with mode: 0644]
libmemcached/hosts.c [new file with mode: 0644]
libmemcached/internal.h [new file with mode: 0644]
libmemcached/io.c [new file with mode: 0644]
libmemcached/io.h [new file with mode: 0644]
libmemcached/key.c [new file with mode: 0644]
libmemcached/memcached.h
libmemcached/memcached_allocators.c [deleted file]
libmemcached/memcached_analyze.c [deleted file]
libmemcached/memcached_auto.c [deleted file]
libmemcached/memcached_behavior.c [deleted file]
libmemcached/memcached_behavior.h [deleted file]
libmemcached/memcached_callback.c [deleted file]
libmemcached/memcached_callback.h [deleted file]
libmemcached/memcached_connect.c [deleted file]
libmemcached/memcached_constants.h [deleted file]
libmemcached/memcached_delete.c [deleted file]
libmemcached/memcached_do.c [deleted file]
libmemcached/memcached_dump.c [deleted file]
libmemcached/memcached_fetch.c [deleted file]
libmemcached/memcached_flush.c [deleted file]
libmemcached/memcached_flush_buffers.c [deleted file]
libmemcached/memcached_get.c [deleted file]
libmemcached/memcached_get.h [deleted file]
libmemcached/memcached_hash.c [deleted file]
libmemcached/memcached_hosts.c [deleted file]
libmemcached/memcached_internal.h [deleted file]
libmemcached/memcached_io.c [deleted file]
libmemcached/memcached_io.h [deleted file]
libmemcached/memcached_key.c [deleted file]
libmemcached/memcached_parse.c [deleted file]
libmemcached/memcached_pool.h [deleted file]
libmemcached/memcached_purge.c [deleted file]
libmemcached/memcached_quit.c [deleted file]
libmemcached/memcached_response.c [deleted file]
libmemcached/memcached_result.c [deleted file]
libmemcached/memcached_result.h [deleted file]
libmemcached/memcached_server.c [deleted file]
libmemcached/memcached_server.h [deleted file]
libmemcached/memcached_stats.c [deleted file]
libmemcached/memcached_storage.c [deleted file]
libmemcached/memcached_storage.h [deleted file]
libmemcached/memcached_strerror.c [deleted file]
libmemcached/memcached_string.c [deleted file]
libmemcached/memcached_string.h [deleted file]
libmemcached/memcached_types.h [deleted file]
libmemcached/memcached_util.h
libmemcached/memcached_verbosity.c [deleted file]
libmemcached/memcached_version.c [deleted file]
libmemcached/memcached_watchpoint.h [deleted file]
libmemcached/parse.c [new file with mode: 0644]
libmemcached/pool.h [new file with mode: 0644]
libmemcached/purge.c [new file with mode: 0644]
libmemcached/quit.c [new file with mode: 0644]
libmemcached/response.c [new file with mode: 0644]
libmemcached/result.c [new file with mode: 0644]
libmemcached/result.h [new file with mode: 0644]
libmemcached/server.c [new file with mode: 0644]
libmemcached/server.h [new file with mode: 0644]
libmemcached/stats.c [new file with mode: 0644]
libmemcached/storage.c [new file with mode: 0644]
libmemcached/storage.h [new file with mode: 0644]
libmemcached/strerror.c [new file with mode: 0644]
libmemcached/string.c [new file with mode: 0644]
libmemcached/string.h [new file with mode: 0644]
libmemcached/types.h [new file with mode: 0644]
libmemcached/util/memcached_pool.c [deleted file]
libmemcached/util/pool.c [new file with mode: 0644]
libmemcached/verbosity.c [new file with mode: 0644]
libmemcached/version.c [new file with mode: 0644]
libmemcached/watchpoint.h [new file with mode: 0644]

index 80db35050fa0fc9c4dd37f5fd60633ee43c427a3..e85fecb770ec75862185148a71fe155979d6cfde 100644 (file)
@@ -1,91 +1,96 @@
-EXTRA_DIST = libmemcached.ver \
-             libmemcached_probes.d \
-             memcached/README.txt \
-             memcached_configure.h.in \
-             protocol/libmemcachedprotocol.ver \
-             util/libmemcachedutil.ver
+EXTRA_DIST = \
+           libmemcached.ver \
+           libmemcached_probes.d \
+           memcached/README.txt \
+           memcached_configure.h.in \
+           protocol/libmemcachedprotocol.ver \
+           util/libmemcachedutil.ver
 
 
 EXTRA_HEADERS =
 BUILT_SOURCES=
 
 noinst_HEADERS = libmemcached_probes.h \
-                 memcached_io.h \
-                 memcached_internal.h \
+                 io.h \
+                 internal.h \
                  common.h \
                  memcached/protocol_binary.h \
                  protocol/common.h \
                  protocol/ascii_handler.h \
                  protocol/binary_handler.h
 
-pkginclude_HEADERS= memcached.h \
-                   memcached.hpp \
+pkginclude_HEADERS= \
+                   behavior.h \
+                   callback.h \
+                   constants.h \
                    exception.hpp \
-                   memcached_behavior.h \
-                   memcached_callback.h \
-                    memcached_configure.h \
-                   memcached_constants.h \
-                   memcached_get.h \
-                   memcached_result.h \
-                   memcached_server.h \
-                   memcached_storage.h \
-                   memcached_string.h \
-                   memcached_types.h \
-                   memcached_watchpoint.h \
-                    protocol_handler.h \
-                   visibility.h
-
-nobase_pkginclude_HEADERS=protocol/cache.h \
-                          protocol/callback.h
-
-
-libmemcachedprotocol_la_SOURCES= protocol/ascii_handler.c \
-                                 protocol/binary_handler.c \
-                                 protocol/cache.c \
-                                 protocol/pedantic.c \
-                                 protocol/protocol_handler.c
+                   get.h \
+                   memcached.h \
+                   memcached.hpp \
+                   memcached_configure.h \
+                   protocol_handler.h \
+                   result.h \
+                   server.h \
+                   storage.h \
+                   string.h \
+                   types.h \
+                   visibility.h \
+                   watchpoint.h
+
+nobase_pkginclude_HEADERS = \
+                           protocol/cache.h \
+                           protocol/callback.h
+
+
+libmemcachedprotocol_la_SOURCES =  \
+                                   protocol/ascii_handler.c \
+                                   protocol/binary_handler.c \
+                                   protocol/cache.c \
+                                   protocol/pedantic.c \
+                                   protocol/protocol_handler.c
 
 libmemcachedprotocol_la_LDFLAGS= ${AM_LDFLAGS} -version-info 0:0:0 
 
 lib_LTLIBRARIES = libmemcached.la libmemcachedprotocol.la
 noinst_LTLIBRARIES = libmemcachedcallbacks.la
 libmemcachedcallbacks_la_CFLAGS = ${AM_CFLAGS} ${NO_STRICT_ALIASING}
-libmemcachedcallbacks_la_SOURCES = memcached_callback.c
+libmemcachedcallbacks_la_SOURCES = callback.c
 
 libmemcached_la_CFLAGS= ${AM_CFLAGS} ${NO_CONVERSION}
-libmemcached_la_SOURCES = crc.c \
-                         memcached.c \
-                         memcached_auto.c \
-                         memcached_analyze.c \
-                         memcached_behavior.c \
-                         memcached_connect.c \
-                         memcached_delete.c \
-                         memcached_do.c \
-                         memcached_dump.c \
-                         memcached_fetch.c \
-                         memcached_flush.c \
-                         memcached_get.c \
-                         memcached_hash.c \
-                         memcached_hosts.c \
-                         memcached_io.c \
-                         memcached_purge.c \
-                          memcached_flush_buffers.c \
+libmemcached_la_SOURCES = \
+                         allocators.c \
+                         analyze.c \
+                         auto.c \
+                         behavior.c \
+                         connect.c \
+                         crc.c \
+                         delete.c \
+                         do.c \
+                         dump.c \
+                         fetch.c \
+                         flush.c \
+                         flush_buffers.c \
+                         get.c \
+                         hash.c \
+                         hosts.c \
+                         io.c \
+                         jenkins_hash.c \
+                         key.c \
                          md5.c \
-                         memcached_key.c \
-                         memcached_quit.c \
-                         memcached_parse.c \
-                         memcached_response.c \
-                         memcached_result.c \
-                         memcached_server.c \
-                         memcached_storage.c \
-                         memcached_string.c \
-                         memcached_stats.c \
-                         memcached_strerror.c \
-                         memcached_verbosity.c \
-                         memcached_version.c \
+                         memcached.c \
                          murmur_hash.c \
-                         jenkins_hash.c \
-                          memcached_allocators.c
+                         parse.c \
+                         purge.c \
+                         quit.c \
+                         response.c \
+                         result.c \
+                         server.c \
+                         stats.c \
+                         storage.c \
+                         strerror.c \
+                         string.c \
+                         verbosity.c \
+                         version.c
 
 
 if INCLUDE_HSIEH_SRC
@@ -97,11 +102,11 @@ libmemcached_la_LIBADD= $(LIBM) libmemcachedcallbacks.la
 libmemcached_la_LDFLAGS= ${AM_LDFLAGS} -version-info 3:0:0
 
 if BUILD_LIBMEMCACHEDUTIL
-pkginclude_HEADERS+= memcached_util.h memcached_pool.h
+pkginclude_HEADERS+= memcached_util.h pool.h
 lib_LTLIBRARIES+= libmemcachedutil.la
 endif
 
-libmemcachedutil_la_SOURCES= util/memcached_pool.c
+libmemcachedutil_la_SOURCES= util/pool.c
 libmemcachedutil_la_LIBADD= libmemcached.la
 libmemcachedutil_la_LDFLAGS= ${AM_LDFLAGS} -version-info 0:0:0
 libmemcachedutil_la_DEPENDENCIES=libmemcached.la
diff --git a/libmemcached/allocators.c b/libmemcached/allocators.c
new file mode 100644 (file)
index 0000000..767371c
--- /dev/null
@@ -0,0 +1,72 @@
+#include "common.h"
+
+void libmemcached_free(memcached_st *ptr, void *mem)
+{
+  (void) ptr;
+  free(mem);
+}
+
+void *libmemcached_malloc(memcached_st *ptr, size_t size)
+{
+  (void) ptr;
+  return malloc(size);
+}
+
+void *libmemcached_realloc(memcached_st *ptr, void *mem, size_t size)
+{
+  (void) ptr;
+  return realloc(mem, size);
+}
+
+void *libmemcached_calloc(memcached_st *ptr, size_t nelem, size_t size)
+{
+  if (ptr->call_malloc != libmemcached_malloc)
+  {
+     void *ret = libmemcached_malloc(ptr, nelem * size);
+     if (ret != NULL) 
+       memset(ret, 0, nelem * size);
+
+     return ret;
+  }
+
+  return calloc(nelem, size);
+}
+
+memcached_return_t memcached_set_memory_allocators(memcached_st *ptr,
+                                                   memcached_malloc_fn mem_malloc,
+                                                   memcached_free_fn mem_free,
+                                                   memcached_realloc_fn mem_realloc,
+                                                   memcached_calloc_fn mem_calloc)
+{
+  /* All should be set, or none should be set */
+  if (mem_malloc == NULL && mem_free == NULL && mem_realloc == NULL && mem_calloc == NULL) 
+  {
+    ptr->call_malloc= libmemcached_malloc;
+    ptr->call_free= libmemcached_free;
+    ptr->call_realloc= libmemcached_realloc;
+    ptr->call_calloc= libmemcached_calloc;
+  }
+  else if (mem_malloc == NULL || mem_free == NULL || mem_realloc == NULL || mem_calloc == NULL)
+    return MEMCACHED_FAILURE;
+  else
+  {
+    ptr->call_malloc= mem_malloc;
+    ptr->call_free= mem_free;
+    ptr->call_realloc= mem_realloc;
+    ptr->call_calloc= mem_calloc;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+void memcached_get_memory_allocators(memcached_st *ptr,
+                                     memcached_malloc_fn *mem_malloc,
+                                     memcached_free_fn *mem_free,
+                                     memcached_realloc_fn *mem_realloc,
+                                     memcached_calloc_fn *mem_calloc)
+{
+   *mem_malloc= ptr->call_malloc;
+   *mem_free= ptr->call_free;
+   *mem_realloc= ptr->call_realloc;
+   *mem_calloc= ptr->call_calloc;
+}
diff --git a/libmemcached/analyze.c b/libmemcached/analyze.c
new file mode 100644 (file)
index 0000000..5c1c7e4
--- /dev/null
@@ -0,0 +1,100 @@
+#include "common.h"
+
+static void calc_largest_consumption(memcached_analysis_st *result,
+                                     const uint32_t server_num,
+                                     const uint64_t nbytes)
+{
+  if (result->most_used_bytes < nbytes)
+  {
+    result->most_used_bytes= nbytes;
+    result->most_consumed_server= server_num;
+  }
+}
+
+static void calc_oldest_node(memcached_analysis_st *result,
+                                     const uint32_t server_num,
+                                     const uint32_t uptime)
+{
+  if (result->longest_uptime < uptime)
+  {
+    result->longest_uptime= uptime;
+    result->oldest_server= server_num;
+  }
+}
+
+static void calc_least_free_node(memcached_analysis_st *result,
+                                 const uint32_t server_num,
+                                 const uint64_t max_allowed_bytes,
+                                 const uint64_t used_bytes)
+{
+  uint64_t remaining_bytes= max_allowed_bytes - used_bytes;
+
+  if (result->least_remaining_bytes == 0 ||
+      remaining_bytes < result->least_remaining_bytes)
+  {
+    result->least_remaining_bytes= remaining_bytes;
+    result->least_free_server= server_num;
+  }
+}
+
+static void calc_average_item_size(memcached_analysis_st *result,
+                                   const uint64_t total_items,
+                                   const uint64_t total_bytes)
+{
+  if (total_items > 0 && total_bytes > 0)
+    result->average_item_size= (uint32_t) (total_bytes / total_items);
+}
+
+static void calc_hit_ratio(memcached_analysis_st *result,
+                           const uint64_t total_get_hits,
+                           const uint64_t total_get_cmds)
+{
+  if (total_get_hits == 0 || total_get_cmds == 0)
+  {
+    result->pool_hit_ratio= 0;
+    return;
+  }
+
+  double temp= (double) (total_get_hits/total_get_cmds);
+  result->pool_hit_ratio= temp * 100;
+}
+
+memcached_analysis_st *memcached_analyze(memcached_st *memc,
+                                         memcached_stat_st *memc_stat,
+                                         memcached_return_t *error)
+{
+  uint64_t total_items= 0, total_bytes= 0;
+  uint64_t total_get_cmds= 0, total_get_hits= 0;
+  uint32_t server_count, x;
+  memcached_analysis_st *result;
+  
+  *error= MEMCACHED_SUCCESS;
+  server_count= memcached_server_count(memc);
+  result= (memcached_analysis_st*)calloc(memc->number_of_hosts,
+                                         sizeof(memcached_analysis_st));
+
+  if (!result)
+  {
+    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return NULL;
+  }
+
+  for (x= 0; x < server_count; x++)
+  {
+    calc_largest_consumption(result, x, memc_stat[x].bytes);
+    calc_oldest_node(result, x, memc_stat[x].uptime);
+    calc_least_free_node(result, x,
+                         memc_stat[x].limit_maxbytes, 
+                         memc_stat[x].bytes);
+
+    total_get_hits+= memc_stat[x].get_hits;
+    total_get_cmds+= memc_stat[x].cmd_get;
+    total_items+= memc_stat[x].curr_items;
+    total_bytes+= memc_stat[x].bytes;
+  }
+
+  calc_average_item_size(result, total_items, total_bytes);
+  calc_hit_ratio(result, total_get_hits, total_get_cmds);
+
+  return result;
+}
diff --git a/libmemcached/auto.c b/libmemcached/auto.c
new file mode 100644 (file)
index 0000000..b746640
--- /dev/null
@@ -0,0 +1,275 @@
+/* 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: Methods for adding or decrementing values from an object in memcached
+ *
+ */
+
+#include "common.h"
+
+static memcached_return_t memcached_auto(memcached_st *ptr,
+                                         const char *verb,
+                                         const char *master_key, size_t master_key_length,
+                                         const char *key, size_t key_length,
+                                         uint64_t offset,
+                                         uint64_t *value)
+{
+  size_t send_length;
+  memcached_return_t rc;
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+  unsigned int server_key;
+  bool no_reply= ptr->flags.no_reply;
+
+  unlikely (ptr->hosts == NULL || ptr->number_of_hosts == 0)
+    return MEMCACHED_NO_SERVERS;
+
+  if (ptr->flags.verify_key && (memcached_key_test((const 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);
+
+  send_length= (size_t)snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
+                                "%s %s%.*s %" PRIu64 "%s\r\n", verb,
+                                ptr->prefix_key,
+                                (int)key_length, key,
+                                offset, no_reply ? " noreply" : "");
+  unlikely (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
+    return MEMCACHED_WRITE_FAILURE;
+
+  rc= memcached_do(&ptr->hosts[server_key], buffer, send_length, 1);
+  if (no_reply || rc != MEMCACHED_SUCCESS)
+    return rc;
+
+  rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+
+  /*
+    So why recheck responce? Because the protocol is brain dead :)
+    The number returned might end up equaling one of the string
+    values. Less chance of a mistake with strncmp() so we will
+    use it. We still called memcached_response() though since it
+    worked its magic for non-blocking IO.
+  */
+  if (!strncmp(buffer, "ERROR\r\n", 7))
+  {
+    *value= 0;
+    rc= MEMCACHED_PROTOCOL_ERROR;
+  }
+  else if (!strncmp(buffer, "NOT_FOUND\r\n", 11))
+  {
+    *value= 0;
+    rc= MEMCACHED_NOTFOUND;
+  }
+  else
+  {
+    *value= strtoull(buffer, (char **)NULL, 10);
+    rc= MEMCACHED_SUCCESS;
+  }
+
+  return rc;
+}
+
+static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd,
+                                           const char *master_key, size_t master_key_length,
+                                           const char *key, size_t key_length,
+                                           uint64_t offset, uint64_t initial,
+                                           uint32_t expiration,
+                                           uint64_t *value)
+{
+  unsigned int server_key;
+  bool no_reply= ptr->flags.no_reply;
+
+  unlikely (ptr->hosts == NULL || ptr->number_of_hosts == 0)
+    return MEMCACHED_NO_SERVERS;
+
+  server_key= memcached_generate_hash(ptr, master_key, master_key_length);
+
+  if (no_reply)
+  {
+    if(cmd == PROTOCOL_BINARY_CMD_DECREMENT)
+      cmd= PROTOCOL_BINARY_CMD_DECREMENTQ;
+    if(cmd == PROTOCOL_BINARY_CMD_INCREMENT)
+      cmd= PROTOCOL_BINARY_CMD_INCREMENTQ;
+  }
+  protocol_binary_request_incr request= {.bytes= {0}};
+
+  request.message.header.request.magic= PROTOCOL_BINARY_REQ;
+  request.message.header.request.opcode= cmd;
+  request.message.header.request.keylen= htons((uint16_t) key_length);
+  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 + request.message.header.request.extlen));
+  request.message.body.delta= htonll(offset);
+  request.message.body.initial= htonll(initial);
+  request.message.body.expiration= htonl((uint32_t) expiration);
+
+  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, 1) == -1))
+  {
+    memcached_io_reset(&ptr->hosts[server_key]);
+    return MEMCACHED_WRITE_FAILURE;
+  }
+
+  if (no_reply)
+    return MEMCACHED_SUCCESS;
+  return memcached_response(&ptr->hosts[server_key], (char*)value, sizeof(*value), NULL);
+}
+
+memcached_return_t memcached_increment(memcached_st *ptr,
+                                       const char *key, size_t key_length,
+                                       uint32_t offset,
+                                       uint64_t *value)
+{
+  return memcached_increment_by_key(ptr, key, key_length, key, key_length, offset, value);
+}
+
+memcached_return_t memcached_decrement(memcached_st *ptr,
+                                       const char *key, size_t key_length,
+                                       uint32_t offset,
+                                       uint64_t *value)
+{
+  return memcached_decrement_by_key(ptr, key, key_length, key, key_length, offset, value);
+}
+
+memcached_return_t memcached_increment_by_key(memcached_st *ptr,
+                                              const char *master_key, size_t master_key_length,
+                                              const char *key, size_t key_length,
+                                              uint64_t offset,
+                                              uint64_t *value)
+{
+  memcached_return_t rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol);
+  unlikely (rc != MEMCACHED_SUCCESS)
+    return rc;
+
+  LIBMEMCACHED_MEMCACHED_INCREMENT_START();
+  if (ptr->flags.binary_protocol)
+  {
+    rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
+                         master_key, master_key_length, key, key_length,
+                         (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
+                         value);
+  }
+  else
+  {
+     rc= memcached_auto(ptr, "incr", master_key, master_key_length, key, key_length, offset, value);
+  }
+
+  LIBMEMCACHED_MEMCACHED_INCREMENT_END();
+
+  return rc;
+}
+
+memcached_return_t memcached_decrement_by_key(memcached_st *ptr,
+                                              const char *master_key, size_t master_key_length,
+                                              const char *key, size_t key_length,
+                                              uint64_t offset,
+                                              uint64_t *value)
+{
+  memcached_return_t rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol);
+  unlikely (rc != MEMCACHED_SUCCESS)
+    return rc;
+
+  LIBMEMCACHED_MEMCACHED_DECREMENT_START();
+  if (ptr->flags.binary_protocol)
+    rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT,
+                         master_key, master_key_length, key, key_length,
+                         (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
+                         value);
+  else
+    rc= memcached_auto(ptr, "decr", master_key, master_key_length, key, key_length, offset, value);
+
+  LIBMEMCACHED_MEMCACHED_DECREMENT_END();
+
+  return rc;
+}
+
+memcached_return_t memcached_increment_with_initial(memcached_st *ptr,
+                                                    const char *key,
+                                                    size_t key_length,
+                                                    uint64_t offset,
+                                                    uint64_t initial,
+                                                    time_t expiration,
+                                                    uint64_t *value)
+{
+  return memcached_increment_with_initial_by_key(ptr, key, key_length,
+                                                 key, key_length,
+                                                 offset, initial, expiration, value);
+}
+
+memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr,
+                                                         const char *master_key,
+                                                         size_t master_key_length,
+                                                         const char *key,
+                                                         size_t key_length,
+                                                         uint64_t offset,
+                                                         uint64_t initial,
+                                                         time_t expiration,
+                                                         uint64_t *value)
+{
+  memcached_return_t rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol);
+  unlikely (rc != MEMCACHED_SUCCESS)
+    return rc;
+
+  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
+  if (ptr->flags.binary_protocol)
+    rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
+                         master_key, master_key_length, key, key_length,
+                         offset, initial, (uint32_t)expiration,
+                         value);
+  else
+    rc= MEMCACHED_PROTOCOL_ERROR;
+
+  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
+
+  return rc;
+}
+
+memcached_return_t memcached_decrement_with_initial(memcached_st *ptr,
+                                                    const char *key,
+                                                    size_t key_length,
+                                                    uint64_t offset,
+                                                    uint64_t initial,
+                                                    time_t expiration,
+                                                    uint64_t *value)
+{
+  return memcached_decrement_with_initial_by_key(ptr, key, key_length,
+                                                 key, key_length,
+                                                 offset, initial, expiration, value);
+}
+
+memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr,
+                                                           const char *master_key,
+                                                           size_t master_key_length,
+                                                           const char *key,
+                                                           size_t key_length,
+                                                           uint64_t offset,
+                                                           uint64_t initial,
+                                                           time_t expiration,
+                                                           uint64_t *value)
+{
+  memcached_return_t rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol);
+  unlikely (rc != MEMCACHED_SUCCESS)
+    return rc;
+
+  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
+  if (ptr->flags.binary_protocol)
+  {
+    rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT,
+                         master_key, master_key_length, key, key_length,
+                         offset, initial, (uint32_t)expiration,
+                         value);
+  }
+  else
+  {
+    rc= MEMCACHED_PROTOCOL_ERROR;
+  }
+
+  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
+
+  return rc;
+}
+
diff --git a/libmemcached/behavior.c b/libmemcached/behavior.c
new file mode 100644 (file)
index 0000000..37c9f52
--- /dev/null
@@ -0,0 +1,314 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Change the behavior of the memcached connection.
+ *
+ */
+
+#include "common.h"
+#include <time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/tcp.h>
+
+/*
+  This function is used to modify the behavior of running client.
+
+  We quit all connections so we can reset the sockets.
+*/
+
+memcached_return_t memcached_behavior_set(memcached_st *ptr,
+                                          memcached_behavior_t flag,
+                                          uint64_t data)
+{
+  switch (flag)
+  {
+  case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
+    ptr->number_of_replicas= (uint32_t)data;
+    break;
+  case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK:
+    ptr->io_msg_watermark= (uint32_t) data;
+    break;
+  case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK:
+    ptr->io_bytes_watermark= (uint32_t)data;
+    break;
+  case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH:
+    ptr->io_key_prefetch = (uint32_t)data;
+    break;
+  case MEMCACHED_BEHAVIOR_SND_TIMEOUT:
+    ptr->snd_timeout= (int32_t)data;
+    break;
+  case MEMCACHED_BEHAVIOR_RCV_TIMEOUT:
+    ptr->rcv_timeout= (int32_t)data;
+    break;
+  case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
+    ptr->server_failure_limit= (uint32_t)data;
+    break;
+  case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL:
+    if (data)
+        ptr->flags.verify_key= false;
+
+    ptr->flags.binary_protocol= data ? true : false;
+    break;
+  case MEMCACHED_BEHAVIOR_SUPPORT_CAS:
+    ptr->flags.support_cas= data ? true: false;
+    break;
+  case MEMCACHED_BEHAVIOR_NO_BLOCK:
+    ptr->flags.no_block= data ? true: false;
+    memcached_quit(ptr);
+    break;
+  case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS:
+    ptr->flags.buffer_requests= data ? true : false;
+    memcached_quit(ptr);
+    break;
+  case MEMCACHED_BEHAVIOR_USE_UDP:
+    if (ptr->number_of_hosts)
+      return MEMCACHED_FAILURE;
+    ptr->flags.use_udp= data ? true : false;
+
+    if (data)
+      ptr->flags.no_reply= data ? true : false;
+    break;
+
+  case MEMCACHED_BEHAVIOR_TCP_NODELAY:
+    ptr->flags.tcp_nodelay= data ? true : false;
+    memcached_quit(ptr);
+    break;
+  case MEMCACHED_BEHAVIOR_DISTRIBUTION:
+    {
+      ptr->distribution= (memcached_server_distribution_t)(data);
+      if (ptr->distribution == MEMCACHED_DISTRIBUTION_RANDOM)
+      {
+        srandom((uint32_t) time(NULL));
+      }
+      run_distribution(ptr);
+      break;
+    }
+  case MEMCACHED_BEHAVIOR_KETAMA:
+    {
+      if (data)
+      {
+        ptr->hash= MEMCACHED_HASH_MD5;
+        ptr->distribution= MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA;
+      }
+      else
+      {
+        ptr->hash= 0;
+        ptr->distribution= 0;
+      }
+      run_distribution(ptr);
+      break;
+    }
+  case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED:
+    {
+      ptr->hash= MEMCACHED_HASH_MD5;
+      ptr->distribution= MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA;
+      ptr->flags.ketama_weighted= data ? true : false;
+      run_distribution(ptr);
+      break;
+    }
+  case MEMCACHED_BEHAVIOR_KETAMA_COMPAT_MODE:
+    switch (data)
+    {
+    case MEMCACHED_KETAMA_COMPAT_LIBMEMCACHED:
+      ptr->hash= MEMCACHED_HASH_MD5;
+      ptr->distribution= MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA;
+      break;
+    case MEMCACHED_KETAMA_COMPAT_SPY:
+      ptr->hash= MEMCACHED_HASH_MD5;
+      ptr->distribution= MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY;
+      break;
+    default:
+       return MEMCACHED_FAILURE;
+    }
+    run_distribution(ptr);
+    break;
+  case MEMCACHED_BEHAVIOR_HASH:
+#ifndef HAVE_HSIEH_HASH
+    if ((memcached_hash_t)(data) == MEMCACHED_HASH_HSIEH)
+      return MEMCACHED_FAILURE;
+#endif
+    ptr->hash= (memcached_hash_t)(data);
+    break;
+  case MEMCACHED_BEHAVIOR_KETAMA_HASH:
+    ptr->hash_continuum= (memcached_hash_t)(data);
+    run_distribution(ptr);
+    break;
+  case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS:
+    ptr->flags.use_cache_lookups= data ? true : false;
+    memcached_quit(ptr);
+    break;
+  case MEMCACHED_BEHAVIOR_VERIFY_KEY:
+    if (ptr->flags.binary_protocol)
+        break;
+    ptr->flags.verify_key= data ? true : false;
+    break;
+  case MEMCACHED_BEHAVIOR_SORT_HOSTS:
+    {
+      ptr->flags.use_sort_hosts= data ? true : false;
+      run_distribution(ptr);
+
+      break;
+    }
+  case MEMCACHED_BEHAVIOR_POLL_TIMEOUT:
+    ptr->poll_timeout= (int32_t)data;
+    break;
+  case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT:
+    ptr->connect_timeout= (int32_t)data;
+    break;
+  case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT:
+    ptr->retry_timeout= (int32_t)data;
+    break;
+  case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE:
+    ptr->send_size= (int32_t)data;
+    memcached_quit(ptr);
+    break;
+  case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE:
+    ptr->recv_size= (int32_t)data;
+    memcached_quit(ptr);
+    break;
+  case MEMCACHED_BEHAVIOR_USER_DATA:
+    return MEMCACHED_FAILURE;
+  case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY:
+    ptr->flags.hash_with_prefix_key= data ? true : false;
+    break;
+  case MEMCACHED_BEHAVIOR_NOREPLY:
+    ptr->flags.no_reply= data ? true : false;
+    break;
+  case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
+    ptr->flags.auto_eject_hosts= data ? true : false;
+    break;
+  case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ:
+      srandom((uint32_t) time(NULL));
+      ptr->flags.randomize_replica_read= data ? true : false;
+      break;
+  default:
+    /* Shouldn't get here */
+    WATCHPOINT_ASSERT(flag);
+    break;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+uint64_t memcached_behavior_get(memcached_st *ptr,
+                                memcached_behavior_t flag)
+{
+  switch (flag)
+  {
+  case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
+    return ptr->number_of_replicas;
+  case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK:
+    return ptr->io_msg_watermark;
+  case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK:
+    return ptr->io_bytes_watermark;
+  case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH:
+    return ptr->io_key_prefetch;
+  case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL:
+    return ptr->flags.binary_protocol;
+  case MEMCACHED_BEHAVIOR_SUPPORT_CAS:
+    return ptr->flags.support_cas;
+  case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS:
+    return ptr->flags.use_cache_lookups;
+  case MEMCACHED_BEHAVIOR_NO_BLOCK:
+    return ptr->flags.no_block;
+  case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS:
+    return ptr->flags.buffer_requests;
+  case MEMCACHED_BEHAVIOR_USE_UDP:
+    return ptr->flags.use_udp;
+  case MEMCACHED_BEHAVIOR_TCP_NODELAY:
+    return ptr->flags.tcp_nodelay;
+  case MEMCACHED_BEHAVIOR_VERIFY_KEY:
+    return ptr->flags.verify_key;
+  case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED:
+    return ptr->flags.ketama_weighted;
+  case MEMCACHED_BEHAVIOR_DISTRIBUTION:
+    return ptr->distribution;
+  case MEMCACHED_BEHAVIOR_KETAMA:
+    return (ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA) ? (uint64_t) 1 : 0;
+  case MEMCACHED_BEHAVIOR_KETAMA_COMPAT_MODE:
+    switch (ptr->distribution)
+    {
+    case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
+      return MEMCACHED_KETAMA_COMPAT_LIBMEMCACHED;
+    case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
+      return MEMCACHED_KETAMA_COMPAT_SPY;
+    case MEMCACHED_DISTRIBUTION_MODULA:
+    case MEMCACHED_DISTRIBUTION_CONSISTENT:
+    case MEMCACHED_DISTRIBUTION_RANDOM:
+    default:
+      return (uint64_t)-1;
+    }
+    /* NOTREACHED */
+  case MEMCACHED_BEHAVIOR_HASH:
+    return ptr->hash;
+  case MEMCACHED_BEHAVIOR_KETAMA_HASH:
+    return ptr->hash_continuum;
+  case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
+    return ptr->server_failure_limit;
+  case MEMCACHED_BEHAVIOR_SORT_HOSTS:
+    return ptr->flags.use_sort_hosts;
+  case MEMCACHED_BEHAVIOR_POLL_TIMEOUT:
+    return (uint64_t)ptr->poll_timeout;
+  case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT:
+    return (uint64_t)ptr->connect_timeout;
+  case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT:
+    return (uint64_t)ptr->retry_timeout;
+  case MEMCACHED_BEHAVIOR_SND_TIMEOUT:
+    return (uint64_t)ptr->snd_timeout;
+  case MEMCACHED_BEHAVIOR_RCV_TIMEOUT:
+    return (uint64_t)ptr->rcv_timeout;
+  case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE:
+    {
+      int sock_size;
+      socklen_t sock_length= sizeof(int);
+
+      /* REFACTOR */
+      /* We just try the first host, and if it is down we return zero */
+      if ((memcached_connect(&ptr->hosts[0])) != MEMCACHED_SUCCESS)
+        return 0;
+
+      if (getsockopt(ptr->hosts[0].fd, SOL_SOCKET,
+                     SO_SNDBUF, &sock_size, &sock_length))
+        return 0; /* Zero means error */
+
+      return (uint64_t) sock_size;
+    }
+  case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE:
+    {
+      int sock_size;
+      socklen_t sock_length= sizeof(int);
+
+      /* REFACTOR */
+      /* We just try the first host, and if it is down we return zero */
+      if ((memcached_connect(&ptr->hosts[0])) != MEMCACHED_SUCCESS)
+        return 0;
+
+      if (getsockopt(ptr->hosts[0].fd, SOL_SOCKET,
+                     SO_RCVBUF, &sock_size, &sock_length))
+        return 0; /* Zero means error */
+
+      return (uint64_t) sock_size;
+    }
+  case MEMCACHED_BEHAVIOR_USER_DATA:
+    return MEMCACHED_FAILURE;
+  case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY:
+    return ptr->flags.hash_with_prefix_key;
+  case MEMCACHED_BEHAVIOR_NOREPLY:
+    return ptr->flags.no_reply;
+  case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
+    return ptr->flags.auto_eject_hosts;
+  case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ:
+    return ptr->flags.randomize_replica_read;
+  default:
+    WATCHPOINT_ASSERT(flag);
+    break;
+  }
+
+  WATCHPOINT_ASSERT(0); /* Programming mistake if it gets this far */
+  return 0;
+}
diff --git a/libmemcached/behavior.h b/libmemcached/behavior.h
new file mode 100644 (file)
index 0000000..14cbc3a
--- /dev/null
@@ -0,0 +1,30 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Change the behavior of the memcached connection.
+ *
+ */
+
+#ifndef __MEMCACHED_BEHAVIOR_H__
+#define __MEMCACHED_BEHAVIOR_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_behavior_set(memcached_st *ptr, memcached_behavior_t flag, uint64_t data);
+
+LIBMEMCACHED_API
+uint64_t memcached_behavior_get(memcached_st *ptr, memcached_behavior_t flag);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MEMCACHED_BEHAVIOR_H__ */
diff --git a/libmemcached/callback.c b/libmemcached/callback.c
new file mode 100644 (file)
index 0000000..b0ddfc2
--- /dev/null
@@ -0,0 +1,186 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Change any of the possible callbacks.
+ *
+ */
+
+#include "common.h" 
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/tcp.h>
+
+/* 
+  These functions provide data and function callback support
+*/
+
+memcached_return_t memcached_callback_set(memcached_st *ptr, 
+                                          memcached_callback_t flag, 
+                                          void *data)
+{
+  switch (flag)
+  {
+  case MEMCACHED_CALLBACK_PREFIX_KEY:
+    {
+      char *key= (char *)data;
+
+      if (key)
+      {
+        size_t key_length= strlen(key);
+
+        if (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)
+        {
+          return MEMCACHED_BAD_KEY_PROVIDED;
+        }
+
+        if ((key_length > MEMCACHED_PREFIX_KEY_MAX_SIZE -1)
+            || (strcpy(ptr->prefix_key, key) == NULL))
+        {
+          ptr->prefix_key_length= 0;
+          return MEMCACHED_BAD_KEY_PROVIDED;
+        }
+        else
+        {
+          ptr->prefix_key_length= key_length;
+        }
+      }
+      else
+      {
+        memset(ptr->prefix_key, 0, MEMCACHED_PREFIX_KEY_MAX_SIZE);
+        ptr->prefix_key_length= 0;
+      }
+
+      break;
+    }
+  case MEMCACHED_CALLBACK_USER_DATA:
+    {
+      ptr->user_data= data;
+      break;
+    }
+  case MEMCACHED_CALLBACK_CLEANUP_FUNCTION:
+    {
+      memcached_cleanup_fn func= *(memcached_cleanup_fn *)&data;
+      ptr->on_cleanup= func;
+      break;
+    }
+  case MEMCACHED_CALLBACK_CLONE_FUNCTION:
+    {
+      memcached_clone_fn func= *(memcached_clone_fn *)&data;
+      ptr->on_clone= func;
+      break;
+    }
+#ifdef MEMCACHED_ENABLE_DEPRECATED
+  case MEMCACHED_CALLBACK_MALLOC_FUNCTION:
+    {
+      memcached_malloc_function func= *(memcached_malloc_fn *)&data;
+      ptr->call_malloc= func;
+      break;
+    }
+  case MEMCACHED_CALLBACK_REALLOC_FUNCTION:
+    {
+      memcached_realloc_function func= *(memcached_realloc_fn *)&data;
+      ptr->call_realloc= func;
+      break;
+    }
+  case MEMCACHED_CALLBACK_FREE_FUNCTION:
+    {
+      memcached_free_function func= *(memcached_free_fn *)&data;
+      ptr->call_free= func;
+      break;
+    }
+#endif
+  case MEMCACHED_CALLBACK_GET_FAILURE:
+    {
+      memcached_trigger_key_fn func= *(memcached_trigger_key_fn *)&data;
+      ptr->get_key_failure= func;
+      break;
+    }
+  case MEMCACHED_CALLBACK_DELETE_TRIGGER:
+    {
+      memcached_trigger_delete_key_fn func= *(memcached_trigger_delete_key_fn *)&data;
+      ptr->delete_trigger= func;
+      break;
+    }
+  default:
+    return MEMCACHED_FAILURE;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+void *memcached_callback_get(memcached_st *ptr, 
+                             memcached_callback_t flag,
+                             memcached_return_t *error)
+{
+  memcached_return_t local_error;
+
+  if (!error)
+    error = &local_error;
+
+  switch (flag)
+  {
+  case MEMCACHED_CALLBACK_PREFIX_KEY:
+    {
+      if (ptr->prefix_key[0] == 0)
+      {
+        *error= MEMCACHED_FAILURE;
+        return NULL;
+      }
+      else
+      {
+        *error= MEMCACHED_SUCCESS;
+        return (void *)ptr->prefix_key;
+      }
+    }
+  case MEMCACHED_CALLBACK_USER_DATA:
+    {
+      *error= ptr->user_data ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+      return (void *)ptr->user_data;
+    }
+  case MEMCACHED_CALLBACK_CLEANUP_FUNCTION:
+    {
+      *error= ptr->on_cleanup ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+      return *(void **)&ptr->on_cleanup;
+    }
+  case MEMCACHED_CALLBACK_CLONE_FUNCTION:
+    {
+      *error= ptr->on_clone ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+      return *(void **)&ptr->on_clone;
+    }
+#ifdef MEMCACHED_ENABLE_DEPRECATED
+  case MEMCACHED_CALLBACK_MALLOC_FUNCTION:
+    {
+      *error= ptr->call_malloc ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+      return *(void **)&ptr->call_malloc;
+    }
+  case MEMCACHED_CALLBACK_REALLOC_FUNCTION:
+    {
+      *error= ptr->call_realloc ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+      return *(void **)&ptr->call_realloc;
+    }
+  case MEMCACHED_CALLBACK_FREE_FUNCTION:
+    {
+      *error= ptr->call_free ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+      return *(void **)&ptr->call_free;
+    }
+#endif
+  case MEMCACHED_CALLBACK_GET_FAILURE:
+    {
+      *error= ptr->get_key_failure ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+      return *(void **)&ptr->get_key_failure;
+    }
+  case MEMCACHED_CALLBACK_DELETE_TRIGGER:
+    {
+      *error= ptr->delete_trigger ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
+      return *(void **)&ptr->delete_trigger;
+    }
+  default:
+    WATCHPOINT_ASSERT(0);
+    *error= MEMCACHED_FAILURE;
+    return NULL;
+  }
+}
diff --git a/libmemcached/callback.h b/libmemcached/callback.h
new file mode 100644 (file)
index 0000000..0719a66
--- /dev/null
@@ -0,0 +1,32 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Change any of the possible callbacks.
+ *
+ */
+
+#ifndef __MEMCACHED_CALLBACK_H__
+#define __MEMCACHED_CALLBACK_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_API
+memcached_return_t memcached_callback_set(memcached_st *ptr,
+                                          memcached_callback_t flag,
+                                          void *data);
+LIBMEMCACHED_API
+void *memcached_callback_get(memcached_st *ptr,
+                             memcached_callback_t flag,
+                             memcached_return_t *error);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MEMCACHED_CALLBACK_H__ */
index 3a08ffca2fc301643d08cbcd7f28d68c924b7f7f..c9d7cf812add5678282bd13d3de8065aa4cb5aef 100644 (file)
 
 
 #include "libmemcached/memcached.h"
-#include "libmemcached/memcached_watchpoint.h"
+#include "libmemcached/watchpoint.h"
 
 /* These are private not to be installed headers */
-#include "libmemcached/memcached_io.h"
-#include "libmemcached/memcached_internal.h"
+#include "libmemcached/io.h"
+#include "libmemcached/internal.h"
 #include "libmemcached/libmemcached_probes.h"
 #include "libmemcached/memcached/protocol_binary.h"
 #include "libmemcached/byteorder.h"
diff --git a/libmemcached/connect.c b/libmemcached/connect.c
new file mode 100644 (file)
index 0000000..24328f4
--- /dev/null
@@ -0,0 +1,355 @@
+#include "common.h"
+#include <netdb.h>
+#include <poll.h>
+#include <sys/time.h>
+
+static memcached_return_t set_hostinfo(memcached_server_st *server)
+{
+  struct addrinfo *ai;
+  struct addrinfo hints;
+  int e;
+  char str_port[NI_MAXSERV];
+
+  sprintf(str_port, "%u", server->port);
+
+  memset(&hints, 0, sizeof(hints));
+
+ // hints.ai_family= AF_INET;
+  if (server->type == MEMCACHED_CONNECTION_UDP)
+  {
+    hints.ai_protocol= IPPROTO_UDP;
+    hints.ai_socktype= SOCK_DGRAM;
+  }
+  else
+  {
+    hints.ai_socktype= SOCK_STREAM;
+    hints.ai_protocol= IPPROTO_TCP;
+  }
+
+  e= getaddrinfo(server->hostname, str_port, &hints, &ai);
+  if (e != 0)
+  {
+    WATCHPOINT_STRING(server->hostname);
+    WATCHPOINT_STRING(gai_strerror(e));
+    return MEMCACHED_HOST_LOOKUP_FAILURE;
+  }
+
+  if (server->address_info)
+  {
+    freeaddrinfo(server->address_info);
+    server->address_info= NULL;
+  }
+  server->address_info= ai;
+
+  return MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t set_socket_options(memcached_server_st *ptr)
+{
+  WATCHPOINT_ASSERT(ptr->fd != -1);
+
+  if (ptr->type == MEMCACHED_CONNECTION_UDP)
+    return MEMCACHED_SUCCESS;
+
+#ifdef HAVE_SNDTIMEO
+  if (ptr->root->snd_timeout)
+  {
+    int error;
+    struct timeval waittime;
+
+    waittime.tv_sec= 0;
+    waittime.tv_usec= ptr->root->snd_timeout;
+
+    error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDTIMEO,
+                      &waittime, (socklen_t)sizeof(struct timeval));
+    WATCHPOINT_ASSERT(error == 0);
+  }
+#endif
+
+#ifdef HAVE_RCVTIMEO
+  if (ptr->root->rcv_timeout)
+  {
+    int error;
+    struct timeval waittime;
+
+    waittime.tv_sec= 0;
+    waittime.tv_usec= ptr->root->rcv_timeout;
+
+    error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVTIMEO,
+                      &waittime, (socklen_t)sizeof(struct timeval));
+    WATCHPOINT_ASSERT(error == 0);
+  }
+#endif
+
+  if (ptr->root->flags.no_block)
+  {
+    int error;
+    struct linger linger;
+
+    linger.l_onoff= 1;
+    linger.l_linger= 0; /* By default on close() just drop the socket */
+    error= setsockopt(ptr->fd, SOL_SOCKET, SO_LINGER,
+                      &linger, (socklen_t)sizeof(struct linger));
+    WATCHPOINT_ASSERT(error == 0);
+  }
+
+  if (ptr->root->flags.tcp_nodelay)
+  {
+    int flag= 1;
+    int error;
+
+    error= setsockopt(ptr->fd, IPPROTO_TCP, TCP_NODELAY,
+                      &flag, (socklen_t)sizeof(int));
+    WATCHPOINT_ASSERT(error == 0);
+  }
+
+  if (ptr->root->send_size)
+  {
+    int error;
+
+    error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDBUF,
+                      &ptr->root->send_size, (socklen_t)sizeof(int));
+    WATCHPOINT_ASSERT(error == 0);
+  }
+
+  if (ptr->root->recv_size)
+  {
+    int error;
+
+    error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVBUF,
+                      &ptr->root->recv_size, (socklen_t)sizeof(int));
+    WATCHPOINT_ASSERT(error == 0);
+  }
+
+  /* libmemcached will always use nonblocking IO to avoid write deadlocks */
+  int flags;
+
+  do
+    flags= fcntl(ptr->fd, F_GETFL, 0);
+  while (flags == -1 && (errno == EINTR || errno == EAGAIN));
+
+  unlikely (flags == -1)
+    return MEMCACHED_CONNECTION_FAILURE;
+  else if ((flags & O_NONBLOCK) == 0)
+  {
+    int rval;
+
+    do
+      rval= fcntl(ptr->fd, F_SETFL, flags | O_NONBLOCK);
+    while (rval == -1 && (errno == EINTR || errno == EAGAIN));
+
+    unlikely (rval == -1)
+      return MEMCACHED_CONNECTION_FAILURE;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t unix_socket_connect(memcached_server_st *ptr)
+{
+  struct sockaddr_un servAddr;
+  socklen_t addrlen;
+
+  if (ptr->fd == -1)
+  {
+    if ((ptr->fd= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+    {
+      ptr->cached_errno= errno;
+      return MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE;
+    }
+
+    memset(&servAddr, 0, sizeof (struct sockaddr_un));
+    servAddr.sun_family= AF_UNIX;
+    strcpy(servAddr.sun_path, ptr->hostname); /* Copy filename */
+
+    addrlen= (socklen_t) (strlen(servAddr.sun_path) + sizeof(servAddr.sun_family));
+
+test_connect:
+    if (connect(ptr->fd,
+                (struct sockaddr *)&servAddr,
+                sizeof(servAddr)) < 0)
+    {
+      switch (errno)
+      {
+      case EINPROGRESS:
+      case EALREADY:
+      case EINTR:
+        goto test_connect;
+      case EISCONN: /* We were spinning waiting on connect */
+        break;
+      default:
+        WATCHPOINT_ERRNO(errno);
+        ptr->cached_errno= errno;
+        return MEMCACHED_ERRNO;
+      }
+    }
+  }
+
+  WATCHPOINT_ASSERT(ptr->fd != -1);
+  return MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t network_connect(memcached_server_st *ptr)
+{
+  if (ptr->fd == -1)
+  {
+    struct addrinfo *use;
+
+    if (!ptr->sockaddr_inited ||
+        (!(ptr->root->flags.use_cache_lookups)))
+    {
+      memcached_return_t rc;
+
+      rc= set_hostinfo(ptr);
+      if (rc != MEMCACHED_SUCCESS)
+        return rc;
+      ptr->sockaddr_inited= true;
+    }
+
+    use= ptr->address_info;
+    /* Create the socket */
+    while (use != NULL)
+    {
+      /* Memcache server does not support IPV6 in udp mode, so skip if not ipv4 */
+      if (ptr->type == MEMCACHED_CONNECTION_UDP && use->ai_family != AF_INET)
+      {
+        use= use->ai_next;
+        continue;
+      }
+
+      if ((ptr->fd= socket(use->ai_family,
+                           use->ai_socktype,
+                           use->ai_protocol)) < 0)
+      {
+        ptr->cached_errno= errno;
+        WATCHPOINT_ERRNO(errno);
+        return MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE;
+      }
+
+      (void)set_socket_options(ptr);
+
+      /* connect to server */
+      while (ptr->fd != -1 &&
+             connect(ptr->fd, use->ai_addr, use->ai_addrlen) < 0)
+      {
+        ptr->cached_errno= errno;
+        if (errno == EINPROGRESS || /* nonblocking mode - first return, */
+            errno == EALREADY) /* nonblocking mode - subsequent returns */
+        {
+          struct pollfd fds[1];
+          fds[0].fd = ptr->fd;
+          fds[0].events = POLLOUT;
+          int error= poll(fds, 1, ptr->root->connect_timeout);
+
+          if (error != 1 || fds[0].revents & POLLERR)
+          {
+            if (fds[0].revents & POLLERR)
+            {
+              int err;
+              socklen_t len = sizeof (err);
+              (void)getsockopt(ptr->fd, SOL_SOCKET, SO_ERROR, &err, &len);
+              ptr->cached_errno= (err == 0) ? errno : err;
+            }
+
+            (void)close(ptr->fd);
+            ptr->fd= -1;
+          }
+        }
+        else if (errno == EISCONN) /* we are connected :-) */
+        {
+          break;
+        }
+        else if (errno != EINTR)
+        {
+          (void)close(ptr->fd);
+          ptr->fd= -1;
+          break;
+        }
+      }
+
+      if (ptr->fd != -1)
+      {
+        WATCHPOINT_ASSERT(ptr->cursor_active == 0);
+        ptr->server_failure_counter= 0;
+        return MEMCACHED_SUCCESS;
+      }
+      use = use->ai_next;
+    }
+  }
+
+  if (ptr->fd == -1)
+  {
+    /* Failed to connect. schedule next retry */
+    if (ptr->root->retry_timeout)
+    {
+      struct timeval next_time;
+
+      if (gettimeofday(&next_time, NULL) == 0)
+        ptr->next_retry= next_time.tv_sec + ptr->root->retry_timeout;
+    }
+    ptr->server_failure_counter++;
+    if (ptr->cached_errno == 0)
+      return MEMCACHED_TIMEOUT;
+
+    return MEMCACHED_ERRNO; /* The last error should be from connect() */
+  }
+
+  ptr->server_failure_counter= 0;
+  return MEMCACHED_SUCCESS; /* The last error should be from connect() */
+}
+
+
+memcached_return_t memcached_connect(memcached_server_st *ptr)
+{
+  memcached_return_t rc= MEMCACHED_NO_SERVERS;
+  LIBMEMCACHED_MEMCACHED_CONNECT_START();
+
+  /* both retry_timeout and server_failure_limit must be set in order to delay retrying a server on error. */
+  WATCHPOINT_ASSERT(ptr->root);
+  if (ptr->root->retry_timeout && ptr->root->server_failure_limit)
+  {
+    struct timeval curr_time;
+
+    gettimeofday(&curr_time, NULL);
+
+    /* if we've had too many consecutive errors on this server, mark it dead. */
+    if (ptr->server_failure_counter >= ptr->root->server_failure_limit)
+    {
+      ptr->next_retry= curr_time.tv_sec + ptr->root->retry_timeout;
+      ptr->server_failure_counter= 0;
+    }
+
+    if (curr_time.tv_sec < ptr->next_retry)
+    {
+      if (memcached_behavior_get(ptr->root, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS))
+        run_distribution(ptr->root);
+
+      ptr->root->last_disconnected_server = ptr;
+      return MEMCACHED_SERVER_MARKED_DEAD;
+    }
+  }
+
+  /* We need to clean up the multi startup piece */
+  switch (ptr->type)
+  {
+  case MEMCACHED_CONNECTION_UNKNOWN:
+    WATCHPOINT_ASSERT(0);
+    rc= MEMCACHED_NOT_SUPPORTED;
+    break;
+  case MEMCACHED_CONNECTION_UDP:
+  case MEMCACHED_CONNECTION_TCP:
+    rc= network_connect(ptr);
+    break;
+  case MEMCACHED_CONNECTION_UNIX_SOCKET:
+    rc= unix_socket_connect(ptr);
+    break;
+  default:
+    WATCHPOINT_ASSERT(0);
+  }
+
+  unlikely ( rc != MEMCACHED_SUCCESS) ptr->root->last_disconnected_server = ptr;
+
+  LIBMEMCACHED_MEMCACHED_CONNECT_END();
+
+  return rc;
+}
diff --git a/libmemcached/constants.h b/libmemcached/constants.h
new file mode 100644 (file)
index 0000000..cbdbf4b
--- /dev/null
@@ -0,0 +1,154 @@
+/* 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: Constants for libmemcached
+ *
+ */
+
+#ifndef __MEMCACHED_CONSTANTS_H__
+#define __MEMCACHED_CONSTANTS_H__
+
+/* Public defines */
+#define MEMCACHED_DEFAULT_PORT 11211
+#define MEMCACHED_MAX_KEY 251 /* We add one to have it null terminated */
+#define MEMCACHED_MAX_BUFFER 8196
+#define MEMCACHED_MAX_HOST_LENGTH 64
+#define MEMCACHED_MAX_HOST_SORT_LENGTH 86 /* Used for Ketama */
+#define MEMCACHED_POINTS_PER_SERVER 100
+#define MEMCACHED_POINTS_PER_SERVER_KETAMA 160
+#define MEMCACHED_CONTINUUM_SIZE MEMCACHED_POINTS_PER_SERVER*100 /* This would then set max hosts to 100 */
+#define MEMCACHED_STRIDE 4
+#define MEMCACHED_DEFAULT_TIMEOUT 1000
+#define MEMCACHED_CONTINUUM_ADDITION 10 /* How many extra slots we should build for in the continuum */
+#define MEMCACHED_PREFIX_KEY_MAX_SIZE 128
+#define MEMCACHED_EXPIRATION_NOT_ADD 0xffffffffU
+
+typedef enum {
+  MEMCACHED_SUCCESS,
+  MEMCACHED_FAILURE,
+  MEMCACHED_HOST_LOOKUP_FAILURE,
+  MEMCACHED_CONNECTION_FAILURE,
+  MEMCACHED_CONNECTION_BIND_FAILURE,
+  MEMCACHED_WRITE_FAILURE,
+  MEMCACHED_READ_FAILURE,
+  MEMCACHED_UNKNOWN_READ_FAILURE,
+  MEMCACHED_PROTOCOL_ERROR,
+  MEMCACHED_CLIENT_ERROR,
+  MEMCACHED_SERVER_ERROR,
+  MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE,
+  MEMCACHED_DATA_EXISTS,
+  MEMCACHED_DATA_DOES_NOT_EXIST,
+  MEMCACHED_NOTSTORED,
+  MEMCACHED_STORED,
+  MEMCACHED_NOTFOUND,
+  MEMCACHED_MEMORY_ALLOCATION_FAILURE,
+  MEMCACHED_PARTIAL_READ,
+  MEMCACHED_SOME_ERRORS,
+  MEMCACHED_NO_SERVERS,
+  MEMCACHED_END,
+  MEMCACHED_DELETED,
+  MEMCACHED_VALUE,
+  MEMCACHED_STAT,
+  MEMCACHED_ITEM,
+  MEMCACHED_ERRNO,
+  MEMCACHED_FAIL_UNIX_SOCKET,
+  MEMCACHED_NOT_SUPPORTED,
+  MEMCACHED_NO_KEY_PROVIDED, /* Deprecated. Use MEMCACHED_BAD_KEY_PROVIDED! */
+  MEMCACHED_FETCH_NOTFINISHED,
+  MEMCACHED_TIMEOUT,
+  MEMCACHED_BUFFERED,
+  MEMCACHED_BAD_KEY_PROVIDED,
+  MEMCACHED_INVALID_HOST_PROTOCOL,
+  MEMCACHED_SERVER_MARKED_DEAD,
+  MEMCACHED_UNKNOWN_STAT_KEY,
+  MEMCACHED_E2BIG,
+  MEMCACHED_INVALID_ARGUMENTS,
+  MEMCACHED_MAXIMUM_RETURN /* Always add new error code before */
+} memcached_return_t;
+
+
+typedef enum {
+  MEMCACHED_DISTRIBUTION_MODULA,
+  MEMCACHED_DISTRIBUTION_CONSISTENT,
+  MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA,
+  MEMCACHED_DISTRIBUTION_RANDOM,
+  MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY
+} memcached_server_distribution_t;
+
+typedef enum {
+  MEMCACHED_BEHAVIOR_NO_BLOCK,
+  MEMCACHED_BEHAVIOR_TCP_NODELAY,
+  MEMCACHED_BEHAVIOR_HASH,
+  MEMCACHED_BEHAVIOR_KETAMA,
+  MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE,
+  MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE,
+  MEMCACHED_BEHAVIOR_CACHE_LOOKUPS,
+  MEMCACHED_BEHAVIOR_SUPPORT_CAS,
+  MEMCACHED_BEHAVIOR_POLL_TIMEOUT,
+  MEMCACHED_BEHAVIOR_DISTRIBUTION,
+  MEMCACHED_BEHAVIOR_BUFFER_REQUESTS,
+  MEMCACHED_BEHAVIOR_USER_DATA,
+  MEMCACHED_BEHAVIOR_SORT_HOSTS,
+  MEMCACHED_BEHAVIOR_VERIFY_KEY,
+  MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT,
+  MEMCACHED_BEHAVIOR_RETRY_TIMEOUT,
+  MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED,
+  MEMCACHED_BEHAVIOR_KETAMA_HASH,
+  MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
+  MEMCACHED_BEHAVIOR_SND_TIMEOUT,
+  MEMCACHED_BEHAVIOR_RCV_TIMEOUT,
+  MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT,
+  MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK,
+  MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK,
+  MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH,
+  MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY,
+  MEMCACHED_BEHAVIOR_NOREPLY,
+  MEMCACHED_BEHAVIOR_USE_UDP,
+  MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS,
+  MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS,
+  MEMCACHED_BEHAVIOR_KETAMA_COMPAT_MODE,
+  MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ
+} memcached_behavior_t;
+
+#define MEMCACHED_KETAMA_COMPAT_LIBMEMCACHED 0
+#define MEMCACHED_KETAMA_COMPAT_SPY 1
+
+typedef enum {
+  MEMCACHED_CALLBACK_PREFIX_KEY = 0,
+  MEMCACHED_CALLBACK_USER_DATA = 1,
+  MEMCACHED_CALLBACK_CLEANUP_FUNCTION = 2,
+  MEMCACHED_CALLBACK_CLONE_FUNCTION = 3,
+#ifdef MEMCACHED_ENABLE_DEPRECATED
+  MEMCACHED_CALLBACK_MALLOC_FUNCTION = 4,
+  MEMCACHED_CALLBACK_REALLOC_FUNCTION = 5,
+  MEMCACHED_CALLBACK_FREE_FUNCTION = 6,
+#endif
+  MEMCACHED_CALLBACK_GET_FAILURE = 7,
+  MEMCACHED_CALLBACK_DELETE_TRIGGER = 8
+} memcached_callback_t;
+
+typedef enum {
+  MEMCACHED_HASH_DEFAULT= 0,
+  MEMCACHED_HASH_MD5,
+  MEMCACHED_HASH_CRC,
+  MEMCACHED_HASH_FNV1_64,
+  MEMCACHED_HASH_FNV1A_64,
+  MEMCACHED_HASH_FNV1_32,
+  MEMCACHED_HASH_FNV1A_32,
+  MEMCACHED_HASH_HSIEH,
+  MEMCACHED_HASH_MURMUR,
+  MEMCACHED_HASH_JENKINS
+} memcached_hash_t;
+
+typedef enum {
+  MEMCACHED_CONNECTION_UNKNOWN,
+  MEMCACHED_CONNECTION_TCP,
+  MEMCACHED_CONNECTION_UDP,
+  MEMCACHED_CONNECTION_UNIX_SOCKET
+} memcached_connection_t;
+
+#endif /* __MEMCACHED_CONSTANTS_H__ */
diff --git a/libmemcached/delete.c b/libmemcached/delete.c
new file mode 100644 (file)
index 0000000..bbdd252
--- /dev/null
@@ -0,0 +1,185 @@
+#include "common.h"
+#include "memcached/protocol_binary.h"
+
+memcached_return_t memcached_delete(memcached_st *ptr, const char *key, size_t key_length,
+                                    time_t expiration)
+{
+  return memcached_delete_by_key(ptr, key, key_length,
+                                 key, key_length, expiration);
+}
+
+static inline memcached_return_t binary_delete(memcached_st *ptr,
+                                               unsigned int server_key,
+                                               const char *key,
+                                               size_t key_length,
+                                               uint8_t flush);
+
+memcached_return_t memcached_delete_by_key(memcached_st *ptr,
+                                           const char *master_key, size_t master_key_length,
+                                           const char *key, size_t key_length,
+                                           time_t expiration)
+{
+  uint8_t to_write;
+  size_t send_length;
+  memcached_return_t rc;
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+  unsigned int server_key;
+
+  LIBMEMCACHED_MEMCACHED_DELETE_START();
+
+  rc= memcached_validate_key_length(key_length,
+                                    ptr->flags.binary_protocol);
+  unlikely (rc != MEMCACHED_SUCCESS)
+    return rc;
+
+  unlikely (ptr->hosts == NULL || ptr->number_of_hosts == 0)
+    return MEMCACHED_NO_SERVERS;
+
+  server_key= memcached_generate_hash(ptr, master_key, master_key_length);
+  to_write= (uint8_t)((ptr->flags.buffer_requests) ? 0 : 1);
+  bool no_reply= (ptr->flags.no_reply);
+
+  if (ptr->flags.binary_protocol)
+  {
+    likely (!expiration)
+      rc= binary_delete(ptr, server_key, key, key_length, to_write);
+    else
+      rc= MEMCACHED_INVALID_ARGUMENTS;
+  }
+  else
+  {
+    unlikely (expiration)
+    {
+       if ((ptr->hosts[server_key].major_version == 1 &&
+            ptr->hosts[server_key].minor_version > 2) ||
+           ptr->hosts[server_key].major_version > 1)
+       {
+         rc= MEMCACHED_INVALID_ARGUMENTS;
+         goto error;
+       }
+       else
+       {
+          if (ptr->hosts[server_key].minor_version == 0)
+          {
+             if (no_reply || !to_write)
+             {
+                /* We might get out of sync with the server if we
+                 * send this command to a server newer than 1.2.x..
+                 * disable no_reply and buffered mode.
+                 */
+                to_write= 1;
+                if (no_reply)
+                   memcached_server_response_increment(&ptr->hosts[server_key]);
+                no_reply= false;
+             }
+          }
+          send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
+                                         "delete %s%.*s %u%s\r\n",
+                                         ptr->prefix_key,
+                                         (int) key_length, key,
+                                         (uint32_t)expiration,
+                                         no_reply ? " noreply" :"" );
+       }
+    }
+    else
+       send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
+                                      "delete %s%.*s%s\r\n",
+                                      ptr->prefix_key,
+                                      (int)key_length, key, no_reply ? " noreply" :"");
+
+    if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
+    {
+      rc= MEMCACHED_WRITE_FAILURE;
+      goto error;
+    }
+
+    if (ptr->flags.use_udp && !to_write)
+    {
+      if (send_length > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
+        return MEMCACHED_WRITE_FAILURE;
+      if (send_length + ptr->hosts[server_key].write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
+        memcached_io_write(&ptr->hosts[server_key], NULL, 0, 1);
+    }
+
+    rc= memcached_do(&ptr->hosts[server_key], buffer, send_length, to_write);
+  }
+
+  if (rc != MEMCACHED_SUCCESS)
+    goto error;
+
+  if (!to_write)
+    rc= MEMCACHED_BUFFERED;
+  else if (!no_reply)
+  {
+    rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+    if (rc == MEMCACHED_DELETED)
+      rc= MEMCACHED_SUCCESS;
+  }
+
+  if (rc == MEMCACHED_SUCCESS && ptr->delete_trigger)
+    ptr->delete_trigger(ptr, key, key_length);
+
+error:
+  LIBMEMCACHED_MEMCACHED_DELETE_END();
+  return rc;
+}
+
+static inline memcached_return_t binary_delete(memcached_st *ptr,
+                                               unsigned int server_key,
+                                               const char *key,
+                                               size_t key_length,
+                                               uint8_t flush)
+{
+  protocol_binary_request_delete request= {.bytes= {0}};
+
+  request.message.header.request.magic= PROTOCOL_BINARY_REQ;
+  if (ptr->flags.no_reply)
+    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
+  else
+    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETE;
+  request.message.header.request.keylen= htons((uint16_t)key_length);
+  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+  request.message.header.request.bodylen= htonl((uint32_t) key_length);
+
+  if (ptr->flags.use_udp && !flush)
+  {
+    size_t cmd_size= sizeof(request.bytes) + key_length;
+    if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
+      return MEMCACHED_WRITE_FAILURE;
+    if (cmd_size + ptr->hosts[server_key].write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
+      memcached_io_write(&ptr->hosts[server_key], NULL, 0, 1);
+  }
+
+  memcached_return_t 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, (char) flush) == -1))
+  {
+    memcached_io_reset(&ptr->hosts[server_key]);
+    rc= MEMCACHED_WRITE_FAILURE;
+  }
+
+  unlikely (ptr->number_of_replicas > 0)
+  {
+    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
+
+    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, (char) flush) == -1))
+        memcached_io_reset(server);
+      else
+        memcached_server_response_decrement(server);
+    }
+  }
+
+  return rc;
+}
diff --git a/libmemcached/do.c b/libmemcached/do.c
new file mode 100644 (file)
index 0000000..d673f18
--- /dev/null
@@ -0,0 +1,34 @@
+#include "common.h"
+
+memcached_return_t memcached_do(memcached_server_st *ptr, const void *command, 
+                                size_t command_length, uint8_t with_flush)
+{
+  memcached_return_t rc;
+  ssize_t sent_length;
+
+  WATCHPOINT_ASSERT(command_length);
+  WATCHPOINT_ASSERT(command);
+
+  if ((rc= memcached_connect(ptr)) != MEMCACHED_SUCCESS)
+  {
+    WATCHPOINT_ERROR(rc);
+    return rc;
+  }
+
+  /*
+  ** Since non buffering ops in UDP mode dont check to make sure they will fit
+  ** before they start writing, if there is any data in buffer, clear it out,
+  ** otherwise we might get a partial write.
+  **/
+  if (ptr->type == MEMCACHED_CONNECTION_UDP && with_flush && ptr->write_buffer_offset > UDP_DATAGRAM_HEADER_LENGTH)
+    memcached_io_write(ptr, NULL, 0, 1);
+
+  sent_length= memcached_io_write(ptr, command, command_length, (char) with_flush);
+
+  if (sent_length == -1 || (size_t)sent_length != command_length)
+    rc= MEMCACHED_WRITE_FAILURE;
+  else if ((ptr->root->flags.no_reply) == 0)
+    memcached_server_response_increment(ptr);
+
+  return rc;
+}
diff --git a/libmemcached/dump.c b/libmemcached/dump.c
new file mode 100644 (file)
index 0000000..4c1006e
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+  We use this to dump all keys.
+
+  At this point we only support a callback method. This could be optimized by first
+  calling items and finding active slabs. For the moment though we just loop through
+  all slabs on servers and "grab" the keys.
+*/
+
+#include "common.h"
+static memcached_return_t ascii_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
+{
+  memcached_return_t rc= 0;
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+  size_t send_length;
+  uint32_t server_key;
+  uint32_t x;
+
+  unlikely (ptr->number_of_hosts == 0)
+    return MEMCACHED_NO_SERVERS;
+
+  for (server_key= 0; server_key < ptr->number_of_hosts; server_key++)
+  {
+    /* 256 I BELIEVE is the upper limit of slabs */
+    for (x= 0; x < 256; x++)
+    {
+      send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
+                                     "stats cachedump %u 0 0\r\n", x);
+
+      rc= memcached_do(&ptr->hosts[server_key], buffer, send_length, 1);
+
+      unlikely (rc != MEMCACHED_SUCCESS)
+        goto error;
+
+      while (1)
+      {
+        uint32_t callback_counter;
+        rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+
+        if (rc == MEMCACHED_ITEM)
+        {
+          char *string_ptr, *end_ptr;
+          char *key;
+
+          string_ptr= buffer;
+          string_ptr+= 5; /* Move past ITEM */
+          for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++);
+          key= string_ptr;
+          key[(size_t)(end_ptr-string_ptr)]= 0;
+          for (callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++)
+          {
+            rc= (*callback[callback_counter])(ptr, key, (size_t)(end_ptr-string_ptr), context);
+            if (rc != MEMCACHED_SUCCESS)
+              break;
+          }
+        }
+        else if (rc == MEMCACHED_END)
+          break;
+        else if (rc == MEMCACHED_SERVER_ERROR || rc == MEMCACHED_CLIENT_ERROR)
+        {
+          /* If we try to request stats cachedump for a slab class that is too big
+           * the server will return an incorrect error message:
+           * "MEMCACHED_SERVER_ERROR failed to allocate memory"
+           * This isn't really a fatal error, so let's just skip it. I want to
+           * fix the return value from the memcached server to a CLIENT_ERROR,
+           * so let's add support for that as well right now.
+           */
+          rc= MEMCACHED_END;
+          break;
+        }
+        else
+          goto error;
+      }
+    }
+  }
+
+error:
+  if (rc == MEMCACHED_END)
+    return MEMCACHED_SUCCESS;
+  else
+    return rc;
+}
+
+memcached_return_t memcached_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
+{
+  /* No support for Binary protocol yet */
+  if (ptr->flags.binary_protocol)
+    return MEMCACHED_FAILURE;
+
+  return ascii_dump(ptr, callback, context, number_of_callbacks);
+}
+
diff --git a/libmemcached/fetch.c b/libmemcached/fetch.c
new file mode 100644 (file)
index 0000000..7baac54
--- /dev/null
@@ -0,0 +1,105 @@
+#include "common.h"
+
+char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length, 
+                      size_t *value_length, 
+                      uint32_t *flags,
+                      memcached_return_t *error)
+{
+  memcached_result_st *result_buffer= &ptr->result;
+
+  unlikely (ptr->flags.use_udp)
+  {
+    *error= MEMCACHED_NOT_SUPPORTED;
+    return NULL;
+  }
+
+  result_buffer= memcached_fetch_result(ptr, result_buffer, error);
+
+  if (result_buffer == NULL || *error != MEMCACHED_SUCCESS)
+  {
+    WATCHPOINT_ASSERT(result_buffer == NULL);
+    *value_length= 0;
+    return NULL;
+  }
+
+  *value_length= memcached_string_length(&result_buffer->value);
+
+  if (key)
+  {
+    strncpy(key, result_buffer->key, result_buffer->key_length);
+    *key_length= result_buffer->key_length;
+  }
+
+  if (result_buffer->flags)
+    *flags= result_buffer->flags;
+  else
+    *flags= 0;
+
+  return memcached_string_c_copy(&result_buffer->value);
+}
+
+memcached_result_st *memcached_fetch_result(memcached_st *ptr,
+                                            memcached_result_st *result,
+                                            memcached_return_t *error)
+{
+  memcached_server_st *server;
+
+  unlikely (ptr->flags.use_udp)
+  {
+    *error= MEMCACHED_NOT_SUPPORTED;
+    return NULL;
+  }
+
+  if (result == NULL)
+    if ((result= memcached_result_create(ptr, NULL)) == NULL)
+      return NULL;
+
+  while ((server = memcached_io_get_readable_server(ptr)) != NULL) 
+  {
+    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+    *error= memcached_response(server, buffer, sizeof(buffer), result);
+
+    if (*error == MEMCACHED_SUCCESS)
+      return result;
+    else if (*error == MEMCACHED_END)
+      memcached_server_response_reset(server);
+    else if (*error != MEMCACHED_NOTFOUND)
+      break;
+  }
+
+  /* We have completed reading data */
+  if (memcached_is_allocated(result))
+  {
+    memcached_result_free(result);
+  }
+  else
+  {
+    memcached_string_reset(&result->value);
+  }
+
+  return NULL;
+}
+
+memcached_return_t memcached_fetch_execute(memcached_st *ptr, 
+                                           memcached_execute_fn *callback,
+                                           void *context,
+                                           uint32_t number_of_callbacks)
+{
+  memcached_result_st *result= &ptr->result;
+  memcached_return_t rc= MEMCACHED_FAILURE;
+  unsigned int x;
+
+  while ((result= memcached_fetch_result(ptr, result, &rc)) != NULL) 
+  {
+    if (rc == MEMCACHED_SUCCESS)
+    {
+      for (x= 0; x < number_of_callbacks; x++)
+      {
+        rc= (*callback[x])(ptr, result, context);
+        if (rc != MEMCACHED_SUCCESS)
+          break;
+      }
+    }
+  }
+  return rc;
+}
diff --git a/libmemcached/flush.c b/libmemcached/flush.c
new file mode 100644 (file)
index 0000000..d05d744
--- /dev/null
@@ -0,0 +1,90 @@
+#include "common.h"
+
+static memcached_return_t memcached_flush_binary(memcached_st *ptr, 
+                                                 time_t expiration);
+static memcached_return_t memcached_flush_textual(memcached_st *ptr, 
+                                                  time_t expiration);
+
+memcached_return_t memcached_flush(memcached_st *ptr, time_t expiration)
+{
+  memcached_return_t rc;
+
+  LIBMEMCACHED_MEMCACHED_FLUSH_START();
+  if (ptr->flags.binary_protocol)
+    rc= memcached_flush_binary(ptr, expiration);
+  else
+    rc= memcached_flush_textual(ptr, expiration);
+  LIBMEMCACHED_MEMCACHED_FLUSH_END();
+  return rc;
+}
+
+static memcached_return_t memcached_flush_textual(memcached_st *ptr, 
+                                                  time_t expiration)
+{
+  unsigned int x;
+  size_t send_length;
+  memcached_return_t rc;
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+
+  unlikely (ptr->number_of_hosts == 0)
+    return MEMCACHED_NO_SERVERS;
+
+  for (x= 0; x < ptr->number_of_hosts; x++)
+  {
+    bool no_reply= ptr->flags.no_reply;
+
+    if (expiration)
+      send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
+                                     "flush_all %llu%s\r\n",
+                                     (unsigned long long)expiration, no_reply ? " noreply" : "");
+    else
+      send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
+                                     "flush_all%s\r\n", no_reply ? " noreply" : "");
+
+    rc= memcached_do(&ptr->hosts[x], buffer, send_length, 1);
+
+    if (rc == MEMCACHED_SUCCESS && !no_reply)
+      (void)memcached_response(&ptr->hosts[x], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t memcached_flush_binary(memcached_st *ptr, 
+                                                 time_t expiration)
+{
+  unsigned int x;
+  protocol_binary_request_flush request= {.bytes= {0}};
+
+  unlikely (ptr->number_of_hosts == 0)
+    return MEMCACHED_NO_SERVERS;
+
+  request.message.header.request.magic= (uint8_t)PROTOCOL_BINARY_REQ;
+  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
+  request.message.header.request.extlen= 4;
+  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+  request.message.header.request.bodylen= htonl(request.message.header.request.extlen);
+  request.message.body.expiration= htonl((uint32_t) expiration);
+
+  for (x= 0; x < ptr->number_of_hosts; x++)
+  {
+    if (ptr->flags.no_reply)
+      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSHQ;
+    else
+      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
+    if (memcached_do(&ptr->hosts[x], request.bytes, 
+                     sizeof(request.bytes), 1) != MEMCACHED_SUCCESS) 
+    {
+      memcached_io_reset(&ptr->hosts[x]);
+      return MEMCACHED_WRITE_FAILURE;
+    } 
+  }
+
+  for (x= 0; x < ptr->number_of_hosts; x++)
+  {
+    if (memcached_server_response_count(&ptr->hosts[x]) > 0)
+      (void)memcached_response(&ptr->hosts[x], NULL, 0, NULL);
+  }
+
+  return MEMCACHED_SUCCESS;
+}
diff --git a/libmemcached/flush_buffers.c b/libmemcached/flush_buffers.c
new file mode 100644 (file)
index 0000000..950fa1e
--- /dev/null
@@ -0,0 +1,21 @@
+#include "common.h"
+
+memcached_return_t memcached_flush_buffers(memcached_st *mem)
+{
+  memcached_return_t ret= MEMCACHED_SUCCESS;
+
+  for (uint32_t x= 0; x < mem->number_of_hosts; ++x)
+    if (mem->hosts[x].write_buffer_offset != 0) 
+    {
+      if (mem->hosts[x].fd == -1 &&
+          (ret= memcached_connect(&mem->hosts[x])) != MEMCACHED_SUCCESS)
+      {
+        WATCHPOINT_ERROR(ret);
+        return ret;
+      }
+      if (memcached_io_write(&mem->hosts[x], NULL, 0, 1) == -1)
+        ret= MEMCACHED_SOME_ERRORS;
+    }
+
+  return ret;
+}
diff --git a/libmemcached/get.c b/libmemcached/get.c
new file mode 100644 (file)
index 0000000..3068242
--- /dev/null
@@ -0,0 +1,574 @@
+/* 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: Get functions for libmemcached
+ *
+ */
+
+#include "common.h"
+
+/*
+  What happens if no servers exist?
+*/
+char *memcached_get(memcached_st *ptr, const char *key,
+                    size_t key_length,
+                    size_t *value_length,
+                    uint32_t *flags,
+                    memcached_return_t *error)
+{
+  return memcached_get_by_key(ptr, NULL, 0, key, key_length, value_length,
+                              flags, error);
+}
+
+static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
+                                                     const char *master_key,
+                                                     size_t master_key_length,
+                                                     const char * const *keys,
+                                                     const size_t *key_length,
+                                                     size_t number_of_keys,
+                                                     bool mget_mode);
+
+char *memcached_get_by_key(memcached_st *ptr,
+                           const char *master_key,
+                           size_t master_key_length,
+                           const char *key, size_t key_length,
+                           size_t *value_length,
+                           uint32_t *flags,
+                           memcached_return_t *error)
+{
+  char *value;
+  size_t dummy_length;
+  uint32_t dummy_flags;
+  memcached_return_t dummy_error;
+
+  unlikely (ptr->flags.use_udp)
+  {
+    *error= MEMCACHED_NOT_SUPPORTED;
+    return NULL;
+  }
+
+  /* Request the key */
+  *error= memcached_mget_by_key_real(ptr, master_key, master_key_length,
+                                     (const char * const *)&key,
+                                     &key_length, 1, false);
+
+  value= memcached_fetch(ptr, NULL, NULL,
+                         value_length, flags, error);
+  /* This is for historical reasons */
+  if (*error == MEMCACHED_END)
+    *error= MEMCACHED_NOTFOUND;
+
+  if (value == NULL)
+  {
+    if (ptr->get_key_failure && *error == MEMCACHED_NOTFOUND)
+    {
+      memcached_return_t rc;
+
+      memcached_result_reset(&ptr->result);
+      rc= ptr->get_key_failure(ptr, key, key_length, &ptr->result);
+
+      /* On all failure drop to returning NULL */
+      if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED)
+      {
+        if (rc == MEMCACHED_BUFFERED)
+        {
+          uint64_t latch; /* We use latch to track the state of the original socket */
+          latch= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS);
+          if (latch == 0)
+            memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1);
+
+          rc= memcached_set(ptr, key, key_length,
+                            memcached_result_value(&ptr->result),
+                            memcached_result_length(&ptr->result),
+                            0, memcached_result_flags(&ptr->result));
+
+          if (rc == MEMCACHED_BUFFERED && latch == 0)
+            memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 0);
+        }
+        else
+        {
+          rc= memcached_set(ptr, key, key_length,
+                            memcached_result_value(&ptr->result),
+                            memcached_result_length(&ptr->result),
+                            0, memcached_result_flags(&ptr->result));
+        }
+
+        if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED)
+        {
+          *error= rc;
+          *value_length= memcached_result_length(&ptr->result);
+          *flags= memcached_result_flags(&ptr->result);
+          return memcached_string_c_copy(&ptr->result.value);
+        }
+      }
+    }
+
+    return NULL;
+  }
+
+  (void)memcached_fetch(ptr, NULL, NULL,
+                        &dummy_length, &dummy_flags,
+                        &dummy_error);
+  WATCHPOINT_ASSERT(dummy_length == 0);
+
+  return value;
+}
+
+memcached_return_t memcached_mget(memcached_st *ptr,
+                                  const char * const *keys,
+                                  const size_t *key_length,
+                                  size_t number_of_keys)
+{
+  return memcached_mget_by_key(ptr, NULL, 0, keys, key_length, number_of_keys);
+}
+
+static memcached_return_t binary_mget_by_key(memcached_st *ptr,
+                                             unsigned int master_server_key,
+                                             bool is_master_key_set,
+                                             const char * const *keys,
+                                             const size_t *key_length,
+                                             size_t number_of_keys,
+                                             bool mget_mode);
+
+static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
+                                                     const char *master_key,
+                                                     size_t master_key_length,
+                                                     const char * const *keys,
+                                                     const size_t *key_length,
+                                                     size_t number_of_keys,
+                                                     bool mget_mode)
+{
+  unsigned int x;
+  memcached_return_t rc= MEMCACHED_NOTFOUND;
+  const char *get_command= "get ";
+  uint8_t get_command_length= 4;
+  unsigned int master_server_key= (unsigned int)-1; /* 0 is a valid server id! */
+  bool is_master_key_set= false;
+
+  unlikely (ptr->flags.use_udp)
+    return MEMCACHED_NOT_SUPPORTED;
+
+  LIBMEMCACHED_MEMCACHED_MGET_START();
+  ptr->cursor_server= 0;
+
+  if (number_of_keys == 0)
+    return MEMCACHED_NOTFOUND;
+
+  if (ptr->number_of_hosts == 0)
+    return MEMCACHED_NO_SERVERS;
+
+  if (ptr->flags.verify_key && (memcached_key_test(keys, key_length, number_of_keys) == MEMCACHED_BAD_KEY_PROVIDED))
+    return MEMCACHED_BAD_KEY_PROVIDED;
+
+  if (master_key && master_key_length)
+  {
+    if (ptr->flags.verify_key && (memcached_key_test((const char * const *)&master_key, &master_key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
+      return MEMCACHED_BAD_KEY_PROVIDED;
+    master_server_key= memcached_generate_hash(ptr, master_key, master_key_length);
+    is_master_key_set= true;
+  }
+
+  /*
+    Here is where we pay for the non-block API. We need to remove any data sitting
+    in the queue before we start our get.
+
+    It might be optimum to bounce the connection if count > some number.
+  */
+  for (x= 0; x < ptr->number_of_hosts; x++)
+  {
+    if (memcached_server_response_count(&ptr->hosts[x]))
+    {
+      char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+
+      if (ptr->flags.no_block)
+        (void)memcached_io_write(&ptr->hosts[x], NULL, 0, 1);
+
+      while(memcached_server_response_count(&ptr->hosts[x]))
+        (void)memcached_response(&ptr->hosts[x], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, &ptr->result);
+    }
+  }
+
+  if (ptr->flags.binary_protocol)
+    return binary_mget_by_key(ptr, master_server_key, is_master_key_set, keys,
+                              key_length, number_of_keys, mget_mode);
+
+  if (ptr->flags.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.
+  */
+  for (x= 0; x < number_of_keys; x++)
+  {
+    unsigned int server_key;
+
+    if (is_master_key_set)
+      server_key= master_server_key;
+    else
+      server_key= memcached_generate_hash(ptr, keys[x], key_length[x]);
+
+    if (memcached_server_response_count(&ptr->hosts[server_key]) == 0)
+    {
+      rc= memcached_connect(&ptr->hosts[server_key]);
+
+      if (rc != MEMCACHED_SUCCESS)
+        continue;
+
+      if ((memcached_io_write(&ptr->hosts[server_key], get_command, get_command_length, 0)) == -1)
+      {
+        rc= MEMCACHED_SOME_ERRORS;
+        continue;
+      }
+      WATCHPOINT_ASSERT(ptr->hosts[server_key].cursor_active == 0);
+      memcached_server_response_increment(&ptr->hosts[server_key]);
+      WATCHPOINT_ASSERT(ptr->hosts[server_key].cursor_active == 1);
+    }
+
+    /* Only called when we have a prefix key */
+    if (ptr->prefix_key[0] != 0)
+    {
+      if ((memcached_io_write(&ptr->hosts[server_key], ptr->prefix_key, ptr->prefix_key_length, 0)) == -1)
+      {
+        memcached_server_response_reset(&ptr->hosts[server_key]);
+        rc= MEMCACHED_SOME_ERRORS;
+        continue;
+      }
+    }
+
+    if ((memcached_io_write(&ptr->hosts[server_key], keys[x], key_length[x], 0)) == -1)
+    {
+      memcached_server_response_reset(&ptr->hosts[server_key]);
+      rc= MEMCACHED_SOME_ERRORS;
+      continue;
+    }
+
+    if ((memcached_io_write(&ptr->hosts[server_key], " ", 1, 0)) == -1)
+    {
+      memcached_server_response_reset(&ptr->hosts[server_key]);
+      rc= MEMCACHED_SOME_ERRORS;
+      continue;
+    }
+  }
+
+  /*
+    Should we muddle on if some servers are dead?
+  */
+  for (x= 0; x < ptr->number_of_hosts; x++)
+  {
+    if (memcached_server_response_count(&ptr->hosts[x]))
+    {
+      /* We need to do something about non-connnected hosts in the future */
+      if ((memcached_io_write(&ptr->hosts[x], "\r\n", 2, 1)) == -1)
+      {
+        rc= MEMCACHED_SOME_ERRORS;
+      }
+    }
+  }
+
+  LIBMEMCACHED_MEMCACHED_MGET_END();
+  return rc;
+}
+
+memcached_return_t memcached_mget_by_key(memcached_st *ptr,
+                                         const char *master_key,
+                                         size_t master_key_length,
+                                         const char * const *keys,
+                                         const size_t *key_length,
+                                         size_t number_of_keys)
+{
+  return memcached_mget_by_key_real(ptr, master_key, master_key_length, keys,
+                                    key_length, number_of_keys, true);
+}
+
+memcached_return_t memcached_mget_execute(memcached_st *ptr,
+                                          const char * const *keys,
+                                          const size_t *key_length,
+                                          size_t number_of_keys,
+                                          memcached_execute_fn *callback,
+                                          void *context,
+                                          unsigned int number_of_callbacks)
+{
+  return memcached_mget_execute_by_key(ptr, NULL, 0, keys, key_length,
+                                       number_of_keys, callback,
+                                       context, number_of_callbacks);
+}
+
+memcached_return_t memcached_mget_execute_by_key(memcached_st *ptr,
+                                                 const char *master_key,
+                                                 size_t master_key_length,
+                                                 const char * const *keys,
+                                                 const size_t *key_length,
+                                                 size_t number_of_keys,
+                                                 memcached_execute_fn *callback,
+                                                 void *context,
+                                                 unsigned int number_of_callbacks)
+{
+  if ((ptr->flags.binary_protocol) == 0)
+    return MEMCACHED_NOT_SUPPORTED;
+
+  memcached_return_t rc;
+  memcached_callback_st *original_callbacks= ptr->callbacks;
+  memcached_callback_st cb= {
+    .callback= callback,
+    .context= context,
+    .number_of_callback= number_of_callbacks
+  };
+
+  ptr->callbacks= &cb;
+  rc= memcached_mget_by_key(ptr, master_key, master_key_length, keys,
+                            key_length, number_of_keys);
+  ptr->callbacks= original_callbacks;
+  return rc;
+}
+
+static memcached_return_t simple_binary_mget(memcached_st *ptr,
+                                             unsigned int master_server_key,
+                                             bool is_master_key_set,
+                                             const char * const *keys,
+                                             const size_t *key_length,
+                                             size_t number_of_keys, bool mget_mode)
+{
+  memcached_return_t rc= MEMCACHED_NOTFOUND;
+  uint32_t x;
+
+  int flush= number_of_keys == 1;
+
+  /*
+    If a server fails we warn about errors and start all over with sending keys
+    to the server.
+  */
+  for (x= 0; x < number_of_keys; x++)
+  {
+    unsigned int server_key;
+
+    if (is_master_key_set)
+      server_key= master_server_key;
+    else
+      server_key= memcached_generate_hash(ptr, keys[x], key_length[x]);
+
+    if (memcached_server_response_count(&ptr->hosts[server_key]) == 0)
+    {
+      rc= memcached_connect(&ptr->hosts[server_key]);
+      if (rc != MEMCACHED_SUCCESS)
+        continue;
+    }
+
+    protocol_binary_request_getk request= {.bytes= {0}};
+    request.message.header.request.magic= PROTOCOL_BINARY_REQ;
+    if (mget_mode)
+      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETKQ;
+    else
+      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
+
+    memcached_return_t vk;
+    vk= memcached_validate_key_length(key_length[x],
+                                      ptr->flags.binary_protocol);
+    unlikely (vk != MEMCACHED_SUCCESS)
+    {
+      if (x > 0)
+        memcached_io_reset(&ptr->hosts[server_key]);
+      return vk;
+    }
+
+    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((uint32_t) key_length[x]);
+
+    if ((memcached_io_write(&ptr->hosts[server_key], request.bytes,
+                            sizeof(request.bytes), 0) == -1) ||
+        (memcached_io_write(&ptr->hosts[server_key], keys[x],
+                            key_length[x], (char) flush) == -1))
+    {
+      memcached_server_response_reset(&ptr->hosts[server_key]);
+      rc= MEMCACHED_SOME_ERRORS;
+      continue;
+    }
+
+    /* We just want one pending response per server */
+    memcached_server_response_reset(&ptr->hosts[server_key]);
+    memcached_server_response_increment(&ptr->hosts[server_key]);
+    if ((x > 0 && x == ptr->io_key_prefetch) &&
+        memcached_flush_buffers(ptr) != MEMCACHED_SUCCESS)
+      rc= MEMCACHED_SOME_ERRORS;
+  }
+
+  if (mget_mode)
+  {
+    /*
+     * Send a noop command to flush the buffers
+   */
+    protocol_binary_request_noop request= {.bytes= {0}};
+    request.message.header.request.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], NULL, 0, 1) == -1)
+        {
+          memcached_server_response_reset(&ptr->hosts[x]);
+          memcached_io_reset(&ptr->hosts[x]);
+          rc= MEMCACHED_SOME_ERRORS;
+        }
+
+        if (memcached_io_write(&ptr->hosts[x], request.bytes,
+                               sizeof(request.bytes), 1) == -1)
+        {
+          memcached_server_response_reset(&ptr->hosts[x]);
+          memcached_io_reset(&ptr->hosts[x]);
+          rc= MEMCACHED_SOME_ERRORS;
+        }
+      }
+  }
+
+
+  return rc;
+}
+
+static memcached_return_t replication_binary_mget(memcached_st *ptr,
+                                                  uint32_t* hash,
+                                                  bool* dead_servers,
+                                                  const char *const *keys,
+                                                  const size_t *key_length,
+                                                  size_t number_of_keys)
+{
+  memcached_return_t rc= MEMCACHED_NOTFOUND;
+  uint32_t x, start= 0;
+  uint64_t randomize_read= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ);
+
+  if (randomize_read)
+    start= (uint32_t)random() % (uint32_t)(ptr->number_of_replicas + 1);
+
+  /* Loop for each replica */
+  for (uint32_t replica= 0; replica <= ptr->number_of_replicas; ++replica)
+  {
+    bool success= true;
+
+    for (x= 0; x < number_of_keys; ++x)
+    {
+      if (hash[x] == ptr->number_of_hosts)
+        continue; /* Already successfully sent */
+
+      uint32_t server= hash[x] + replica;
+
+      /* In case of randomized reads */
+      if (randomize_read && ((server + start) <= (hash[x] + ptr->number_of_replicas)))
+        server += start;
+
+      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= {
+        .message.header.request= {
+          .magic= PROTOCOL_BINARY_REQ,
+          .opcode= PROTOCOL_BINARY_CMD_GETK,
+          .keylen= htons((uint16_t)key_length[x]),
+          .datatype= PROTOCOL_BINARY_RAW_BYTES,
+          .bodylen= htonl((uint32_t)key_length[x])
+        }
+      };
+
+      /*
+       * We need to disable buffering to actually know that the request was
+       * successfully sent to the server (so that we should expect a result
+       * back). It would be nice to do this in buffered mode, but then it
+       * would be complex to handle all error situations if we got to send
+       * some of the messages, and then we failed on writing out some others
+       * and we used the callback interface from memcached_mget_execute so
+       * that we might have processed some of the responses etc. For now,
+       * just make sure we work _correctly_
+     */
+      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], 1) == -1))
+      {
+        memcached_io_reset(&ptr->hosts[server]);
+        dead_servers[server]= true;
+        success= false;
+        continue;
+      }
+
+      memcached_server_response_increment(&ptr->hosts[server]);
+      hash[x]= ptr->number_of_hosts;
+    }
+
+    if (success)
+      break;
+  }
+
+  return rc;
+}
+
+static memcached_return_t binary_mget_by_key(memcached_st *ptr,
+                                             unsigned int master_server_key,
+                                             bool is_master_key_set,
+                                             const char * const *keys,
+                                             const size_t *key_length,
+                                             size_t number_of_keys,
+                                             bool mget_mode)
+{
+  memcached_return_t 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, mget_mode);
+  }
+  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;
+}
diff --git a/libmemcached/get.h b/libmemcached/get.h
new file mode 100644 (file)
index 0000000..bb04a15
--- /dev/null
@@ -0,0 +1,84 @@
+/* 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: Get functions for libmemcached
+ *
+ */
+
+#ifndef LIBMEMCACHED_MEMCACHED_GET_H
+#define LIBMEMCACHED_MEMCACHED_GET_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Public defines */
+LIBMEMCACHED_API
+char *memcached_get(memcached_st *ptr, 
+                    const char *key, size_t key_length,
+                    size_t *value_length, 
+                    uint32_t *flags,
+                    memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_mget(memcached_st *ptr, 
+                                  const char * const *keys, 
+                                  const size_t *key_length, 
+                                  size_t number_of_keys);
+
+LIBMEMCACHED_API
+char *memcached_get_by_key(memcached_st *ptr, 
+                           const char *master_key, size_t master_key_length, 
+                           const char *key, size_t key_length, 
+                           size_t *value_length, 
+                           uint32_t *flags,
+                           memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_mget_by_key(memcached_st *ptr, 
+                                         const char *master_key, size_t 
+                                         master_key_length,
+                                         const char * const *keys, 
+                                         const size_t *key_length, 
+                                         size_t number_of_keys);
+
+LIBMEMCACHED_API
+char *memcached_fetch(memcached_st *ptr, 
+                      char *key, size_t *key_length, 
+                      size_t *value_length, uint32_t *flags, 
+                      memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_result_st *memcached_fetch_result(memcached_st *ptr, 
+                                            memcached_result_st *result,
+                                            memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_mget_execute(memcached_st *ptr,
+                                          const char * const *keys,
+                                          const size_t *key_length,
+                                          size_t number_of_keys,
+                                          memcached_execute_fn *callback,
+                                          void *context,
+                                          unsigned int number_of_callbacks);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_mget_execute_by_key(memcached_st *ptr,
+                                                 const char *master_key,
+                                                 size_t master_key_length,
+                                                 const char * const *keys,
+                                                 const size_t *key_length,
+                                                 size_t number_of_keys,
+                                                 memcached_execute_fn *callback,
+                                                 void *context,
+                                                 unsigned int number_of_callbacks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBMEMCACHED_MEMCACHED_GET_H */
diff --git a/libmemcached/hash.c b/libmemcached/hash.c
new file mode 100644 (file)
index 0000000..395020a
--- /dev/null
@@ -0,0 +1,234 @@
+#include "common.h"
+
+
+/* Defines */
+static uint64_t FNV_64_INIT= UINT64_C(0xcbf29ce484222325);
+static uint64_t FNV_64_PRIME= UINT64_C(0x100000001b3);
+
+static uint32_t FNV_32_INIT= 2166136261UL;
+static uint32_t FNV_32_PRIME= 16777619;
+
+/* Prototypes */
+static uint32_t internal_generate_hash(const char *key, size_t key_length);
+static uint32_t internal_generate_md5(const char *key, size_t key_length);
+
+uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash_t hash_algorithm)
+{
+  uint32_t hash= 1; /* Just here to remove compile warning */
+  uint32_t x= 0;
+
+  switch (hash_algorithm)
+  {
+  case MEMCACHED_HASH_DEFAULT:
+    hash= internal_generate_hash(key, key_length);
+    break;
+  case MEMCACHED_HASH_MD5:
+    hash= internal_generate_md5(key, key_length);
+    break;
+  case MEMCACHED_HASH_CRC:
+    hash= ((hash_crc32(key, key_length) >> 16) & 0x7fff);
+    if (hash == 0)
+      hash= 1;
+    break;
+    /* FNV hash'es lifted from Dustin Sallings work */
+  case MEMCACHED_HASH_FNV1_64:
+    {
+      /* Thanks to pierre@demartines.com for the pointer */
+      uint64_t temp_hash;
+
+      temp_hash= FNV_64_INIT;
+      for (x= 0; x < key_length; x++)
+      {
+        temp_hash *= FNV_64_PRIME;
+        temp_hash ^= (uint64_t)key[x];
+      }
+      hash= (uint32_t)temp_hash;
+    }
+    break;
+  case MEMCACHED_HASH_FNV1A_64:
+    {
+      hash= (uint32_t) FNV_64_INIT;
+      for (x= 0; x < key_length; x++)
+      {
+        uint32_t val= (uint32_t)key[x];
+        hash ^= val;
+        hash *= (uint32_t) FNV_64_PRIME;
+      }
+    }
+    break;
+  case MEMCACHED_HASH_FNV1_32:
+    {
+      hash= FNV_32_INIT;
+      for (x= 0; x < key_length; x++)
+      {
+        uint32_t val= (uint32_t)key[x];
+        hash *= FNV_32_PRIME;
+        hash ^= val;
+      }
+    }
+    break;
+  case MEMCACHED_HASH_FNV1A_32:
+    {
+      hash= FNV_32_INIT;
+      for (x= 0; x < key_length; x++)
+      {
+        uint32_t val= (uint32_t)key[x];
+        hash ^= val;
+        hash *= FNV_32_PRIME;
+      }
+    }
+    break;
+    case MEMCACHED_HASH_HSIEH:
+    {
+#ifdef HAVE_HSIEH_HASH
+      hash= hsieh_hash(key, key_length);
+#endif
+      break;
+    }
+    case MEMCACHED_HASH_MURMUR:
+    {
+      hash= murmur_hash(key, key_length);
+      break;
+    }
+    case MEMCACHED_HASH_JENKINS:
+    {
+      hash=jenkins_hash(key, key_length, 13);
+      break;
+    }
+    default:
+    {
+      WATCHPOINT_ASSERT(hash_algorithm);
+      break;
+    }
+  }
+  return hash;
+}
+
+uint32_t generate_hash(memcached_st *ptr, const char *key, size_t key_length)
+{
+  uint32_t hash= 1; /* Just here to remove compile warning */
+
+
+  WATCHPOINT_ASSERT(ptr->number_of_hosts);
+
+  if (ptr->number_of_hosts == 1)
+    return 0;
+
+  hash= memcached_generate_hash_value(key, key_length, ptr->hash);
+  WATCHPOINT_ASSERT(hash);
+  return hash;
+}
+
+static uint32_t dispatch_host(memcached_st *ptr, uint32_t hash)
+{
+  switch (ptr->distribution)
+  {
+  case MEMCACHED_DISTRIBUTION_CONSISTENT:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
+    {
+      uint32_t num= ptr->continuum_points_counter;
+      WATCHPOINT_ASSERT(ptr->continuum);
+
+      hash= hash;
+      memcached_continuum_item_st *begin, *end, *left, *right, *middle;
+      begin= left= ptr->continuum;
+      end= right= ptr->continuum + num;
+
+      while (left < right)
+      {
+        middle= left + (right - left) / 2;
+        if (middle->value < hash)
+          left= middle + 1;
+        else
+          right= middle;
+      }
+      if (right == end)
+        right= begin;
+      return right->index;
+    }
+  case MEMCACHED_DISTRIBUTION_MODULA:
+    return hash % ptr->number_of_hosts;
+  case MEMCACHED_DISTRIBUTION_RANDOM:
+    return (uint32_t) random() % ptr->number_of_hosts;
+  default:
+    WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
+    return hash % ptr->number_of_hosts;
+  }
+
+  /* NOTREACHED */
+}
+
+/*
+  One day make this public, and have it return the actual memcached_server_st
+  to the calling application.
+*/
+uint32_t memcached_generate_hash(memcached_st *ptr, const char *key, size_t key_length)
+{
+  uint32_t hash= 1; /* Just here to remove compile warning */
+
+  WATCHPOINT_ASSERT(ptr->number_of_hosts);
+
+  if (ptr->number_of_hosts == 1)
+    return 0;
+
+  if (ptr->flags.hash_with_prefix_key)
+  {
+    size_t temp_length= ptr->prefix_key_length + key_length;
+    char temp[temp_length];
+
+    if (temp_length > MEMCACHED_MAX_KEY -1)
+      return 0;
+
+    strncpy(temp, ptr->prefix_key, ptr->prefix_key_length);
+    strncpy(temp + ptr->prefix_key_length, key, key_length);
+    hash= generate_hash(ptr, temp, temp_length);
+  }
+  else
+  {
+    hash= generate_hash(ptr, key, key_length);
+  }
+
+  WATCHPOINT_ASSERT(hash);
+
+  if (memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS) && ptr->next_distribution_rebuild) {
+    struct timeval now;
+
+    if (gettimeofday(&now, NULL) == 0 &&
+        now.tv_sec > ptr->next_distribution_rebuild)
+      run_distribution(ptr);
+  }
+
+  return dispatch_host(ptr, hash);
+}
+
+static uint32_t internal_generate_hash(const char *key, size_t key_length)
+{
+  const char *ptr= key;
+  uint32_t value= 0;
+
+  while (key_length--)
+  {
+    uint32_t val= (uint32_t) *ptr++;
+    value += val;
+    value += (value << 10);
+    value ^= (value >> 6);
+  }
+  value += (value << 3);
+  value ^= (value >> 11);
+  value += (value << 15);
+
+  return value == 0 ? 1 : (uint32_t) value;
+}
+
+static uint32_t internal_generate_md5(const char *key, size_t key_length)
+{
+  unsigned char results[16];
+
+  md5_signature((unsigned char*)key, (unsigned int)key_length, results);
+
+  return ((uint32_t) (results[3] & 0xFF) << 24)
+    | ((uint32_t) (results[2] & 0xFF) << 16)
+    | ((uint32_t) (results[1] & 0xFF) << 8)
+    | (results[0] & 0xFF);
+}
diff --git a/libmemcached/hosts.c b/libmemcached/hosts.c
new file mode 100644 (file)
index 0000000..8cc5f3e
--- /dev/null
@@ -0,0 +1,514 @@
+#include "common.h"
+#include <math.h>
+
+/* Protoypes (static) */
+static memcached_return_t server_add(memcached_st *ptr, const char *hostname,
+                                     in_port_t port,
+                                     uint32_t weight,
+                                     memcached_connection_t type);
+memcached_return_t update_continuum(memcached_st *ptr);
+
+static int compare_servers(const void *p1, const void *p2)
+{
+  int return_value;
+  memcached_server_st *a= (memcached_server_st *)p1;
+  memcached_server_st *b= (memcached_server_st *)p2;
+
+  return_value= strcmp(a->hostname, b->hostname);
+
+  if (return_value == 0)
+  {
+    return_value= (int) (a->port - b->port);
+  }
+
+  return return_value;
+}
+
+static void sort_hosts(memcached_st *ptr)
+{
+  if (ptr->number_of_hosts)
+  {
+    qsort(ptr->hosts, ptr->number_of_hosts, sizeof(memcached_server_st), compare_servers);
+    ptr->hosts[0].count= (uint16_t) ptr->number_of_hosts;
+  }
+}
+
+
+memcached_return_t run_distribution(memcached_st *ptr)
+{
+  switch (ptr->distribution)
+  {
+  case MEMCACHED_DISTRIBUTION_CONSISTENT:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
+  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
+    return update_continuum(ptr);
+  case MEMCACHED_DISTRIBUTION_MODULA:
+    if (ptr->flags.use_sort_hosts)
+      sort_hosts(ptr);
+    break;
+  case MEMCACHED_DISTRIBUTION_RANDOM:
+    break;
+  default:
+    WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
+  }
+
+  ptr->last_disconnected_server = NULL;
+
+  return MEMCACHED_SUCCESS;
+}
+
+void server_list_free(memcached_st *ptr, memcached_server_st *servers)
+{
+  unsigned int x;
+
+  if (servers == NULL)
+    return;
+
+  for (x= 0; x < servers->count; x++)
+    if (servers[x].address_info)
+    {
+      freeaddrinfo(servers[x].address_info);
+      servers[x].address_info= NULL;
+    }
+
+  if (ptr)
+    ptr->call_free(ptr, servers);
+  else
+    free(servers);
+}
+
+static uint32_t ketama_server_hash(const char *key, unsigned int key_length, int alignment)
+{
+  unsigned char results[16];
+
+  md5_signature((unsigned char*)key, key_length, results);
+  return ((uint32_t) (results[3 + alignment * 4] & 0xFF) << 24)
+    | ((uint32_t) (results[2 + alignment * 4] & 0xFF) << 16)
+    | ((uint32_t) (results[1 + alignment * 4] & 0xFF) << 8)
+    | (results[0 + alignment * 4] & 0xFF);
+}
+
+static int continuum_item_cmp(const void *t1, const void *t2)
+{
+  memcached_continuum_item_st *ct1= (memcached_continuum_item_st *)t1;
+  memcached_continuum_item_st *ct2= (memcached_continuum_item_st *)t2;
+
+  /* Why 153? Hmmm... */
+  WATCHPOINT_ASSERT(ct1->value != 153);
+  if (ct1->value == ct2->value)
+    return 0;
+  else if (ct1->value > ct2->value)
+    return 1;
+  else
+    return -1;
+}
+
+memcached_return_t update_continuum(memcached_st *ptr)
+{
+  uint32_t host_index;
+  uint32_t continuum_index= 0;
+  uint32_t value;
+  memcached_server_st *list;
+  uint32_t pointer_index;
+  uint32_t pointer_counter= 0;
+  uint32_t pointer_per_server= MEMCACHED_POINTS_PER_SERVER;
+  uint32_t pointer_per_hash= 1;
+  uint64_t total_weight= 0;
+  uint64_t is_ketama_weighted= 0;
+  uint64_t is_auto_ejecting= 0;
+  uint32_t points_per_server= 0;
+  uint32_t live_servers= 0;
+  struct timeval now;
+
+  if (gettimeofday(&now, NULL) != 0)
+  {
+    ptr->cached_errno = errno;
+    return MEMCACHED_ERRNO;
+  }
+
+  list = ptr->hosts;
+
+  /* count live servers (those without a retry delay set) */
+  is_auto_ejecting= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS);
+  if (is_auto_ejecting)
+  {
+    live_servers= 0;
+    ptr->next_distribution_rebuild= 0;
+    for (host_index= 0; host_index < ptr->number_of_hosts; ++host_index)
+    {
+      if (list[host_index].next_retry <= now.tv_sec)
+        live_servers++;
+      else
+      {
+        if (ptr->next_distribution_rebuild == 0 || list[host_index].next_retry < ptr->next_distribution_rebuild)
+          ptr->next_distribution_rebuild= list[host_index].next_retry;
+      }
+    }
+  }
+  else
+    live_servers= ptr->number_of_hosts;
+
+  is_ketama_weighted= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED);
+  points_per_server= (uint32_t) (is_ketama_weighted ? MEMCACHED_POINTS_PER_SERVER_KETAMA : MEMCACHED_POINTS_PER_SERVER);
+
+  if (live_servers == 0)
+    return MEMCACHED_SUCCESS;
+
+  if (live_servers > ptr->continuum_count)
+  {
+    memcached_continuum_item_st *new_ptr;
+
+    new_ptr= ptr->call_realloc(ptr, ptr->continuum,
+                               sizeof(memcached_continuum_item_st) * (live_servers + MEMCACHED_CONTINUUM_ADDITION) * points_per_server);
+
+    if (new_ptr == 0)
+      return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+
+    ptr->continuum= new_ptr;
+    ptr->continuum_count= live_servers + MEMCACHED_CONTINUUM_ADDITION;
+  }
+
+  if (is_ketama_weighted)
+  {
+    for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index)
+    {
+      if (list[host_index].weight == 0)
+      {
+        list[host_index].weight = 1;
+      }
+      if (!is_auto_ejecting || list[host_index].next_retry <= now.tv_sec)
+        total_weight += list[host_index].weight;
+    }
+  }
+
+  for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index)
+  {
+    if (is_auto_ejecting && list[host_index].next_retry > now.tv_sec)
+      continue;
+
+    if (is_ketama_weighted)
+    {
+        float pct = (float)list[host_index].weight / (float)total_weight;
+        pointer_per_server= (uint32_t) ((floorf((float) (pct * MEMCACHED_POINTS_PER_SERVER_KETAMA / 4 * (float)live_servers + 0.0000000001))) * 4);
+        pointer_per_hash= 4;
+#ifdef DEBUG
+        printf("ketama_weighted:%s|%d|%llu|%u\n",
+               list[host_index].hostname,
+               list[host_index].port,
+               (unsigned long long)list[host_index].weight,
+               pointer_per_server);
+#endif
+    }
+
+
+    if (ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY)
+    {
+      for (pointer_index= 0;
+           pointer_index < pointer_per_server / pointer_per_hash;
+           pointer_index++)
+      {
+        char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= "";
+        size_t sort_host_length;
+
+        // Spymemcached ketema key format is: hostname/ip:port-index
+        // If hostname is not available then: /ip:port-index
+        sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
+                                            "/%s:%d-%d",
+                                            list[host_index].hostname,
+                                            list[host_index].port,
+                                            pointer_index);
+#ifdef DEBUG
+        printf("update_continuum: key is %s\n", sort_host);
+#endif
+
+        WATCHPOINT_ASSERT(sort_host_length);
+
+        if (is_ketama_weighted)
+        {
+          unsigned int i;
+          for (i = 0; i < pointer_per_hash; i++)
+          {
+             value= ketama_server_hash(sort_host, (uint32_t) sort_host_length, (int) i);
+             ptr->continuum[continuum_index].index= host_index;
+             ptr->continuum[continuum_index++].value= value;
+          }
+        }
+        else
+        {
+          value= memcached_generate_hash_value(sort_host, sort_host_length, ptr->hash_continuum);
+          ptr->continuum[continuum_index].index= host_index;
+          ptr->continuum[continuum_index++].value= value;
+        }
+      }
+    }
+    else
+    {
+      for (pointer_index= 1;
+           pointer_index <= pointer_per_server / pointer_per_hash;
+           pointer_index++)
+      {
+        char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= "";
+        size_t sort_host_length;
+
+        if (list[host_index].port == MEMCACHED_DEFAULT_PORT)
+        {
+          sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
+                                              "%s-%d",
+                                              list[host_index].hostname,
+                                              pointer_index - 1);
+        }
+        else
+        {
+          sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
+                                              "%s:%d-%d",
+                                              list[host_index].hostname,
+                                              list[host_index].port, pointer_index - 1);
+        }
+
+        WATCHPOINT_ASSERT(sort_host_length);
+
+        if (is_ketama_weighted)
+        {
+          unsigned int i;
+          for (i = 0; i < pointer_per_hash; i++)
+          {
+             value= ketama_server_hash(sort_host, (uint32_t) sort_host_length, (int) i);
+             ptr->continuum[continuum_index].index= host_index;
+             ptr->continuum[continuum_index++].value= value;
+          }
+        }
+        else
+        {
+          value= memcached_generate_hash_value(sort_host, sort_host_length, ptr->hash_continuum);
+          ptr->continuum[continuum_index].index= host_index;
+          ptr->continuum[continuum_index++].value= value;
+        }
+      }
+    }
+
+    pointer_counter+= pointer_per_server;
+  }
+
+  WATCHPOINT_ASSERT(ptr);
+  WATCHPOINT_ASSERT(ptr->continuum);
+  WATCHPOINT_ASSERT(ptr->number_of_hosts * MEMCACHED_POINTS_PER_SERVER <= MEMCACHED_CONTINUUM_SIZE);
+  ptr->continuum_points_counter= pointer_counter;
+  qsort(ptr->continuum, ptr->continuum_points_counter, sizeof(memcached_continuum_item_st), continuum_item_cmp);
+
+#ifdef DEBUG
+  for (pointer_index= 0; ptr->number_of_hosts && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++)
+  {
+    WATCHPOINT_ASSERT(ptr->continuum[pointer_index].value <= ptr->continuum[pointer_index + 1].value);
+  }
+#endif
+
+  return MEMCACHED_SUCCESS;
+}
+
+
+memcached_return_t memcached_server_push(memcached_st *ptr, memcached_server_st *list)
+{
+  unsigned int x;
+  uint16_t count;
+  memcached_server_st *new_host_list;
+
+  if (!list)
+    return MEMCACHED_SUCCESS;
+
+  count= list[0].count;
+  new_host_list= ptr->call_realloc(ptr, ptr->hosts,
+                                   sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
+
+  if (!new_host_list)
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+
+  ptr->hosts= new_host_list;
+
+  for (x= 0; x < count; x++)
+  {
+    if ((ptr->flags.use_udp && list[x].type != MEMCACHED_CONNECTION_UDP)
+            || ((list[x].type == MEMCACHED_CONNECTION_UDP)
+            && ! (ptr->flags.use_udp)) )
+      return MEMCACHED_INVALID_HOST_PROTOCOL;
+
+    WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
+    memcached_server_create(ptr, &ptr->hosts[ptr->number_of_hosts]);
+    /* TODO check return type */
+    (void)memcached_server_create_with(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname,
+                                       list[x].port, list[x].weight, list[x].type);
+    ptr->number_of_hosts++;
+  }
+  ptr->hosts[0].count= (uint16_t) ptr->number_of_hosts;
+
+  return run_distribution(ptr);
+}
+
+memcached_return_t memcached_server_add_unix_socket(memcached_st *ptr,
+                                                    const char *filename)
+{
+  return memcached_server_add_unix_socket_with_weight(ptr, filename, 0);
+}
+
+memcached_return_t memcached_server_add_unix_socket_with_weight(memcached_st *ptr,
+                                                                const char *filename,
+                                                                uint32_t weight)
+{
+  if (!filename)
+    return MEMCACHED_FAILURE;
+
+  return server_add(ptr, filename, 0, weight, MEMCACHED_CONNECTION_UNIX_SOCKET);
+}
+
+memcached_return_t memcached_server_add_udp(memcached_st *ptr,
+                                            const char *hostname,
+                                            in_port_t port)
+{
+  return memcached_server_add_udp_with_weight(ptr, hostname, port, 0);
+}
+
+memcached_return_t memcached_server_add_udp_with_weight(memcached_st *ptr,
+                                                        const char *hostname,
+                                                        in_port_t port,
+                                                        uint32_t weight)
+{
+  if (!port)
+    port= MEMCACHED_DEFAULT_PORT;
+
+  if (!hostname)
+    hostname= "localhost";
+
+  return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_UDP);
+}
+
+memcached_return_t memcached_server_add(memcached_st *ptr,
+                                        const char *hostname,
+                                        in_port_t port)
+{
+  return memcached_server_add_with_weight(ptr, hostname, port, 0);
+}
+
+memcached_return_t memcached_server_add_with_weight(memcached_st *ptr,
+                                                    const char *hostname,
+                                                    in_port_t port,
+                                                    uint32_t weight)
+{
+  if (!port)
+    port= MEMCACHED_DEFAULT_PORT;
+
+  if (!hostname)
+    hostname= "localhost";
+
+  return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_TCP);
+}
+
+static memcached_return_t server_add(memcached_st *ptr, const char *hostname,
+                                     in_port_t port,
+                                     uint32_t weight,
+                                     memcached_connection_t type)
+{
+  memcached_server_st *new_host_list;
+
+  if ( (ptr->flags.use_udp && type != MEMCACHED_CONNECTION_UDP)
+      || ( (type == MEMCACHED_CONNECTION_UDP) && (! ptr->flags.use_udp) ) )
+    return MEMCACHED_INVALID_HOST_PROTOCOL;
+
+  new_host_list= ptr->call_realloc(ptr, ptr->hosts,
+                                   sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
+
+  if (new_host_list == NULL)
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+
+  ptr->hosts= new_host_list;
+
+  /* TODO: Check return type */
+  (void)memcached_server_create_with(ptr, &ptr->hosts[ptr->number_of_hosts], hostname, port, weight, type);
+  ptr->number_of_hosts++;
+  ptr->hosts[0].count= (uint16_t) ptr->number_of_hosts;
+
+  return run_distribution(ptr);
+}
+
+memcached_return_t memcached_server_remove(memcached_server_st *st_ptr)
+{
+  uint32_t x, host_index;
+  memcached_st *ptr= st_ptr->root;
+  memcached_server_st *list= ptr->hosts;
+
+  for (x= 0, host_index= 0; x < ptr->number_of_hosts; x++)
+  {
+    if (strncmp(list[x].hostname, st_ptr->hostname, MEMCACHED_MAX_HOST_LENGTH) != 0 || list[x].port != st_ptr->port)
+    {
+      if (host_index != x)
+        memcpy(list+host_index, list+x, sizeof(memcached_server_st));
+      host_index++;
+    }
+  }
+  ptr->number_of_hosts= host_index;
+
+  if (st_ptr->address_info)
+  {
+    freeaddrinfo(st_ptr->address_info);
+    st_ptr->address_info= NULL;
+  }
+  run_distribution(ptr);
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_server_st *memcached_server_list_append(memcached_server_st *ptr,
+                                                  const char *hostname, in_port_t port,
+                                                  memcached_return_t *error)
+{
+  return memcached_server_list_append_with_weight(ptr, hostname, port, 0, error);
+}
+
+memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr,
+                                                              const char *hostname, in_port_t port,
+                                                              uint32_t weight,
+                                                              memcached_return_t *error)
+{
+  unsigned int count;
+  memcached_server_st *new_host_list;
+
+  if (hostname == NULL || error == NULL)
+    return NULL;
+
+  if (!port)
+    port= MEMCACHED_DEFAULT_PORT;
+
+  /* Increment count for hosts */
+  count= 1;
+  if (ptr != NULL)
+  {
+    count+= ptr[0].count;
+  }
+
+  new_host_list= (memcached_server_st *)realloc(ptr, sizeof(memcached_server_st) * count);
+  if (!new_host_list)
+  {
+    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return NULL;
+  }
+
+  /* TODO: Check return type */
+  memcached_server_create_with(NULL, &new_host_list[count-1], hostname, port, weight, MEMCACHED_CONNECTION_TCP);
+
+  /* Backwards compatibility hack */
+  new_host_list[0].count= (uint16_t) count;
+
+  *error= MEMCACHED_SUCCESS;
+  return new_host_list;
+}
+
+unsigned int memcached_server_list_count(memcached_server_st *ptr)
+{
+  if (ptr == NULL)
+    return 0;
+
+  return ptr[0].count;
+}
+
+void memcached_server_list_free(memcached_server_st *ptr)
+{
+  server_list_free(NULL, ptr);
+}
diff --git a/libmemcached/internal.h b/libmemcached/internal.h
new file mode 100644 (file)
index 0000000..3e4415d
--- /dev/null
@@ -0,0 +1,35 @@
+/* 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: Internal functions used by the library. Not for public use!
+ *
+ */
+
+#ifndef LIBMEMCACHED_MEMCACHED_INTERNAL_H
+#define LIBMEMCACHED_MEMCACHED_INTERNAL_H
+
+#if defined(BUILDING_LIBMEMCACHED)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+LIBMEMCACHED_LOCAL
+void libmemcached_free(memcached_st *ptr, void *mem);
+LIBMEMCACHED_LOCAL
+void *libmemcached_malloc(memcached_st *ptr, const size_t size);
+LIBMEMCACHED_LOCAL
+void *libmemcached_realloc(memcached_st *ptr, void *mem, const size_t size);
+LIBMEMCACHED_LOCAL
+void *libmemcached_calloc(memcached_st *ptr, size_t nelem, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BUILDING_LIBMEMCACHED */
+#endif /* LIBMEMCACHED_MEMCACHED_INTERNAL_H */
diff --git a/libmemcached/io.c b/libmemcached/io.c
new file mode 100644 (file)
index 0000000..8f96bc3
--- /dev/null
@@ -0,0 +1,643 @@
+/* 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: Server IO, Not public!
+ *
+ */
+
+
+#include "common.h"
+#include <sys/select.h>
+#include <poll.h>
+
+typedef enum {
+  MEM_READ,
+  MEM_WRITE
+} memc_read_or_write;
+
+static ssize_t io_flush(memcached_server_st *ptr, memcached_return_t *error);
+static void increment_udp_message_id(memcached_server_st *ptr);
+
+static memcached_return_t io_wait(memcached_server_st *ptr,
+                                  memc_read_or_write read_or_write)
+{
+  struct pollfd fds= {
+    .fd= ptr->fd,
+    .events = POLLIN
+  };
+  int error;
+
+  unlikely (read_or_write == MEM_WRITE) /* write */
+    fds.events= POLLOUT;
+
+  /*
+   ** We are going to block on write, but at least on Solaris we might block
+   ** on write if we haven't read anything from our input buffer..
+   ** Try to purge the input buffer if we don't do any flow control in the
+   ** application layer (just sending a lot of data etc)
+   ** The test is moved down in the purge function to avoid duplication of
+   ** the test.
+ */
+  if (read_or_write == MEM_WRITE)
+  {
+    memcached_return_t rc= memcached_purge(ptr);
+    if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_STORED)
+      return MEMCACHED_FAILURE;
+  }
+
+  int timeout= ptr->root->poll_timeout;
+  if (ptr->root->flags.no_block == false)
+    timeout= -1;
+
+  error= poll(&fds, 1, timeout);
+
+  if (error == 1)
+    return MEMCACHED_SUCCESS;
+  else if (error == 0)
+    return MEMCACHED_TIMEOUT;
+
+  /* Imposssible for anything other then -1 */
+  WATCHPOINT_ASSERT(error == -1);
+  memcached_quit_server(ptr, 1);
+
+  return MEMCACHED_FAILURE;
+}
+
+/**
+ * Try to fill the input buffer for a server with as much
+ * data as possible.
+ *
+ * @param ptr the server to pack
+ */
+static bool repack_input_buffer(memcached_server_st *ptr)
+{
+  if (ptr->read_ptr != ptr->read_buffer)
+  {
+    /* Move all of the data to the beginning of the buffer so
+     ** that we can fit more data into the buffer...
+   */
+    memmove(ptr->read_buffer, ptr->read_ptr, ptr->read_buffer_length);
+    ptr->read_ptr= ptr->read_buffer;
+    ptr->read_data_length= ptr->read_buffer_length;
+  }
+
+  /* There is room in the buffer, try to fill it! */
+  if (ptr->read_buffer_length != MEMCACHED_MAX_BUFFER)
+  {
+    /* Just try a single read to grab what's available */
+    ssize_t nr= read(ptr->fd,
+                     ptr->read_ptr + ptr->read_data_length,
+                     MEMCACHED_MAX_BUFFER - ptr->read_data_length);
+
+    if (nr > 0)
+    {
+      ptr->read_data_length+= (size_t)nr;
+      ptr->read_buffer_length+= (size_t)nr;
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
+ * If the we have callbacks connected to this server structure
+ * we may start process the input queue and fire the callbacks
+ * for the incomming messages. This function is _only_ called
+ * when the input buffer is full, so that we _know_ that we have
+ * at least _one_ message to process.
+ *
+ * @param ptr the server to star processing iput messages for
+ * @return true if we processed anything, false otherwise
+ */
+static bool process_input_buffer(memcached_server_st *ptr)
+{
+  /*
+   ** We might be able to process some of the response messages if we
+   ** have a callback set up
+ */
+  if (ptr->root->callbacks != NULL && ptr->root->flags.use_udp == false)
+  {
+    /*
+     * We might have responses... try to read them out and fire
+     * callbacks
+   */
+    memcached_callback_st cb= *ptr->root->callbacks;
+
+    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+    memcached_return_t error;
+    error= memcached_response(ptr, buffer, sizeof(buffer),
+                              &ptr->root->result);
+    if (error == MEMCACHED_SUCCESS)
+    {
+      for (unsigned int x= 0; x < cb.number_of_callback; x++)
+      {
+        error= (*cb.callback[x])(ptr->root, &ptr->root->result, cb.context);
+        if (error != MEMCACHED_SUCCESS)
+          break;
+      }
+
+      /* @todo what should I do with the error message??? */
+    }
+    /* @todo what should I do with other error messages?? */
+    return true;
+  }
+
+  return false;
+}
+
+#ifdef UNUSED
+void memcached_io_preread(memcached_st *ptr)
+{
+  unsigned int x;
+
+  return;
+
+  for (x= 0; x < ptr->number_of_hosts; x++)
+  {
+    if (memcached_server_response_count(ptr, x) &&
+        ptr->hosts[x].read_data_length < MEMCACHED_MAX_BUFFER )
+    {
+      size_t data_read;
+
+      data_read= read(ptr->hosts[x].fd,
+                      ptr->hosts[x].read_ptr + ptr->hosts[x].read_data_length,
+                      MEMCACHED_MAX_BUFFER - ptr->hosts[x].read_data_length);
+      if (data_read == -1)
+        continue;
+
+      ptr->hosts[x].read_buffer_length+= data_read;
+      ptr->hosts[x].read_data_length+= data_read;
+    }
+  }
+}
+#endif
+
+memcached_return_t memcached_io_read(memcached_server_st *ptr,
+                                     void *buffer, size_t length, ssize_t *nread)
+{
+  char *buffer_ptr;
+
+  buffer_ptr= buffer;
+
+  while (length)
+  {
+    if (!ptr->read_buffer_length)
+    {
+      ssize_t data_read;
+
+      while (1)
+      {
+        data_read= read(ptr->fd, ptr->read_buffer, MEMCACHED_MAX_BUFFER);
+        if (data_read > 0)
+          break;
+        else if (data_read == -1)
+        {
+          ptr->cached_errno= errno;
+          memcached_return_t rc= MEMCACHED_UNKNOWN_READ_FAILURE;
+          switch (errno)
+          {
+          case EAGAIN:
+          case EINTR:
+            if ((rc= io_wait(ptr, MEM_READ)) == MEMCACHED_SUCCESS)
+              continue;
+            /* fall through */
+
+          default:
+            {
+              memcached_quit_server(ptr, 1);
+              *nread= -1;
+              return rc;
+            }
+          }
+        }
+        else
+        {
+          /*
+            EOF. Any data received so far is incomplete
+            so discard it. This always reads by byte in case of TCP
+            and protocol enforcement happens at memcached_response()
+            looking for '\n'. We do not care for UDB which requests 8 bytes
+            at once. Generally, this means that connection went away. Since
+            for blocking I/O we do not return 0 and for non-blocking case
+            it will return EGAIN if data is not immediatly available.
+          */
+          memcached_quit_server(ptr, 1);
+          *nread= -1;
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+        }
+      }
+
+      ptr->io_bytes_sent = 0;
+      ptr->read_data_length= (size_t) data_read;
+      ptr->read_buffer_length= (size_t) data_read;
+      ptr->read_ptr= ptr->read_buffer;
+    }
+
+    if (length > 1)
+    {
+      size_t difference;
+
+      difference= (length > ptr->read_buffer_length) ? ptr->read_buffer_length : length;
+
+      memcpy(buffer_ptr, ptr->read_ptr, difference);
+      length -= difference;
+      ptr->read_ptr+= difference;
+      ptr->read_buffer_length-= difference;
+      buffer_ptr+= difference;
+    }
+    else
+    {
+      *buffer_ptr= *ptr->read_ptr;
+      ptr->read_ptr++;
+      ptr->read_buffer_length--;
+      buffer_ptr++;
+      break;
+    }
+  }
+
+  ptr->server_failure_counter= 0;
+  *nread = (ssize_t)(buffer_ptr - (char*)buffer);
+  return MEMCACHED_SUCCESS;
+}
+
+ssize_t memcached_io_write(memcached_server_st *ptr,
+                           const void *buffer, size_t length, char with_flush)
+{
+  size_t original_length;
+  const char* buffer_ptr;
+
+  WATCHPOINT_ASSERT(ptr->fd != -1);
+
+  original_length= length;
+  buffer_ptr= buffer;
+
+  while (length)
+  {
+    char *write_ptr;
+    size_t should_write;
+    size_t buffer_end;
+
+    if (ptr->type == MEMCACHED_CONNECTION_UDP)
+    {
+      //UDP does not support partial writes
+      buffer_end= MAX_UDP_DATAGRAM_LENGTH;
+      should_write= length;
+      if (ptr->write_buffer_offset + should_write > buffer_end)
+        return -1;
+    }
+    else
+    {
+      buffer_end= MEMCACHED_MAX_BUFFER;
+      should_write= buffer_end - ptr->write_buffer_offset;
+      should_write= (should_write < length) ? should_write : length;
+    }
+
+    write_ptr= ptr->write_buffer + ptr->write_buffer_offset;
+    memcpy(write_ptr, buffer_ptr, should_write);
+    ptr->write_buffer_offset+= should_write;
+    buffer_ptr+= should_write;
+    length-= should_write;
+
+    if (ptr->write_buffer_offset == buffer_end && ptr->type != MEMCACHED_CONNECTION_UDP)
+    {
+      memcached_return_t rc;
+      ssize_t sent_length;
+
+      WATCHPOINT_ASSERT(ptr->fd != -1);
+      sent_length= io_flush(ptr, &rc);
+      if (sent_length == -1)
+        return -1;
+
+      /* If io_flush calls memcached_purge, sent_length may be 0 */
+      unlikely (sent_length != 0)
+      {
+        WATCHPOINT_ASSERT(sent_length == (ssize_t)buffer_end);
+      }
+    }
+  }
+
+  if (with_flush)
+  {
+    memcached_return_t rc;
+    WATCHPOINT_ASSERT(ptr->fd != -1);
+    if (io_flush(ptr, &rc) == -1)
+      return -1;
+  }
+
+  return (ssize_t) original_length;
+}
+
+memcached_return_t memcached_io_close(memcached_server_st *ptr)
+{
+  int r;
+
+  if (ptr->fd == -1)
+    return MEMCACHED_SUCCESS;
+
+  /* in case of death shutdown to avoid blocking at close() */
+  if (1)
+  {
+    r= shutdown(ptr->fd, SHUT_RDWR);
+
+#ifdef DEBUG
+    if (r && errno != ENOTCONN)
+    {
+      WATCHPOINT_NUMBER(ptr->fd);
+      WATCHPOINT_ERRNO(errno);
+      WATCHPOINT_ASSERT(errno);
+    }
+#endif
+  }
+
+  r= close(ptr->fd);
+#ifdef DEBUG
+  if (r != 0)
+    WATCHPOINT_ERRNO(errno);
+#endif
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_server_st *memcached_io_get_readable_server(memcached_st *memc)
+{
+#define MAX_SERVERS_TO_POLL 100
+  struct pollfd fds[MAX_SERVERS_TO_POLL];
+  unsigned int host_index= 0;
+
+  for (unsigned int x= 0;
+       x< memc->number_of_hosts && host_index < MAX_SERVERS_TO_POLL;
+       ++x)
+  {
+    if (memc->hosts[x].read_buffer_length > 0) /* I have data in the buffer */
+      return &memc->hosts[x];
+
+    if (memcached_server_response_count(&memc->hosts[x]) > 0)
+    {
+      fds[host_index].events = POLLIN;
+      fds[host_index].revents = 0;
+      fds[host_index].fd = memc->hosts[x].fd;
+      ++host_index;
+    }
+  }
+
+  if (host_index < 2)
+  {
+    /* We have 0 or 1 server with pending events.. */
+    for (unsigned int x= 0; x< memc->number_of_hosts; ++x)
+      if (memcached_server_response_count(&memc->hosts[x]) > 0)
+        return &memc->hosts[x];
+
+    return NULL;
+  }
+
+  int err= poll(fds, host_index, memc->poll_timeout);
+  switch (err) {
+  case -1:
+    memc->cached_errno = errno;
+    /* FALLTHROUGH */
+  case 0:
+    break;
+  default:
+    for (unsigned int x= 0; x < host_index; ++x)
+      if (fds[x].revents & POLLIN)
+        for (unsigned int y= 0; y < memc->number_of_hosts; ++y)
+          if (memc->hosts[y].fd == fds[x].fd)
+            return &memc->hosts[y];
+  }
+
+  return NULL;
+}
+
+static ssize_t io_flush(memcached_server_st *ptr,
+                        memcached_return_t *error)
+{
+  /*
+   ** We might want to purge the input buffer if we haven't consumed
+   ** any output yet... The test for the limits is the purge is inline
+   ** in the purge function to avoid duplicating the logic..
+ */
+  {
+    memcached_return_t rc;
+    WATCHPOINT_ASSERT(ptr->fd != -1);
+    rc= memcached_purge(ptr);
+
+    if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_STORED)
+      return -1;
+  }
+  ssize_t sent_length;
+  size_t return_length;
+  char *local_write_ptr= ptr->write_buffer;
+  size_t write_length= ptr->write_buffer_offset;
+
+  *error= MEMCACHED_SUCCESS;
+
+  WATCHPOINT_ASSERT(ptr->fd != -1);
+
+  // UDP Sanity check, make sure that we are not sending somthing too big
+  if (ptr->type == MEMCACHED_CONNECTION_UDP && write_length > MAX_UDP_DATAGRAM_LENGTH)
+    return -1;
+
+  if (ptr->write_buffer_offset == 0 || (ptr->type == MEMCACHED_CONNECTION_UDP
+                                        && ptr->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH))
+    return 0;
+
+  /* Looking for memory overflows */
+#if defined(DEBUG)
+  if (write_length == MEMCACHED_MAX_BUFFER)
+    WATCHPOINT_ASSERT(ptr->write_buffer == local_write_ptr);
+  WATCHPOINT_ASSERT((ptr->write_buffer + MEMCACHED_MAX_BUFFER) >= (local_write_ptr + write_length));
+#endif
+
+  return_length= 0;
+  while (write_length)
+  {
+    WATCHPOINT_ASSERT(ptr->fd != -1);
+    WATCHPOINT_ASSERT(write_length > 0);
+    sent_length= 0;
+    if (ptr->type == MEMCACHED_CONNECTION_UDP)
+      increment_udp_message_id(ptr);
+    sent_length= write(ptr->fd, local_write_ptr, write_length);
+
+    if (sent_length == -1)
+    {
+      ptr->cached_errno= errno;
+      switch (errno)
+      {
+      case ENOBUFS:
+        continue;
+      case EAGAIN:
+        {
+          /*
+           * We may be blocked on write because the input buffer
+           * is full. Let's check if we have room in our input
+           * buffer for more data and retry the write before
+           * waiting..
+         */
+          if (repack_input_buffer(ptr) ||
+              process_input_buffer(ptr))
+            continue;
+
+          memcached_return_t rc;
+          rc= io_wait(ptr, MEM_WRITE);
+
+          if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_TIMEOUT)
+            continue;
+
+          memcached_quit_server(ptr, 1);
+          return -1;
+        }
+      default:
+        memcached_quit_server(ptr, 1);
+        *error= MEMCACHED_ERRNO;
+        return -1;
+      }
+    }
+
+    if (ptr->type == MEMCACHED_CONNECTION_UDP &&
+        (size_t)sent_length != write_length)
+    {
+      memcached_quit_server(ptr, 1);
+      return -1;
+    }
+
+    ptr->io_bytes_sent += (uint32_t) sent_length;
+
+    local_write_ptr+= sent_length;
+    write_length-= (uint32_t) sent_length;
+    return_length+= (uint32_t) sent_length;
+  }
+
+  WATCHPOINT_ASSERT(write_length == 0);
+  // Need to study this assert() WATCHPOINT_ASSERT(return_length ==
+  // ptr->write_buffer_offset);
+
+  // if we are a udp server, the begining of the buffer is reserverd for
+  // the upd frame header
+  if (ptr->type == MEMCACHED_CONNECTION_UDP)
+    ptr->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
+  else
+    ptr->write_buffer_offset= 0;
+
+  return (ssize_t) return_length;
+}
+
+/*
+  Eventually we will just kill off the server with the problem.
+*/
+void memcached_io_reset(memcached_server_st *ptr)
+{
+  memcached_quit_server(ptr, 1);
+}
+
+/**
+ * Read a given number of bytes from the server and place it into a specific
+ * buffer. Reset the IO channel on this server if an error occurs.
+ */
+memcached_return_t memcached_safe_read(memcached_server_st *ptr,
+                                       void *dta,
+                                       size_t size)
+{
+  size_t offset= 0;
+  char *data= dta;
+
+  while (offset < size)
+  {
+    ssize_t nread;
+    memcached_return_t rc= memcached_io_read(ptr, data + offset, size - offset,
+                                             &nread);
+    if (rc != MEMCACHED_SUCCESS)
+      return rc;
+
+    offset+= (size_t) nread;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_io_readline(memcached_server_st *ptr,
+                                         char *buffer_ptr,
+                                         size_t size)
+{
+  bool line_complete= false;
+  size_t total_nr= 0;
+
+  while (!line_complete)
+  {
+    if (ptr->read_buffer_length == 0)
+    {
+      /*
+       * We don't have any data in the buffer, so let's fill the read
+       * buffer. Call the standard read function to avoid duplicating
+       * the logic.
+     */
+      ssize_t nread;
+      memcached_return_t rc= memcached_io_read(ptr, buffer_ptr, 1, &nread);
+      if (rc != MEMCACHED_SUCCESS)
+        return rc;
+
+      if (*buffer_ptr == '\n')
+        line_complete= true;
+
+      ++buffer_ptr;
+      ++total_nr;
+    }
+
+    /* Now let's look in the buffer and copy as we go! */
+    while (ptr->read_buffer_length && total_nr < size && !line_complete)
+    {
+      *buffer_ptr = *ptr->read_ptr;
+      if (*buffer_ptr == '\n')
+        line_complete = true;
+      --ptr->read_buffer_length;
+      ++ptr->read_ptr;
+      ++total_nr;
+      ++buffer_ptr;
+    }
+
+    if (total_nr == size)
+      return MEMCACHED_PROTOCOL_ERROR;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+/*
+ * The udp request id consists of two seperate sections
+ *   1) The thread id
+ *   2) The message number
+ * The thread id should only be set when the memcached_st struct is created
+ * and should not be changed.
+ *
+ * The message num is incremented for each new message we send, this function
+ * extracts the message number from message_id, increments it and then
+ * writes the new value back into the header
+ */
+static void increment_udp_message_id(memcached_server_st *ptr)
+{
+  struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
+  uint16_t cur_req= get_udp_datagram_request_id(header);
+  int msg_num= get_msg_num_from_request_id(cur_req);
+  int thread_id= get_thread_id_from_request_id(cur_req);
+
+  if (((++msg_num) & UDP_REQUEST_ID_THREAD_MASK) != 0)
+    msg_num= 0;
+
+  header->request_id= htons((uint16_t) (thread_id | msg_num));
+}
+
+memcached_return_t memcached_io_init_udp_header(memcached_server_st *ptr, uint16_t thread_id)
+{
+  if (thread_id > UDP_REQUEST_ID_MAX_THREAD_ID)
+    return MEMCACHED_FAILURE;
+
+  struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
+  header->request_id= htons((uint16_t) (generate_udp_request_thread_id(thread_id)));
+  header->num_datagrams= htons(1);
+  header->sequence_number= htons(0);
+
+  return MEMCACHED_SUCCESS;
+}
diff --git a/libmemcached/io.h b/libmemcached/io.h
new file mode 100644 (file)
index 0000000..03d63b5
--- /dev/null
@@ -0,0 +1,71 @@
+/* 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: Server IO, Not public!
+ *
+ */
+
+#ifndef LIBMEMCACHED_MEMCACHED_IO_H
+#define LIBMEMCACHED_MEMCACHED_IO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(BUILDING_LIBMEMCACHED)
+
+#include "libmemcached/memcached.h"
+
+#define MAX_UDP_DATAGRAM_LENGTH 1400
+#define UDP_DATAGRAM_HEADER_LENGTH 8
+#define UDP_REQUEST_ID_MSG_SIG_DIGITS 10
+#define UDP_REQUEST_ID_THREAD_MASK 0xFFFF << UDP_REQUEST_ID_MSG_SIG_DIGITS
+#define get_udp_datagram_request_id(A) ntohs((A)->request_id)
+#define get_udp_datagram_seq_num(A) ntohs((A)->sequence_number)
+#define get_udp_datagram_num_datagrams(A) ntohs((A)->num_datagrams)
+#define get_msg_num_from_request_id(A) ( (A) & (~(UDP_REQUEST_ID_THREAD_MASK)) )
+#define get_thread_id_from_request_id(A) ( (A) & (UDP_REQUEST_ID_THREAD_MASK) ) >> UDP_REQUEST_ID_MSG_SIG_DIGITS
+#define generate_udp_request_thread_id(A) (A) << UDP_REQUEST_ID_MSG_SIG_DIGITS
+#define UDP_REQUEST_ID_MAX_THREAD_ID get_thread_id_from_request_id(0xFFFF)
+
+struct udp_datagram_header_st {
+  uint16_t request_id;
+  uint16_t sequence_number;
+  uint16_t num_datagrams;
+  uint16_t reserved;
+};
+
+ssize_t memcached_io_write(memcached_server_st *ptr,
+                           const void *buffer, size_t length, char with_flush);
+void memcached_io_reset(memcached_server_st *ptr);
+memcached_return_t memcached_io_read(memcached_server_st *ptr,
+                                     void *buffer, size_t length, ssize_t *nread);
+/* Read a line (terminated by '\n') into the buffer */
+memcached_return_t memcached_io_readline(memcached_server_st *ptr,
+                                         char *buffer_ptr,
+                                         size_t size);
+memcached_return_t memcached_io_close(memcached_server_st *ptr);
+/* Read n bytes of data from the server and store them in dta */
+memcached_return_t memcached_safe_read(memcached_server_st *ptr, 
+                                       void *dta, 
+                                       size_t size);
+/* Read a single response from the server */
+memcached_return_t memcached_read_one_response(memcached_server_st *ptr,
+                                               char *buffer, size_t buffer_length,
+                                               memcached_result_st *result);
+memcached_return_t memcached_io_init_udp_header(memcached_server_st *ptr,
+                                                uint16_t thread_id);
+
+memcached_server_st *memcached_io_get_readable_server(memcached_st *memc);
+
+#endif /* BUILDING_LIBMEMCACHED */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBMEMCACHED_MEMCACHED_IO_H */
diff --git a/libmemcached/key.c b/libmemcached/key.c
new file mode 100644 (file)
index 0000000..3b16b27
--- /dev/null
@@ -0,0 +1,27 @@
+#include "common.h"
+
+memcached_return_t memcached_key_test(const char * const *keys, 
+                                      const size_t *key_length, 
+                                      size_t number_of_keys)
+{
+  uint32_t x;
+  memcached_return_t rc;
+
+  for (x= 0; x < number_of_keys; x++)
+  {
+    size_t y;
+
+    rc= memcached_validate_key_length(*(key_length + x), false);
+    if (rc != MEMCACHED_SUCCESS)
+      return rc;
+    
+    for (y= 0; y < *(key_length + x); y++)
+    {
+      if ((isgraph(keys[x][y])) == 0)
+        return MEMCACHED_BAD_KEY_PROVIDED;
+    }
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
index 39158498c1bbbe53b468eb5145c93386324cf09a..efe16e0c4a3828c3ae9589da21af603642acfd6b 100644 (file)
 
 #include <libmemcached/visibility.h>
 #include <libmemcached/memcached_configure.h>
-#include <libmemcached/memcached_constants.h>
-#include <libmemcached/memcached_types.h>
-#include <libmemcached/memcached_behavior.h>
-#include <libmemcached/memcached_callback.h>
-#include <libmemcached/memcached_get.h>
-#include <libmemcached/memcached_server.h>
-#include <libmemcached/memcached_string.h>
-#include <libmemcached/memcached_result.h>
-#include <libmemcached/memcached_storage.h>
+#include <libmemcached/constants.h>
+#include <libmemcached/types.h>
+#include <libmemcached/string.h>
+// Everything above this line must be in the order specified.
+#include <libmemcached/behavior.h>
+#include <libmemcached/callback.h>
+#include <libmemcached/get.h>
+#include <libmemcached/result.h>
+#include <libmemcached/server.h>
+#include <libmemcached/storage.h>
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/libmemcached/memcached_allocators.c b/libmemcached/memcached_allocators.c
deleted file mode 100644 (file)
index 767371c..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "common.h"
-
-void libmemcached_free(memcached_st *ptr, void *mem)
-{
-  (void) ptr;
-  free(mem);
-}
-
-void *libmemcached_malloc(memcached_st *ptr, size_t size)
-{
-  (void) ptr;
-  return malloc(size);
-}
-
-void *libmemcached_realloc(memcached_st *ptr, void *mem, size_t size)
-{
-  (void) ptr;
-  return realloc(mem, size);
-}
-
-void *libmemcached_calloc(memcached_st *ptr, size_t nelem, size_t size)
-{
-  if (ptr->call_malloc != libmemcached_malloc)
-  {
-     void *ret = libmemcached_malloc(ptr, nelem * size);
-     if (ret != NULL) 
-       memset(ret, 0, nelem * size);
-
-     return ret;
-  }
-
-  return calloc(nelem, size);
-}
-
-memcached_return_t memcached_set_memory_allocators(memcached_st *ptr,
-                                                   memcached_malloc_fn mem_malloc,
-                                                   memcached_free_fn mem_free,
-                                                   memcached_realloc_fn mem_realloc,
-                                                   memcached_calloc_fn mem_calloc)
-{
-  /* All should be set, or none should be set */
-  if (mem_malloc == NULL && mem_free == NULL && mem_realloc == NULL && mem_calloc == NULL) 
-  {
-    ptr->call_malloc= libmemcached_malloc;
-    ptr->call_free= libmemcached_free;
-    ptr->call_realloc= libmemcached_realloc;
-    ptr->call_calloc= libmemcached_calloc;
-  }
-  else if (mem_malloc == NULL || mem_free == NULL || mem_realloc == NULL || mem_calloc == NULL)
-    return MEMCACHED_FAILURE;
-  else
-  {
-    ptr->call_malloc= mem_malloc;
-    ptr->call_free= mem_free;
-    ptr->call_realloc= mem_realloc;
-    ptr->call_calloc= mem_calloc;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-void memcached_get_memory_allocators(memcached_st *ptr,
-                                     memcached_malloc_fn *mem_malloc,
-                                     memcached_free_fn *mem_free,
-                                     memcached_realloc_fn *mem_realloc,
-                                     memcached_calloc_fn *mem_calloc)
-{
-   *mem_malloc= ptr->call_malloc;
-   *mem_free= ptr->call_free;
-   *mem_realloc= ptr->call_realloc;
-   *mem_calloc= ptr->call_calloc;
-}
diff --git a/libmemcached/memcached_analyze.c b/libmemcached/memcached_analyze.c
deleted file mode 100644 (file)
index 5c1c7e4..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-#include "common.h"
-
-static void calc_largest_consumption(memcached_analysis_st *result,
-                                     const uint32_t server_num,
-                                     const uint64_t nbytes)
-{
-  if (result->most_used_bytes < nbytes)
-  {
-    result->most_used_bytes= nbytes;
-    result->most_consumed_server= server_num;
-  }
-}
-
-static void calc_oldest_node(memcached_analysis_st *result,
-                                     const uint32_t server_num,
-                                     const uint32_t uptime)
-{
-  if (result->longest_uptime < uptime)
-  {
-    result->longest_uptime= uptime;
-    result->oldest_server= server_num;
-  }
-}
-
-static void calc_least_free_node(memcached_analysis_st *result,
-                                 const uint32_t server_num,
-                                 const uint64_t max_allowed_bytes,
-                                 const uint64_t used_bytes)
-{
-  uint64_t remaining_bytes= max_allowed_bytes - used_bytes;
-
-  if (result->least_remaining_bytes == 0 ||
-      remaining_bytes < result->least_remaining_bytes)
-  {
-    result->least_remaining_bytes= remaining_bytes;
-    result->least_free_server= server_num;
-  }
-}
-
-static void calc_average_item_size(memcached_analysis_st *result,
-                                   const uint64_t total_items,
-                                   const uint64_t total_bytes)
-{
-  if (total_items > 0 && total_bytes > 0)
-    result->average_item_size= (uint32_t) (total_bytes / total_items);
-}
-
-static void calc_hit_ratio(memcached_analysis_st *result,
-                           const uint64_t total_get_hits,
-                           const uint64_t total_get_cmds)
-{
-  if (total_get_hits == 0 || total_get_cmds == 0)
-  {
-    result->pool_hit_ratio= 0;
-    return;
-  }
-
-  double temp= (double) (total_get_hits/total_get_cmds);
-  result->pool_hit_ratio= temp * 100;
-}
-
-memcached_analysis_st *memcached_analyze(memcached_st *memc,
-                                         memcached_stat_st *memc_stat,
-                                         memcached_return_t *error)
-{
-  uint64_t total_items= 0, total_bytes= 0;
-  uint64_t total_get_cmds= 0, total_get_hits= 0;
-  uint32_t server_count, x;
-  memcached_analysis_st *result;
-  
-  *error= MEMCACHED_SUCCESS;
-  server_count= memcached_server_count(memc);
-  result= (memcached_analysis_st*)calloc(memc->number_of_hosts,
-                                         sizeof(memcached_analysis_st));
-
-  if (!result)
-  {
-    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-    return NULL;
-  }
-
-  for (x= 0; x < server_count; x++)
-  {
-    calc_largest_consumption(result, x, memc_stat[x].bytes);
-    calc_oldest_node(result, x, memc_stat[x].uptime);
-    calc_least_free_node(result, x,
-                         memc_stat[x].limit_maxbytes, 
-                         memc_stat[x].bytes);
-
-    total_get_hits+= memc_stat[x].get_hits;
-    total_get_cmds+= memc_stat[x].cmd_get;
-    total_items+= memc_stat[x].curr_items;
-    total_bytes+= memc_stat[x].bytes;
-  }
-
-  calc_average_item_size(result, total_items, total_bytes);
-  calc_hit_ratio(result, total_get_hits, total_get_cmds);
-
-  return result;
-}
diff --git a/libmemcached/memcached_auto.c b/libmemcached/memcached_auto.c
deleted file mode 100644 (file)
index b746640..0000000
+++ /dev/null
@@ -1,275 +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: Methods for adding or decrementing values from an object in memcached
- *
- */
-
-#include "common.h"
-
-static memcached_return_t memcached_auto(memcached_st *ptr,
-                                         const char *verb,
-                                         const char *master_key, size_t master_key_length,
-                                         const char *key, size_t key_length,
-                                         uint64_t offset,
-                                         uint64_t *value)
-{
-  size_t send_length;
-  memcached_return_t rc;
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  unsigned int server_key;
-  bool no_reply= ptr->flags.no_reply;
-
-  unlikely (ptr->hosts == NULL || ptr->number_of_hosts == 0)
-    return MEMCACHED_NO_SERVERS;
-
-  if (ptr->flags.verify_key && (memcached_key_test((const 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);
-
-  send_length= (size_t)snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
-                                "%s %s%.*s %" PRIu64 "%s\r\n", verb,
-                                ptr->prefix_key,
-                                (int)key_length, key,
-                                offset, no_reply ? " noreply" : "");
-  unlikely (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
-    return MEMCACHED_WRITE_FAILURE;
-
-  rc= memcached_do(&ptr->hosts[server_key], buffer, send_length, 1);
-  if (no_reply || rc != MEMCACHED_SUCCESS)
-    return rc;
-
-  rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
-
-  /*
-    So why recheck responce? Because the protocol is brain dead :)
-    The number returned might end up equaling one of the string
-    values. Less chance of a mistake with strncmp() so we will
-    use it. We still called memcached_response() though since it
-    worked its magic for non-blocking IO.
-  */
-  if (!strncmp(buffer, "ERROR\r\n", 7))
-  {
-    *value= 0;
-    rc= MEMCACHED_PROTOCOL_ERROR;
-  }
-  else if (!strncmp(buffer, "NOT_FOUND\r\n", 11))
-  {
-    *value= 0;
-    rc= MEMCACHED_NOTFOUND;
-  }
-  else
-  {
-    *value= strtoull(buffer, (char **)NULL, 10);
-    rc= MEMCACHED_SUCCESS;
-  }
-
-  return rc;
-}
-
-static memcached_return_t binary_incr_decr(memcached_st *ptr, uint8_t cmd,
-                                           const char *master_key, size_t master_key_length,
-                                           const char *key, size_t key_length,
-                                           uint64_t offset, uint64_t initial,
-                                           uint32_t expiration,
-                                           uint64_t *value)
-{
-  unsigned int server_key;
-  bool no_reply= ptr->flags.no_reply;
-
-  unlikely (ptr->hosts == NULL || ptr->number_of_hosts == 0)
-    return MEMCACHED_NO_SERVERS;
-
-  server_key= memcached_generate_hash(ptr, master_key, master_key_length);
-
-  if (no_reply)
-  {
-    if(cmd == PROTOCOL_BINARY_CMD_DECREMENT)
-      cmd= PROTOCOL_BINARY_CMD_DECREMENTQ;
-    if(cmd == PROTOCOL_BINARY_CMD_INCREMENT)
-      cmd= PROTOCOL_BINARY_CMD_INCREMENTQ;
-  }
-  protocol_binary_request_incr request= {.bytes= {0}};
-
-  request.message.header.request.magic= PROTOCOL_BINARY_REQ;
-  request.message.header.request.opcode= cmd;
-  request.message.header.request.keylen= htons((uint16_t) key_length);
-  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 + request.message.header.request.extlen));
-  request.message.body.delta= htonll(offset);
-  request.message.body.initial= htonll(initial);
-  request.message.body.expiration= htonl((uint32_t) expiration);
-
-  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, 1) == -1))
-  {
-    memcached_io_reset(&ptr->hosts[server_key]);
-    return MEMCACHED_WRITE_FAILURE;
-  }
-
-  if (no_reply)
-    return MEMCACHED_SUCCESS;
-  return memcached_response(&ptr->hosts[server_key], (char*)value, sizeof(*value), NULL);
-}
-
-memcached_return_t memcached_increment(memcached_st *ptr,
-                                       const char *key, size_t key_length,
-                                       uint32_t offset,
-                                       uint64_t *value)
-{
-  return memcached_increment_by_key(ptr, key, key_length, key, key_length, offset, value);
-}
-
-memcached_return_t memcached_decrement(memcached_st *ptr,
-                                       const char *key, size_t key_length,
-                                       uint32_t offset,
-                                       uint64_t *value)
-{
-  return memcached_decrement_by_key(ptr, key, key_length, key, key_length, offset, value);
-}
-
-memcached_return_t memcached_increment_by_key(memcached_st *ptr,
-                                              const char *master_key, size_t master_key_length,
-                                              const char *key, size_t key_length,
-                                              uint64_t offset,
-                                              uint64_t *value)
-{
-  memcached_return_t rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol);
-  unlikely (rc != MEMCACHED_SUCCESS)
-    return rc;
-
-  LIBMEMCACHED_MEMCACHED_INCREMENT_START();
-  if (ptr->flags.binary_protocol)
-  {
-    rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
-                         master_key, master_key_length, key, key_length,
-                         (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
-                         value);
-  }
-  else
-  {
-     rc= memcached_auto(ptr, "incr", master_key, master_key_length, key, key_length, offset, value);
-  }
-
-  LIBMEMCACHED_MEMCACHED_INCREMENT_END();
-
-  return rc;
-}
-
-memcached_return_t memcached_decrement_by_key(memcached_st *ptr,
-                                              const char *master_key, size_t master_key_length,
-                                              const char *key, size_t key_length,
-                                              uint64_t offset,
-                                              uint64_t *value)
-{
-  memcached_return_t rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol);
-  unlikely (rc != MEMCACHED_SUCCESS)
-    return rc;
-
-  LIBMEMCACHED_MEMCACHED_DECREMENT_START();
-  if (ptr->flags.binary_protocol)
-    rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT,
-                         master_key, master_key_length, key, key_length,
-                         (uint64_t)offset, 0, MEMCACHED_EXPIRATION_NOT_ADD,
-                         value);
-  else
-    rc= memcached_auto(ptr, "decr", master_key, master_key_length, key, key_length, offset, value);
-
-  LIBMEMCACHED_MEMCACHED_DECREMENT_END();
-
-  return rc;
-}
-
-memcached_return_t memcached_increment_with_initial(memcached_st *ptr,
-                                                    const char *key,
-                                                    size_t key_length,
-                                                    uint64_t offset,
-                                                    uint64_t initial,
-                                                    time_t expiration,
-                                                    uint64_t *value)
-{
-  return memcached_increment_with_initial_by_key(ptr, key, key_length,
-                                                 key, key_length,
-                                                 offset, initial, expiration, value);
-}
-
-memcached_return_t memcached_increment_with_initial_by_key(memcached_st *ptr,
-                                                         const char *master_key,
-                                                         size_t master_key_length,
-                                                         const char *key,
-                                                         size_t key_length,
-                                                         uint64_t offset,
-                                                         uint64_t initial,
-                                                         time_t expiration,
-                                                         uint64_t *value)
-{
-  memcached_return_t rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol);
-  unlikely (rc != MEMCACHED_SUCCESS)
-    return rc;
-
-  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
-  if (ptr->flags.binary_protocol)
-    rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_INCREMENT,
-                         master_key, master_key_length, key, key_length,
-                         offset, initial, (uint32_t)expiration,
-                         value);
-  else
-    rc= MEMCACHED_PROTOCOL_ERROR;
-
-  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
-
-  return rc;
-}
-
-memcached_return_t memcached_decrement_with_initial(memcached_st *ptr,
-                                                    const char *key,
-                                                    size_t key_length,
-                                                    uint64_t offset,
-                                                    uint64_t initial,
-                                                    time_t expiration,
-                                                    uint64_t *value)
-{
-  return memcached_decrement_with_initial_by_key(ptr, key, key_length,
-                                                 key, key_length,
-                                                 offset, initial, expiration, value);
-}
-
-memcached_return_t memcached_decrement_with_initial_by_key(memcached_st *ptr,
-                                                           const char *master_key,
-                                                           size_t master_key_length,
-                                                           const char *key,
-                                                           size_t key_length,
-                                                           uint64_t offset,
-                                                           uint64_t initial,
-                                                           time_t expiration,
-                                                           uint64_t *value)
-{
-  memcached_return_t rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol);
-  unlikely (rc != MEMCACHED_SUCCESS)
-    return rc;
-
-  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_START();
-  if (ptr->flags.binary_protocol)
-  {
-    rc= binary_incr_decr(ptr, PROTOCOL_BINARY_CMD_DECREMENT,
-                         master_key, master_key_length, key, key_length,
-                         offset, initial, (uint32_t)expiration,
-                         value);
-  }
-  else
-  {
-    rc= MEMCACHED_PROTOCOL_ERROR;
-  }
-
-  LIBMEMCACHED_MEMCACHED_INCREMENT_WITH_INITIAL_END();
-
-  return rc;
-}
-
diff --git a/libmemcached/memcached_behavior.c b/libmemcached/memcached_behavior.c
deleted file mode 100644 (file)
index 37c9f52..0000000
+++ /dev/null
@@ -1,314 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Change the behavior of the memcached connection.
- *
- */
-
-#include "common.h"
-#include <time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/tcp.h>
-
-/*
-  This function is used to modify the behavior of running client.
-
-  We quit all connections so we can reset the sockets.
-*/
-
-memcached_return_t memcached_behavior_set(memcached_st *ptr,
-                                          memcached_behavior_t flag,
-                                          uint64_t data)
-{
-  switch (flag)
-  {
-  case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
-    ptr->number_of_replicas= (uint32_t)data;
-    break;
-  case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK:
-    ptr->io_msg_watermark= (uint32_t) data;
-    break;
-  case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK:
-    ptr->io_bytes_watermark= (uint32_t)data;
-    break;
-  case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH:
-    ptr->io_key_prefetch = (uint32_t)data;
-    break;
-  case MEMCACHED_BEHAVIOR_SND_TIMEOUT:
-    ptr->snd_timeout= (int32_t)data;
-    break;
-  case MEMCACHED_BEHAVIOR_RCV_TIMEOUT:
-    ptr->rcv_timeout= (int32_t)data;
-    break;
-  case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
-    ptr->server_failure_limit= (uint32_t)data;
-    break;
-  case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL:
-    if (data)
-        ptr->flags.verify_key= false;
-
-    ptr->flags.binary_protocol= data ? true : false;
-    break;
-  case MEMCACHED_BEHAVIOR_SUPPORT_CAS:
-    ptr->flags.support_cas= data ? true: false;
-    break;
-  case MEMCACHED_BEHAVIOR_NO_BLOCK:
-    ptr->flags.no_block= data ? true: false;
-    memcached_quit(ptr);
-    break;
-  case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS:
-    ptr->flags.buffer_requests= data ? true : false;
-    memcached_quit(ptr);
-    break;
-  case MEMCACHED_BEHAVIOR_USE_UDP:
-    if (ptr->number_of_hosts)
-      return MEMCACHED_FAILURE;
-    ptr->flags.use_udp= data ? true : false;
-
-    if (data)
-      ptr->flags.no_reply= data ? true : false;
-    break;
-
-  case MEMCACHED_BEHAVIOR_TCP_NODELAY:
-    ptr->flags.tcp_nodelay= data ? true : false;
-    memcached_quit(ptr);
-    break;
-  case MEMCACHED_BEHAVIOR_DISTRIBUTION:
-    {
-      ptr->distribution= (memcached_server_distribution_t)(data);
-      if (ptr->distribution == MEMCACHED_DISTRIBUTION_RANDOM)
-      {
-        srandom((uint32_t) time(NULL));
-      }
-      run_distribution(ptr);
-      break;
-    }
-  case MEMCACHED_BEHAVIOR_KETAMA:
-    {
-      if (data)
-      {
-        ptr->hash= MEMCACHED_HASH_MD5;
-        ptr->distribution= MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA;
-      }
-      else
-      {
-        ptr->hash= 0;
-        ptr->distribution= 0;
-      }
-      run_distribution(ptr);
-      break;
-    }
-  case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED:
-    {
-      ptr->hash= MEMCACHED_HASH_MD5;
-      ptr->distribution= MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA;
-      ptr->flags.ketama_weighted= data ? true : false;
-      run_distribution(ptr);
-      break;
-    }
-  case MEMCACHED_BEHAVIOR_KETAMA_COMPAT_MODE:
-    switch (data)
-    {
-    case MEMCACHED_KETAMA_COMPAT_LIBMEMCACHED:
-      ptr->hash= MEMCACHED_HASH_MD5;
-      ptr->distribution= MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA;
-      break;
-    case MEMCACHED_KETAMA_COMPAT_SPY:
-      ptr->hash= MEMCACHED_HASH_MD5;
-      ptr->distribution= MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY;
-      break;
-    default:
-       return MEMCACHED_FAILURE;
-    }
-    run_distribution(ptr);
-    break;
-  case MEMCACHED_BEHAVIOR_HASH:
-#ifndef HAVE_HSIEH_HASH
-    if ((memcached_hash_t)(data) == MEMCACHED_HASH_HSIEH)
-      return MEMCACHED_FAILURE;
-#endif
-    ptr->hash= (memcached_hash_t)(data);
-    break;
-  case MEMCACHED_BEHAVIOR_KETAMA_HASH:
-    ptr->hash_continuum= (memcached_hash_t)(data);
-    run_distribution(ptr);
-    break;
-  case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS:
-    ptr->flags.use_cache_lookups= data ? true : false;
-    memcached_quit(ptr);
-    break;
-  case MEMCACHED_BEHAVIOR_VERIFY_KEY:
-    if (ptr->flags.binary_protocol)
-        break;
-    ptr->flags.verify_key= data ? true : false;
-    break;
-  case MEMCACHED_BEHAVIOR_SORT_HOSTS:
-    {
-      ptr->flags.use_sort_hosts= data ? true : false;
-      run_distribution(ptr);
-
-      break;
-    }
-  case MEMCACHED_BEHAVIOR_POLL_TIMEOUT:
-    ptr->poll_timeout= (int32_t)data;
-    break;
-  case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT:
-    ptr->connect_timeout= (int32_t)data;
-    break;
-  case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT:
-    ptr->retry_timeout= (int32_t)data;
-    break;
-  case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE:
-    ptr->send_size= (int32_t)data;
-    memcached_quit(ptr);
-    break;
-  case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE:
-    ptr->recv_size= (int32_t)data;
-    memcached_quit(ptr);
-    break;
-  case MEMCACHED_BEHAVIOR_USER_DATA:
-    return MEMCACHED_FAILURE;
-  case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY:
-    ptr->flags.hash_with_prefix_key= data ? true : false;
-    break;
-  case MEMCACHED_BEHAVIOR_NOREPLY:
-    ptr->flags.no_reply= data ? true : false;
-    break;
-  case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
-    ptr->flags.auto_eject_hosts= data ? true : false;
-    break;
-  case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ:
-      srandom((uint32_t) time(NULL));
-      ptr->flags.randomize_replica_read= data ? true : false;
-      break;
-  default:
-    /* Shouldn't get here */
-    WATCHPOINT_ASSERT(flag);
-    break;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-uint64_t memcached_behavior_get(memcached_st *ptr,
-                                memcached_behavior_t flag)
-{
-  switch (flag)
-  {
-  case MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS:
-    return ptr->number_of_replicas;
-  case MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK:
-    return ptr->io_msg_watermark;
-  case MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK:
-    return ptr->io_bytes_watermark;
-  case MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH:
-    return ptr->io_key_prefetch;
-  case MEMCACHED_BEHAVIOR_BINARY_PROTOCOL:
-    return ptr->flags.binary_protocol;
-  case MEMCACHED_BEHAVIOR_SUPPORT_CAS:
-    return ptr->flags.support_cas;
-  case MEMCACHED_BEHAVIOR_CACHE_LOOKUPS:
-    return ptr->flags.use_cache_lookups;
-  case MEMCACHED_BEHAVIOR_NO_BLOCK:
-    return ptr->flags.no_block;
-  case MEMCACHED_BEHAVIOR_BUFFER_REQUESTS:
-    return ptr->flags.buffer_requests;
-  case MEMCACHED_BEHAVIOR_USE_UDP:
-    return ptr->flags.use_udp;
-  case MEMCACHED_BEHAVIOR_TCP_NODELAY:
-    return ptr->flags.tcp_nodelay;
-  case MEMCACHED_BEHAVIOR_VERIFY_KEY:
-    return ptr->flags.verify_key;
-  case MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED:
-    return ptr->flags.ketama_weighted;
-  case MEMCACHED_BEHAVIOR_DISTRIBUTION:
-    return ptr->distribution;
-  case MEMCACHED_BEHAVIOR_KETAMA:
-    return (ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA) ? (uint64_t) 1 : 0;
-  case MEMCACHED_BEHAVIOR_KETAMA_COMPAT_MODE:
-    switch (ptr->distribution)
-    {
-    case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
-      return MEMCACHED_KETAMA_COMPAT_LIBMEMCACHED;
-    case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
-      return MEMCACHED_KETAMA_COMPAT_SPY;
-    case MEMCACHED_DISTRIBUTION_MODULA:
-    case MEMCACHED_DISTRIBUTION_CONSISTENT:
-    case MEMCACHED_DISTRIBUTION_RANDOM:
-    default:
-      return (uint64_t)-1;
-    }
-    /* NOTREACHED */
-  case MEMCACHED_BEHAVIOR_HASH:
-    return ptr->hash;
-  case MEMCACHED_BEHAVIOR_KETAMA_HASH:
-    return ptr->hash_continuum;
-  case MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT:
-    return ptr->server_failure_limit;
-  case MEMCACHED_BEHAVIOR_SORT_HOSTS:
-    return ptr->flags.use_sort_hosts;
-  case MEMCACHED_BEHAVIOR_POLL_TIMEOUT:
-    return (uint64_t)ptr->poll_timeout;
-  case MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT:
-    return (uint64_t)ptr->connect_timeout;
-  case MEMCACHED_BEHAVIOR_RETRY_TIMEOUT:
-    return (uint64_t)ptr->retry_timeout;
-  case MEMCACHED_BEHAVIOR_SND_TIMEOUT:
-    return (uint64_t)ptr->snd_timeout;
-  case MEMCACHED_BEHAVIOR_RCV_TIMEOUT:
-    return (uint64_t)ptr->rcv_timeout;
-  case MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE:
-    {
-      int sock_size;
-      socklen_t sock_length= sizeof(int);
-
-      /* REFACTOR */
-      /* We just try the first host, and if it is down we return zero */
-      if ((memcached_connect(&ptr->hosts[0])) != MEMCACHED_SUCCESS)
-        return 0;
-
-      if (getsockopt(ptr->hosts[0].fd, SOL_SOCKET,
-                     SO_SNDBUF, &sock_size, &sock_length))
-        return 0; /* Zero means error */
-
-      return (uint64_t) sock_size;
-    }
-  case MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE:
-    {
-      int sock_size;
-      socklen_t sock_length= sizeof(int);
-
-      /* REFACTOR */
-      /* We just try the first host, and if it is down we return zero */
-      if ((memcached_connect(&ptr->hosts[0])) != MEMCACHED_SUCCESS)
-        return 0;
-
-      if (getsockopt(ptr->hosts[0].fd, SOL_SOCKET,
-                     SO_RCVBUF, &sock_size, &sock_length))
-        return 0; /* Zero means error */
-
-      return (uint64_t) sock_size;
-    }
-  case MEMCACHED_BEHAVIOR_USER_DATA:
-    return MEMCACHED_FAILURE;
-  case MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY:
-    return ptr->flags.hash_with_prefix_key;
-  case MEMCACHED_BEHAVIOR_NOREPLY:
-    return ptr->flags.no_reply;
-  case MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS:
-    return ptr->flags.auto_eject_hosts;
-  case MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ:
-    return ptr->flags.randomize_replica_read;
-  default:
-    WATCHPOINT_ASSERT(flag);
-    break;
-  }
-
-  WATCHPOINT_ASSERT(0); /* Programming mistake if it gets this far */
-  return 0;
-}
diff --git a/libmemcached/memcached_behavior.h b/libmemcached/memcached_behavior.h
deleted file mode 100644 (file)
index 14cbc3a..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Change the behavior of the memcached connection.
- *
- */
-
-#ifndef __MEMCACHED_BEHAVIOR_H__
-#define __MEMCACHED_BEHAVIOR_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_behavior_set(memcached_st *ptr, memcached_behavior_t flag, uint64_t data);
-
-LIBMEMCACHED_API
-uint64_t memcached_behavior_get(memcached_st *ptr, memcached_behavior_t flag);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MEMCACHED_BEHAVIOR_H__ */
diff --git a/libmemcached/memcached_callback.c b/libmemcached/memcached_callback.c
deleted file mode 100644 (file)
index b0ddfc2..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Change any of the possible callbacks.
- *
- */
-
-#include "common.h" 
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/tcp.h>
-
-/* 
-  These functions provide data and function callback support
-*/
-
-memcached_return_t memcached_callback_set(memcached_st *ptr, 
-                                          memcached_callback_t flag, 
-                                          void *data)
-{
-  switch (flag)
-  {
-  case MEMCACHED_CALLBACK_PREFIX_KEY:
-    {
-      char *key= (char *)data;
-
-      if (key)
-      {
-        size_t key_length= strlen(key);
-
-        if (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED)
-        {
-          return MEMCACHED_BAD_KEY_PROVIDED;
-        }
-
-        if ((key_length > MEMCACHED_PREFIX_KEY_MAX_SIZE -1)
-            || (strcpy(ptr->prefix_key, key) == NULL))
-        {
-          ptr->prefix_key_length= 0;
-          return MEMCACHED_BAD_KEY_PROVIDED;
-        }
-        else
-        {
-          ptr->prefix_key_length= key_length;
-        }
-      }
-      else
-      {
-        memset(ptr->prefix_key, 0, MEMCACHED_PREFIX_KEY_MAX_SIZE);
-        ptr->prefix_key_length= 0;
-      }
-
-      break;
-    }
-  case MEMCACHED_CALLBACK_USER_DATA:
-    {
-      ptr->user_data= data;
-      break;
-    }
-  case MEMCACHED_CALLBACK_CLEANUP_FUNCTION:
-    {
-      memcached_cleanup_fn func= *(memcached_cleanup_fn *)&data;
-      ptr->on_cleanup= func;
-      break;
-    }
-  case MEMCACHED_CALLBACK_CLONE_FUNCTION:
-    {
-      memcached_clone_fn func= *(memcached_clone_fn *)&data;
-      ptr->on_clone= func;
-      break;
-    }
-#ifdef MEMCACHED_ENABLE_DEPRECATED
-  case MEMCACHED_CALLBACK_MALLOC_FUNCTION:
-    {
-      memcached_malloc_function func= *(memcached_malloc_fn *)&data;
-      ptr->call_malloc= func;
-      break;
-    }
-  case MEMCACHED_CALLBACK_REALLOC_FUNCTION:
-    {
-      memcached_realloc_function func= *(memcached_realloc_fn *)&data;
-      ptr->call_realloc= func;
-      break;
-    }
-  case MEMCACHED_CALLBACK_FREE_FUNCTION:
-    {
-      memcached_free_function func= *(memcached_free_fn *)&data;
-      ptr->call_free= func;
-      break;
-    }
-#endif
-  case MEMCACHED_CALLBACK_GET_FAILURE:
-    {
-      memcached_trigger_key_fn func= *(memcached_trigger_key_fn *)&data;
-      ptr->get_key_failure= func;
-      break;
-    }
-  case MEMCACHED_CALLBACK_DELETE_TRIGGER:
-    {
-      memcached_trigger_delete_key_fn func= *(memcached_trigger_delete_key_fn *)&data;
-      ptr->delete_trigger= func;
-      break;
-    }
-  default:
-    return MEMCACHED_FAILURE;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-void *memcached_callback_get(memcached_st *ptr, 
-                             memcached_callback_t flag,
-                             memcached_return_t *error)
-{
-  memcached_return_t local_error;
-
-  if (!error)
-    error = &local_error;
-
-  switch (flag)
-  {
-  case MEMCACHED_CALLBACK_PREFIX_KEY:
-    {
-      if (ptr->prefix_key[0] == 0)
-      {
-        *error= MEMCACHED_FAILURE;
-        return NULL;
-      }
-      else
-      {
-        *error= MEMCACHED_SUCCESS;
-        return (void *)ptr->prefix_key;
-      }
-    }
-  case MEMCACHED_CALLBACK_USER_DATA:
-    {
-      *error= ptr->user_data ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
-      return (void *)ptr->user_data;
-    }
-  case MEMCACHED_CALLBACK_CLEANUP_FUNCTION:
-    {
-      *error= ptr->on_cleanup ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
-      return *(void **)&ptr->on_cleanup;
-    }
-  case MEMCACHED_CALLBACK_CLONE_FUNCTION:
-    {
-      *error= ptr->on_clone ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
-      return *(void **)&ptr->on_clone;
-    }
-#ifdef MEMCACHED_ENABLE_DEPRECATED
-  case MEMCACHED_CALLBACK_MALLOC_FUNCTION:
-    {
-      *error= ptr->call_malloc ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
-      return *(void **)&ptr->call_malloc;
-    }
-  case MEMCACHED_CALLBACK_REALLOC_FUNCTION:
-    {
-      *error= ptr->call_realloc ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
-      return *(void **)&ptr->call_realloc;
-    }
-  case MEMCACHED_CALLBACK_FREE_FUNCTION:
-    {
-      *error= ptr->call_free ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
-      return *(void **)&ptr->call_free;
-    }
-#endif
-  case MEMCACHED_CALLBACK_GET_FAILURE:
-    {
-      *error= ptr->get_key_failure ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
-      return *(void **)&ptr->get_key_failure;
-    }
-  case MEMCACHED_CALLBACK_DELETE_TRIGGER:
-    {
-      *error= ptr->delete_trigger ? MEMCACHED_SUCCESS : MEMCACHED_FAILURE;
-      return *(void **)&ptr->delete_trigger;
-    }
-  default:
-    WATCHPOINT_ASSERT(0);
-    *error= MEMCACHED_FAILURE;
-    return NULL;
-  }
-}
diff --git a/libmemcached/memcached_callback.h b/libmemcached/memcached_callback.h
deleted file mode 100644 (file)
index 0719a66..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Change any of the possible callbacks.
- *
- */
-
-#ifndef __MEMCACHED_CALLBACK_H__
-#define __MEMCACHED_CALLBACK_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_API
-memcached_return_t memcached_callback_set(memcached_st *ptr,
-                                          memcached_callback_t flag,
-                                          void *data);
-LIBMEMCACHED_API
-void *memcached_callback_get(memcached_st *ptr,
-                             memcached_callback_t flag,
-                             memcached_return_t *error);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MEMCACHED_CALLBACK_H__ */
diff --git a/libmemcached/memcached_connect.c b/libmemcached/memcached_connect.c
deleted file mode 100644 (file)
index 24328f4..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-#include "common.h"
-#include <netdb.h>
-#include <poll.h>
-#include <sys/time.h>
-
-static memcached_return_t set_hostinfo(memcached_server_st *server)
-{
-  struct addrinfo *ai;
-  struct addrinfo hints;
-  int e;
-  char str_port[NI_MAXSERV];
-
-  sprintf(str_port, "%u", server->port);
-
-  memset(&hints, 0, sizeof(hints));
-
- // hints.ai_family= AF_INET;
-  if (server->type == MEMCACHED_CONNECTION_UDP)
-  {
-    hints.ai_protocol= IPPROTO_UDP;
-    hints.ai_socktype= SOCK_DGRAM;
-  }
-  else
-  {
-    hints.ai_socktype= SOCK_STREAM;
-    hints.ai_protocol= IPPROTO_TCP;
-  }
-
-  e= getaddrinfo(server->hostname, str_port, &hints, &ai);
-  if (e != 0)
-  {
-    WATCHPOINT_STRING(server->hostname);
-    WATCHPOINT_STRING(gai_strerror(e));
-    return MEMCACHED_HOST_LOOKUP_FAILURE;
-  }
-
-  if (server->address_info)
-  {
-    freeaddrinfo(server->address_info);
-    server->address_info= NULL;
-  }
-  server->address_info= ai;
-
-  return MEMCACHED_SUCCESS;
-}
-
-static memcached_return_t set_socket_options(memcached_server_st *ptr)
-{
-  WATCHPOINT_ASSERT(ptr->fd != -1);
-
-  if (ptr->type == MEMCACHED_CONNECTION_UDP)
-    return MEMCACHED_SUCCESS;
-
-#ifdef HAVE_SNDTIMEO
-  if (ptr->root->snd_timeout)
-  {
-    int error;
-    struct timeval waittime;
-
-    waittime.tv_sec= 0;
-    waittime.tv_usec= ptr->root->snd_timeout;
-
-    error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDTIMEO,
-                      &waittime, (socklen_t)sizeof(struct timeval));
-    WATCHPOINT_ASSERT(error == 0);
-  }
-#endif
-
-#ifdef HAVE_RCVTIMEO
-  if (ptr->root->rcv_timeout)
-  {
-    int error;
-    struct timeval waittime;
-
-    waittime.tv_sec= 0;
-    waittime.tv_usec= ptr->root->rcv_timeout;
-
-    error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVTIMEO,
-                      &waittime, (socklen_t)sizeof(struct timeval));
-    WATCHPOINT_ASSERT(error == 0);
-  }
-#endif
-
-  if (ptr->root->flags.no_block)
-  {
-    int error;
-    struct linger linger;
-
-    linger.l_onoff= 1;
-    linger.l_linger= 0; /* By default on close() just drop the socket */
-    error= setsockopt(ptr->fd, SOL_SOCKET, SO_LINGER,
-                      &linger, (socklen_t)sizeof(struct linger));
-    WATCHPOINT_ASSERT(error == 0);
-  }
-
-  if (ptr->root->flags.tcp_nodelay)
-  {
-    int flag= 1;
-    int error;
-
-    error= setsockopt(ptr->fd, IPPROTO_TCP, TCP_NODELAY,
-                      &flag, (socklen_t)sizeof(int));
-    WATCHPOINT_ASSERT(error == 0);
-  }
-
-  if (ptr->root->send_size)
-  {
-    int error;
-
-    error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDBUF,
-                      &ptr->root->send_size, (socklen_t)sizeof(int));
-    WATCHPOINT_ASSERT(error == 0);
-  }
-
-  if (ptr->root->recv_size)
-  {
-    int error;
-
-    error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVBUF,
-                      &ptr->root->recv_size, (socklen_t)sizeof(int));
-    WATCHPOINT_ASSERT(error == 0);
-  }
-
-  /* libmemcached will always use nonblocking IO to avoid write deadlocks */
-  int flags;
-
-  do
-    flags= fcntl(ptr->fd, F_GETFL, 0);
-  while (flags == -1 && (errno == EINTR || errno == EAGAIN));
-
-  unlikely (flags == -1)
-    return MEMCACHED_CONNECTION_FAILURE;
-  else if ((flags & O_NONBLOCK) == 0)
-  {
-    int rval;
-
-    do
-      rval= fcntl(ptr->fd, F_SETFL, flags | O_NONBLOCK);
-    while (rval == -1 && (errno == EINTR || errno == EAGAIN));
-
-    unlikely (rval == -1)
-      return MEMCACHED_CONNECTION_FAILURE;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-static memcached_return_t unix_socket_connect(memcached_server_st *ptr)
-{
-  struct sockaddr_un servAddr;
-  socklen_t addrlen;
-
-  if (ptr->fd == -1)
-  {
-    if ((ptr->fd= socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
-    {
-      ptr->cached_errno= errno;
-      return MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE;
-    }
-
-    memset(&servAddr, 0, sizeof (struct sockaddr_un));
-    servAddr.sun_family= AF_UNIX;
-    strcpy(servAddr.sun_path, ptr->hostname); /* Copy filename */
-
-    addrlen= (socklen_t) (strlen(servAddr.sun_path) + sizeof(servAddr.sun_family));
-
-test_connect:
-    if (connect(ptr->fd,
-                (struct sockaddr *)&servAddr,
-                sizeof(servAddr)) < 0)
-    {
-      switch (errno)
-      {
-      case EINPROGRESS:
-      case EALREADY:
-      case EINTR:
-        goto test_connect;
-      case EISCONN: /* We were spinning waiting on connect */
-        break;
-      default:
-        WATCHPOINT_ERRNO(errno);
-        ptr->cached_errno= errno;
-        return MEMCACHED_ERRNO;
-      }
-    }
-  }
-
-  WATCHPOINT_ASSERT(ptr->fd != -1);
-  return MEMCACHED_SUCCESS;
-}
-
-static memcached_return_t network_connect(memcached_server_st *ptr)
-{
-  if (ptr->fd == -1)
-  {
-    struct addrinfo *use;
-
-    if (!ptr->sockaddr_inited ||
-        (!(ptr->root->flags.use_cache_lookups)))
-    {
-      memcached_return_t rc;
-
-      rc= set_hostinfo(ptr);
-      if (rc != MEMCACHED_SUCCESS)
-        return rc;
-      ptr->sockaddr_inited= true;
-    }
-
-    use= ptr->address_info;
-    /* Create the socket */
-    while (use != NULL)
-    {
-      /* Memcache server does not support IPV6 in udp mode, so skip if not ipv4 */
-      if (ptr->type == MEMCACHED_CONNECTION_UDP && use->ai_family != AF_INET)
-      {
-        use= use->ai_next;
-        continue;
-      }
-
-      if ((ptr->fd= socket(use->ai_family,
-                           use->ai_socktype,
-                           use->ai_protocol)) < 0)
-      {
-        ptr->cached_errno= errno;
-        WATCHPOINT_ERRNO(errno);
-        return MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE;
-      }
-
-      (void)set_socket_options(ptr);
-
-      /* connect to server */
-      while (ptr->fd != -1 &&
-             connect(ptr->fd, use->ai_addr, use->ai_addrlen) < 0)
-      {
-        ptr->cached_errno= errno;
-        if (errno == EINPROGRESS || /* nonblocking mode - first return, */
-            errno == EALREADY) /* nonblocking mode - subsequent returns */
-        {
-          struct pollfd fds[1];
-          fds[0].fd = ptr->fd;
-          fds[0].events = POLLOUT;
-          int error= poll(fds, 1, ptr->root->connect_timeout);
-
-          if (error != 1 || fds[0].revents & POLLERR)
-          {
-            if (fds[0].revents & POLLERR)
-            {
-              int err;
-              socklen_t len = sizeof (err);
-              (void)getsockopt(ptr->fd, SOL_SOCKET, SO_ERROR, &err, &len);
-              ptr->cached_errno= (err == 0) ? errno : err;
-            }
-
-            (void)close(ptr->fd);
-            ptr->fd= -1;
-          }
-        }
-        else if (errno == EISCONN) /* we are connected :-) */
-        {
-          break;
-        }
-        else if (errno != EINTR)
-        {
-          (void)close(ptr->fd);
-          ptr->fd= -1;
-          break;
-        }
-      }
-
-      if (ptr->fd != -1)
-      {
-        WATCHPOINT_ASSERT(ptr->cursor_active == 0);
-        ptr->server_failure_counter= 0;
-        return MEMCACHED_SUCCESS;
-      }
-      use = use->ai_next;
-    }
-  }
-
-  if (ptr->fd == -1)
-  {
-    /* Failed to connect. schedule next retry */
-    if (ptr->root->retry_timeout)
-    {
-      struct timeval next_time;
-
-      if (gettimeofday(&next_time, NULL) == 0)
-        ptr->next_retry= next_time.tv_sec + ptr->root->retry_timeout;
-    }
-    ptr->server_failure_counter++;
-    if (ptr->cached_errno == 0)
-      return MEMCACHED_TIMEOUT;
-
-    return MEMCACHED_ERRNO; /* The last error should be from connect() */
-  }
-
-  ptr->server_failure_counter= 0;
-  return MEMCACHED_SUCCESS; /* The last error should be from connect() */
-}
-
-
-memcached_return_t memcached_connect(memcached_server_st *ptr)
-{
-  memcached_return_t rc= MEMCACHED_NO_SERVERS;
-  LIBMEMCACHED_MEMCACHED_CONNECT_START();
-
-  /* both retry_timeout and server_failure_limit must be set in order to delay retrying a server on error. */
-  WATCHPOINT_ASSERT(ptr->root);
-  if (ptr->root->retry_timeout && ptr->root->server_failure_limit)
-  {
-    struct timeval curr_time;
-
-    gettimeofday(&curr_time, NULL);
-
-    /* if we've had too many consecutive errors on this server, mark it dead. */
-    if (ptr->server_failure_counter >= ptr->root->server_failure_limit)
-    {
-      ptr->next_retry= curr_time.tv_sec + ptr->root->retry_timeout;
-      ptr->server_failure_counter= 0;
-    }
-
-    if (curr_time.tv_sec < ptr->next_retry)
-    {
-      if (memcached_behavior_get(ptr->root, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS))
-        run_distribution(ptr->root);
-
-      ptr->root->last_disconnected_server = ptr;
-      return MEMCACHED_SERVER_MARKED_DEAD;
-    }
-  }
-
-  /* We need to clean up the multi startup piece */
-  switch (ptr->type)
-  {
-  case MEMCACHED_CONNECTION_UNKNOWN:
-    WATCHPOINT_ASSERT(0);
-    rc= MEMCACHED_NOT_SUPPORTED;
-    break;
-  case MEMCACHED_CONNECTION_UDP:
-  case MEMCACHED_CONNECTION_TCP:
-    rc= network_connect(ptr);
-    break;
-  case MEMCACHED_CONNECTION_UNIX_SOCKET:
-    rc= unix_socket_connect(ptr);
-    break;
-  default:
-    WATCHPOINT_ASSERT(0);
-  }
-
-  unlikely ( rc != MEMCACHED_SUCCESS) ptr->root->last_disconnected_server = ptr;
-
-  LIBMEMCACHED_MEMCACHED_CONNECT_END();
-
-  return rc;
-}
diff --git a/libmemcached/memcached_constants.h b/libmemcached/memcached_constants.h
deleted file mode 100644 (file)
index cbdbf4b..0000000
+++ /dev/null
@@ -1,154 +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: Constants for libmemcached
- *
- */
-
-#ifndef __MEMCACHED_CONSTANTS_H__
-#define __MEMCACHED_CONSTANTS_H__
-
-/* Public defines */
-#define MEMCACHED_DEFAULT_PORT 11211
-#define MEMCACHED_MAX_KEY 251 /* We add one to have it null terminated */
-#define MEMCACHED_MAX_BUFFER 8196
-#define MEMCACHED_MAX_HOST_LENGTH 64
-#define MEMCACHED_MAX_HOST_SORT_LENGTH 86 /* Used for Ketama */
-#define MEMCACHED_POINTS_PER_SERVER 100
-#define MEMCACHED_POINTS_PER_SERVER_KETAMA 160
-#define MEMCACHED_CONTINUUM_SIZE MEMCACHED_POINTS_PER_SERVER*100 /* This would then set max hosts to 100 */
-#define MEMCACHED_STRIDE 4
-#define MEMCACHED_DEFAULT_TIMEOUT 1000
-#define MEMCACHED_CONTINUUM_ADDITION 10 /* How many extra slots we should build for in the continuum */
-#define MEMCACHED_PREFIX_KEY_MAX_SIZE 128
-#define MEMCACHED_EXPIRATION_NOT_ADD 0xffffffffU
-
-typedef enum {
-  MEMCACHED_SUCCESS,
-  MEMCACHED_FAILURE,
-  MEMCACHED_HOST_LOOKUP_FAILURE,
-  MEMCACHED_CONNECTION_FAILURE,
-  MEMCACHED_CONNECTION_BIND_FAILURE,
-  MEMCACHED_WRITE_FAILURE,
-  MEMCACHED_READ_FAILURE,
-  MEMCACHED_UNKNOWN_READ_FAILURE,
-  MEMCACHED_PROTOCOL_ERROR,
-  MEMCACHED_CLIENT_ERROR,
-  MEMCACHED_SERVER_ERROR,
-  MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE,
-  MEMCACHED_DATA_EXISTS,
-  MEMCACHED_DATA_DOES_NOT_EXIST,
-  MEMCACHED_NOTSTORED,
-  MEMCACHED_STORED,
-  MEMCACHED_NOTFOUND,
-  MEMCACHED_MEMORY_ALLOCATION_FAILURE,
-  MEMCACHED_PARTIAL_READ,
-  MEMCACHED_SOME_ERRORS,
-  MEMCACHED_NO_SERVERS,
-  MEMCACHED_END,
-  MEMCACHED_DELETED,
-  MEMCACHED_VALUE,
-  MEMCACHED_STAT,
-  MEMCACHED_ITEM,
-  MEMCACHED_ERRNO,
-  MEMCACHED_FAIL_UNIX_SOCKET,
-  MEMCACHED_NOT_SUPPORTED,
-  MEMCACHED_NO_KEY_PROVIDED, /* Deprecated. Use MEMCACHED_BAD_KEY_PROVIDED! */
-  MEMCACHED_FETCH_NOTFINISHED,
-  MEMCACHED_TIMEOUT,
-  MEMCACHED_BUFFERED,
-  MEMCACHED_BAD_KEY_PROVIDED,
-  MEMCACHED_INVALID_HOST_PROTOCOL,
-  MEMCACHED_SERVER_MARKED_DEAD,
-  MEMCACHED_UNKNOWN_STAT_KEY,
-  MEMCACHED_E2BIG,
-  MEMCACHED_INVALID_ARGUMENTS,
-  MEMCACHED_MAXIMUM_RETURN /* Always add new error code before */
-} memcached_return_t;
-
-
-typedef enum {
-  MEMCACHED_DISTRIBUTION_MODULA,
-  MEMCACHED_DISTRIBUTION_CONSISTENT,
-  MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA,
-  MEMCACHED_DISTRIBUTION_RANDOM,
-  MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY
-} memcached_server_distribution_t;
-
-typedef enum {
-  MEMCACHED_BEHAVIOR_NO_BLOCK,
-  MEMCACHED_BEHAVIOR_TCP_NODELAY,
-  MEMCACHED_BEHAVIOR_HASH,
-  MEMCACHED_BEHAVIOR_KETAMA,
-  MEMCACHED_BEHAVIOR_SOCKET_SEND_SIZE,
-  MEMCACHED_BEHAVIOR_SOCKET_RECV_SIZE,
-  MEMCACHED_BEHAVIOR_CACHE_LOOKUPS,
-  MEMCACHED_BEHAVIOR_SUPPORT_CAS,
-  MEMCACHED_BEHAVIOR_POLL_TIMEOUT,
-  MEMCACHED_BEHAVIOR_DISTRIBUTION,
-  MEMCACHED_BEHAVIOR_BUFFER_REQUESTS,
-  MEMCACHED_BEHAVIOR_USER_DATA,
-  MEMCACHED_BEHAVIOR_SORT_HOSTS,
-  MEMCACHED_BEHAVIOR_VERIFY_KEY,
-  MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT,
-  MEMCACHED_BEHAVIOR_RETRY_TIMEOUT,
-  MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED,
-  MEMCACHED_BEHAVIOR_KETAMA_HASH,
-  MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
-  MEMCACHED_BEHAVIOR_SND_TIMEOUT,
-  MEMCACHED_BEHAVIOR_RCV_TIMEOUT,
-  MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT,
-  MEMCACHED_BEHAVIOR_IO_MSG_WATERMARK,
-  MEMCACHED_BEHAVIOR_IO_BYTES_WATERMARK,
-  MEMCACHED_BEHAVIOR_IO_KEY_PREFETCH,
-  MEMCACHED_BEHAVIOR_HASH_WITH_PREFIX_KEY,
-  MEMCACHED_BEHAVIOR_NOREPLY,
-  MEMCACHED_BEHAVIOR_USE_UDP,
-  MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS,
-  MEMCACHED_BEHAVIOR_NUMBER_OF_REPLICAS,
-  MEMCACHED_BEHAVIOR_KETAMA_COMPAT_MODE,
-  MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ
-} memcached_behavior_t;
-
-#define MEMCACHED_KETAMA_COMPAT_LIBMEMCACHED 0
-#define MEMCACHED_KETAMA_COMPAT_SPY 1
-
-typedef enum {
-  MEMCACHED_CALLBACK_PREFIX_KEY = 0,
-  MEMCACHED_CALLBACK_USER_DATA = 1,
-  MEMCACHED_CALLBACK_CLEANUP_FUNCTION = 2,
-  MEMCACHED_CALLBACK_CLONE_FUNCTION = 3,
-#ifdef MEMCACHED_ENABLE_DEPRECATED
-  MEMCACHED_CALLBACK_MALLOC_FUNCTION = 4,
-  MEMCACHED_CALLBACK_REALLOC_FUNCTION = 5,
-  MEMCACHED_CALLBACK_FREE_FUNCTION = 6,
-#endif
-  MEMCACHED_CALLBACK_GET_FAILURE = 7,
-  MEMCACHED_CALLBACK_DELETE_TRIGGER = 8
-} memcached_callback_t;
-
-typedef enum {
-  MEMCACHED_HASH_DEFAULT= 0,
-  MEMCACHED_HASH_MD5,
-  MEMCACHED_HASH_CRC,
-  MEMCACHED_HASH_FNV1_64,
-  MEMCACHED_HASH_FNV1A_64,
-  MEMCACHED_HASH_FNV1_32,
-  MEMCACHED_HASH_FNV1A_32,
-  MEMCACHED_HASH_HSIEH,
-  MEMCACHED_HASH_MURMUR,
-  MEMCACHED_HASH_JENKINS
-} memcached_hash_t;
-
-typedef enum {
-  MEMCACHED_CONNECTION_UNKNOWN,
-  MEMCACHED_CONNECTION_TCP,
-  MEMCACHED_CONNECTION_UDP,
-  MEMCACHED_CONNECTION_UNIX_SOCKET
-} memcached_connection_t;
-
-#endif /* __MEMCACHED_CONSTANTS_H__ */
diff --git a/libmemcached/memcached_delete.c b/libmemcached/memcached_delete.c
deleted file mode 100644 (file)
index bbdd252..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-#include "common.h"
-#include "memcached/protocol_binary.h"
-
-memcached_return_t memcached_delete(memcached_st *ptr, const char *key, size_t key_length,
-                                    time_t expiration)
-{
-  return memcached_delete_by_key(ptr, key, key_length,
-                                 key, key_length, expiration);
-}
-
-static inline memcached_return_t binary_delete(memcached_st *ptr,
-                                               unsigned int server_key,
-                                               const char *key,
-                                               size_t key_length,
-                                               uint8_t flush);
-
-memcached_return_t memcached_delete_by_key(memcached_st *ptr,
-                                           const char *master_key, size_t master_key_length,
-                                           const char *key, size_t key_length,
-                                           time_t expiration)
-{
-  uint8_t to_write;
-  size_t send_length;
-  memcached_return_t rc;
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  unsigned int server_key;
-
-  LIBMEMCACHED_MEMCACHED_DELETE_START();
-
-  rc= memcached_validate_key_length(key_length,
-                                    ptr->flags.binary_protocol);
-  unlikely (rc != MEMCACHED_SUCCESS)
-    return rc;
-
-  unlikely (ptr->hosts == NULL || ptr->number_of_hosts == 0)
-    return MEMCACHED_NO_SERVERS;
-
-  server_key= memcached_generate_hash(ptr, master_key, master_key_length);
-  to_write= (uint8_t)((ptr->flags.buffer_requests) ? 0 : 1);
-  bool no_reply= (ptr->flags.no_reply);
-
-  if (ptr->flags.binary_protocol)
-  {
-    likely (!expiration)
-      rc= binary_delete(ptr, server_key, key, key_length, to_write);
-    else
-      rc= MEMCACHED_INVALID_ARGUMENTS;
-  }
-  else
-  {
-    unlikely (expiration)
-    {
-       if ((ptr->hosts[server_key].major_version == 1 &&
-            ptr->hosts[server_key].minor_version > 2) ||
-           ptr->hosts[server_key].major_version > 1)
-       {
-         rc= MEMCACHED_INVALID_ARGUMENTS;
-         goto error;
-       }
-       else
-       {
-          if (ptr->hosts[server_key].minor_version == 0)
-          {
-             if (no_reply || !to_write)
-             {
-                /* We might get out of sync with the server if we
-                 * send this command to a server newer than 1.2.x..
-                 * disable no_reply and buffered mode.
-                 */
-                to_write= 1;
-                if (no_reply)
-                   memcached_server_response_increment(&ptr->hosts[server_key]);
-                no_reply= false;
-             }
-          }
-          send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
-                                         "delete %s%.*s %u%s\r\n",
-                                         ptr->prefix_key,
-                                         (int) key_length, key,
-                                         (uint32_t)expiration,
-                                         no_reply ? " noreply" :"" );
-       }
-    }
-    else
-       send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE,
-                                      "delete %s%.*s%s\r\n",
-                                      ptr->prefix_key,
-                                      (int)key_length, key, no_reply ? " noreply" :"");
-
-    if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
-    {
-      rc= MEMCACHED_WRITE_FAILURE;
-      goto error;
-    }
-
-    if (ptr->flags.use_udp && !to_write)
-    {
-      if (send_length > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
-        return MEMCACHED_WRITE_FAILURE;
-      if (send_length + ptr->hosts[server_key].write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
-        memcached_io_write(&ptr->hosts[server_key], NULL, 0, 1);
-    }
-
-    rc= memcached_do(&ptr->hosts[server_key], buffer, send_length, to_write);
-  }
-
-  if (rc != MEMCACHED_SUCCESS)
-    goto error;
-
-  if (!to_write)
-    rc= MEMCACHED_BUFFERED;
-  else if (!no_reply)
-  {
-    rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
-    if (rc == MEMCACHED_DELETED)
-      rc= MEMCACHED_SUCCESS;
-  }
-
-  if (rc == MEMCACHED_SUCCESS && ptr->delete_trigger)
-    ptr->delete_trigger(ptr, key, key_length);
-
-error:
-  LIBMEMCACHED_MEMCACHED_DELETE_END();
-  return rc;
-}
-
-static inline memcached_return_t binary_delete(memcached_st *ptr,
-                                               unsigned int server_key,
-                                               const char *key,
-                                               size_t key_length,
-                                               uint8_t flush)
-{
-  protocol_binary_request_delete request= {.bytes= {0}};
-
-  request.message.header.request.magic= PROTOCOL_BINARY_REQ;
-  if (ptr->flags.no_reply)
-    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
-  else
-    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETE;
-  request.message.header.request.keylen= htons((uint16_t)key_length);
-  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-  request.message.header.request.bodylen= htonl((uint32_t) key_length);
-
-  if (ptr->flags.use_udp && !flush)
-  {
-    size_t cmd_size= sizeof(request.bytes) + key_length;
-    if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
-      return MEMCACHED_WRITE_FAILURE;
-    if (cmd_size + ptr->hosts[server_key].write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
-      memcached_io_write(&ptr->hosts[server_key], NULL, 0, 1);
-  }
-
-  memcached_return_t 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, (char) flush) == -1))
-  {
-    memcached_io_reset(&ptr->hosts[server_key]);
-    rc= MEMCACHED_WRITE_FAILURE;
-  }
-
-  unlikely (ptr->number_of_replicas > 0)
-  {
-    request.message.header.request.opcode= PROTOCOL_BINARY_CMD_DELETEQ;
-
-    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, (char) flush) == -1))
-        memcached_io_reset(server);
-      else
-        memcached_server_response_decrement(server);
-    }
-  }
-
-  return rc;
-}
diff --git a/libmemcached/memcached_do.c b/libmemcached/memcached_do.c
deleted file mode 100644 (file)
index d673f18..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "common.h"
-
-memcached_return_t memcached_do(memcached_server_st *ptr, const void *command, 
-                                size_t command_length, uint8_t with_flush)
-{
-  memcached_return_t rc;
-  ssize_t sent_length;
-
-  WATCHPOINT_ASSERT(command_length);
-  WATCHPOINT_ASSERT(command);
-
-  if ((rc= memcached_connect(ptr)) != MEMCACHED_SUCCESS)
-  {
-    WATCHPOINT_ERROR(rc);
-    return rc;
-  }
-
-  /*
-  ** Since non buffering ops in UDP mode dont check to make sure they will fit
-  ** before they start writing, if there is any data in buffer, clear it out,
-  ** otherwise we might get a partial write.
-  **/
-  if (ptr->type == MEMCACHED_CONNECTION_UDP && with_flush && ptr->write_buffer_offset > UDP_DATAGRAM_HEADER_LENGTH)
-    memcached_io_write(ptr, NULL, 0, 1);
-
-  sent_length= memcached_io_write(ptr, command, command_length, (char) with_flush);
-
-  if (sent_length == -1 || (size_t)sent_length != command_length)
-    rc= MEMCACHED_WRITE_FAILURE;
-  else if ((ptr->root->flags.no_reply) == 0)
-    memcached_server_response_increment(ptr);
-
-  return rc;
-}
diff --git a/libmemcached/memcached_dump.c b/libmemcached/memcached_dump.c
deleted file mode 100644 (file)
index 4c1006e..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-  We use this to dump all keys.
-
-  At this point we only support a callback method. This could be optimized by first
-  calling items and finding active slabs. For the moment though we just loop through
-  all slabs on servers and "grab" the keys.
-*/
-
-#include "common.h"
-static memcached_return_t ascii_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
-{
-  memcached_return_t rc= 0;
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  size_t send_length;
-  uint32_t server_key;
-  uint32_t x;
-
-  unlikely (ptr->number_of_hosts == 0)
-    return MEMCACHED_NO_SERVERS;
-
-  for (server_key= 0; server_key < ptr->number_of_hosts; server_key++)
-  {
-    /* 256 I BELIEVE is the upper limit of slabs */
-    for (x= 0; x < 256; x++)
-    {
-      send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
-                                     "stats cachedump %u 0 0\r\n", x);
-
-      rc= memcached_do(&ptr->hosts[server_key], buffer, send_length, 1);
-
-      unlikely (rc != MEMCACHED_SUCCESS)
-        goto error;
-
-      while (1)
-      {
-        uint32_t callback_counter;
-        rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
-
-        if (rc == MEMCACHED_ITEM)
-        {
-          char *string_ptr, *end_ptr;
-          char *key;
-
-          string_ptr= buffer;
-          string_ptr+= 5; /* Move past ITEM */
-          for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++);
-          key= string_ptr;
-          key[(size_t)(end_ptr-string_ptr)]= 0;
-          for (callback_counter= 0; callback_counter < number_of_callbacks; callback_counter++)
-          {
-            rc= (*callback[callback_counter])(ptr, key, (size_t)(end_ptr-string_ptr), context);
-            if (rc != MEMCACHED_SUCCESS)
-              break;
-          }
-        }
-        else if (rc == MEMCACHED_END)
-          break;
-        else if (rc == MEMCACHED_SERVER_ERROR || rc == MEMCACHED_CLIENT_ERROR)
-        {
-          /* If we try to request stats cachedump for a slab class that is too big
-           * the server will return an incorrect error message:
-           * "MEMCACHED_SERVER_ERROR failed to allocate memory"
-           * This isn't really a fatal error, so let's just skip it. I want to
-           * fix the return value from the memcached server to a CLIENT_ERROR,
-           * so let's add support for that as well right now.
-           */
-          rc= MEMCACHED_END;
-          break;
-        }
-        else
-          goto error;
-      }
-    }
-  }
-
-error:
-  if (rc == MEMCACHED_END)
-    return MEMCACHED_SUCCESS;
-  else
-    return rc;
-}
-
-memcached_return_t memcached_dump(memcached_st *ptr, memcached_dump_fn *callback, void *context, uint32_t number_of_callbacks)
-{
-  /* No support for Binary protocol yet */
-  if (ptr->flags.binary_protocol)
-    return MEMCACHED_FAILURE;
-
-  return ascii_dump(ptr, callback, context, number_of_callbacks);
-}
-
diff --git a/libmemcached/memcached_fetch.c b/libmemcached/memcached_fetch.c
deleted file mode 100644 (file)
index dbb1ff6..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-#include "common.h"
-#include "memcached_io.h"
-
-char *memcached_fetch(memcached_st *ptr, char *key, size_t *key_length, 
-                      size_t *value_length, 
-                      uint32_t *flags,
-                      memcached_return_t *error)
-{
-  memcached_result_st *result_buffer= &ptr->result;
-
-  unlikely (ptr->flags.use_udp)
-  {
-    *error= MEMCACHED_NOT_SUPPORTED;
-    return NULL;
-  }
-
-  result_buffer= memcached_fetch_result(ptr, result_buffer, error);
-
-  if (result_buffer == NULL || *error != MEMCACHED_SUCCESS)
-  {
-    WATCHPOINT_ASSERT(result_buffer == NULL);
-    *value_length= 0;
-    return NULL;
-  }
-
-  *value_length= memcached_string_length(&result_buffer->value);
-
-  if (key)
-  {
-    strncpy(key, result_buffer->key, result_buffer->key_length);
-    *key_length= result_buffer->key_length;
-  }
-
-  if (result_buffer->flags)
-    *flags= result_buffer->flags;
-  else
-    *flags= 0;
-
-  return memcached_string_c_copy(&result_buffer->value);
-}
-
-memcached_result_st *memcached_fetch_result(memcached_st *ptr,
-                                            memcached_result_st *result,
-                                            memcached_return_t *error)
-{
-  memcached_server_st *server;
-
-  unlikely (ptr->flags.use_udp)
-  {
-    *error= MEMCACHED_NOT_SUPPORTED;
-    return NULL;
-  }
-
-  if (result == NULL)
-    if ((result= memcached_result_create(ptr, NULL)) == NULL)
-      return NULL;
-
-  while ((server = memcached_io_get_readable_server(ptr)) != NULL) 
-  {
-    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-    *error= memcached_response(server, buffer, sizeof(buffer), result);
-
-    if (*error == MEMCACHED_SUCCESS)
-      return result;
-    else if (*error == MEMCACHED_END)
-      memcached_server_response_reset(server);
-    else if (*error != MEMCACHED_NOTFOUND)
-      break;
-  }
-
-  /* We have completed reading data */
-  if (memcached_is_allocated(result))
-  {
-    memcached_result_free(result);
-  }
-  else
-  {
-    memcached_string_reset(&result->value);
-  }
-
-  return NULL;
-}
-
-memcached_return_t memcached_fetch_execute(memcached_st *ptr, 
-                                           memcached_execute_fn *callback,
-                                           void *context,
-                                           uint32_t number_of_callbacks)
-{
-  memcached_result_st *result= &ptr->result;
-  memcached_return_t rc= MEMCACHED_FAILURE;
-  unsigned int x;
-
-  while ((result= memcached_fetch_result(ptr, result, &rc)) != NULL) 
-  {
-    if (rc == MEMCACHED_SUCCESS)
-    {
-      for (x= 0; x < number_of_callbacks; x++)
-      {
-        rc= (*callback[x])(ptr, result, context);
-        if (rc != MEMCACHED_SUCCESS)
-          break;
-      }
-    }
-  }
-  return rc;
-}
diff --git a/libmemcached/memcached_flush.c b/libmemcached/memcached_flush.c
deleted file mode 100644 (file)
index d05d744..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "common.h"
-
-static memcached_return_t memcached_flush_binary(memcached_st *ptr, 
-                                                 time_t expiration);
-static memcached_return_t memcached_flush_textual(memcached_st *ptr, 
-                                                  time_t expiration);
-
-memcached_return_t memcached_flush(memcached_st *ptr, time_t expiration)
-{
-  memcached_return_t rc;
-
-  LIBMEMCACHED_MEMCACHED_FLUSH_START();
-  if (ptr->flags.binary_protocol)
-    rc= memcached_flush_binary(ptr, expiration);
-  else
-    rc= memcached_flush_textual(ptr, expiration);
-  LIBMEMCACHED_MEMCACHED_FLUSH_END();
-  return rc;
-}
-
-static memcached_return_t memcached_flush_textual(memcached_st *ptr, 
-                                                  time_t expiration)
-{
-  unsigned int x;
-  size_t send_length;
-  memcached_return_t rc;
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-
-  unlikely (ptr->number_of_hosts == 0)
-    return MEMCACHED_NO_SERVERS;
-
-  for (x= 0; x < ptr->number_of_hosts; x++)
-  {
-    bool no_reply= ptr->flags.no_reply;
-
-    if (expiration)
-      send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
-                                     "flush_all %llu%s\r\n",
-                                     (unsigned long long)expiration, no_reply ? " noreply" : "");
-    else
-      send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
-                                     "flush_all%s\r\n", no_reply ? " noreply" : "");
-
-    rc= memcached_do(&ptr->hosts[x], buffer, send_length, 1);
-
-    if (rc == MEMCACHED_SUCCESS && !no_reply)
-      (void)memcached_response(&ptr->hosts[x], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-static memcached_return_t memcached_flush_binary(memcached_st *ptr, 
-                                                 time_t expiration)
-{
-  unsigned int x;
-  protocol_binary_request_flush request= {.bytes= {0}};
-
-  unlikely (ptr->number_of_hosts == 0)
-    return MEMCACHED_NO_SERVERS;
-
-  request.message.header.request.magic= (uint8_t)PROTOCOL_BINARY_REQ;
-  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
-  request.message.header.request.extlen= 4;
-  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-  request.message.header.request.bodylen= htonl(request.message.header.request.extlen);
-  request.message.body.expiration= htonl((uint32_t) expiration);
-
-  for (x= 0; x < ptr->number_of_hosts; x++)
-  {
-    if (ptr->flags.no_reply)
-      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSHQ;
-    else
-      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_FLUSH;
-    if (memcached_do(&ptr->hosts[x], request.bytes, 
-                     sizeof(request.bytes), 1) != MEMCACHED_SUCCESS) 
-    {
-      memcached_io_reset(&ptr->hosts[x]);
-      return MEMCACHED_WRITE_FAILURE;
-    } 
-  }
-
-  for (x= 0; x < ptr->number_of_hosts; x++)
-  {
-    if (memcached_server_response_count(&ptr->hosts[x]) > 0)
-      (void)memcached_response(&ptr->hosts[x], NULL, 0, NULL);
-  }
-
-  return MEMCACHED_SUCCESS;
-}
diff --git a/libmemcached/memcached_flush_buffers.c b/libmemcached/memcached_flush_buffers.c
deleted file mode 100644 (file)
index f001e21..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#include "common.h"
-#include "memcached_io.h"
-
-memcached_return_t memcached_flush_buffers(memcached_st *mem)
-{
-  memcached_return_t ret= MEMCACHED_SUCCESS;
-
-  for (uint32_t x= 0; x < mem->number_of_hosts; ++x)
-    if (mem->hosts[x].write_buffer_offset != 0) 
-    {
-      if (mem->hosts[x].fd == -1 &&
-          (ret= memcached_connect(&mem->hosts[x])) != MEMCACHED_SUCCESS)
-      {
-        WATCHPOINT_ERROR(ret);
-        return ret;
-      }
-      if (memcached_io_write(&mem->hosts[x], NULL, 0, 1) == -1)
-        ret= MEMCACHED_SOME_ERRORS;
-    }
-
-  return ret;
-}
diff --git a/libmemcached/memcached_get.c b/libmemcached/memcached_get.c
deleted file mode 100644 (file)
index 27a1410..0000000
+++ /dev/null
@@ -1,575 +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: Get functions for libmemcached
- *
- */
-
-#include "common.h"
-#include "memcached_io.h"
-
-/*
-  What happens if no servers exist?
-*/
-char *memcached_get(memcached_st *ptr, const char *key,
-                    size_t key_length,
-                    size_t *value_length,
-                    uint32_t *flags,
-                    memcached_return_t *error)
-{
-  return memcached_get_by_key(ptr, NULL, 0, key, key_length, value_length,
-                              flags, error);
-}
-
-static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
-                                                     const char *master_key,
-                                                     size_t master_key_length,
-                                                     const char * const *keys,
-                                                     const size_t *key_length,
-                                                     size_t number_of_keys,
-                                                     bool mget_mode);
-
-char *memcached_get_by_key(memcached_st *ptr,
-                           const char *master_key,
-                           size_t master_key_length,
-                           const char *key, size_t key_length,
-                           size_t *value_length,
-                           uint32_t *flags,
-                           memcached_return_t *error)
-{
-  char *value;
-  size_t dummy_length;
-  uint32_t dummy_flags;
-  memcached_return_t dummy_error;
-
-  unlikely (ptr->flags.use_udp)
-  {
-    *error= MEMCACHED_NOT_SUPPORTED;
-    return NULL;
-  }
-
-  /* Request the key */
-  *error= memcached_mget_by_key_real(ptr, master_key, master_key_length,
-                                     (const char * const *)&key,
-                                     &key_length, 1, false);
-
-  value= memcached_fetch(ptr, NULL, NULL,
-                         value_length, flags, error);
-  /* This is for historical reasons */
-  if (*error == MEMCACHED_END)
-    *error= MEMCACHED_NOTFOUND;
-
-  if (value == NULL)
-  {
-    if (ptr->get_key_failure && *error == MEMCACHED_NOTFOUND)
-    {
-      memcached_return_t rc;
-
-      memcached_result_reset(&ptr->result);
-      rc= ptr->get_key_failure(ptr, key, key_length, &ptr->result);
-
-      /* On all failure drop to returning NULL */
-      if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED)
-      {
-        if (rc == MEMCACHED_BUFFERED)
-        {
-          uint64_t latch; /* We use latch to track the state of the original socket */
-          latch= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS);
-          if (latch == 0)
-            memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1);
-
-          rc= memcached_set(ptr, key, key_length,
-                            memcached_result_value(&ptr->result),
-                            memcached_result_length(&ptr->result),
-                            0, memcached_result_flags(&ptr->result));
-
-          if (rc == MEMCACHED_BUFFERED && latch == 0)
-            memcached_behavior_set(ptr, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 0);
-        }
-        else
-        {
-          rc= memcached_set(ptr, key, key_length,
-                            memcached_result_value(&ptr->result),
-                            memcached_result_length(&ptr->result),
-                            0, memcached_result_flags(&ptr->result));
-        }
-
-        if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED)
-        {
-          *error= rc;
-          *value_length= memcached_result_length(&ptr->result);
-          *flags= memcached_result_flags(&ptr->result);
-          return memcached_string_c_copy(&ptr->result.value);
-        }
-      }
-    }
-
-    return NULL;
-  }
-
-  (void)memcached_fetch(ptr, NULL, NULL,
-                        &dummy_length, &dummy_flags,
-                        &dummy_error);
-  WATCHPOINT_ASSERT(dummy_length == 0);
-
-  return value;
-}
-
-memcached_return_t memcached_mget(memcached_st *ptr,
-                                  const char * const *keys,
-                                  const size_t *key_length,
-                                  size_t number_of_keys)
-{
-  return memcached_mget_by_key(ptr, NULL, 0, keys, key_length, number_of_keys);
-}
-
-static memcached_return_t binary_mget_by_key(memcached_st *ptr,
-                                             unsigned int master_server_key,
-                                             bool is_master_key_set,
-                                             const char * const *keys,
-                                             const size_t *key_length,
-                                             size_t number_of_keys,
-                                             bool mget_mode);
-
-static memcached_return_t memcached_mget_by_key_real(memcached_st *ptr,
-                                                     const char *master_key,
-                                                     size_t master_key_length,
-                                                     const char * const *keys,
-                                                     const size_t *key_length,
-                                                     size_t number_of_keys,
-                                                     bool mget_mode)
-{
-  unsigned int x;
-  memcached_return_t rc= MEMCACHED_NOTFOUND;
-  const char *get_command= "get ";
-  uint8_t get_command_length= 4;
-  unsigned int master_server_key= (unsigned int)-1; /* 0 is a valid server id! */
-  bool is_master_key_set= false;
-
-  unlikely (ptr->flags.use_udp)
-    return MEMCACHED_NOT_SUPPORTED;
-
-  LIBMEMCACHED_MEMCACHED_MGET_START();
-  ptr->cursor_server= 0;
-
-  if (number_of_keys == 0)
-    return MEMCACHED_NOTFOUND;
-
-  if (ptr->number_of_hosts == 0)
-    return MEMCACHED_NO_SERVERS;
-
-  if (ptr->flags.verify_key && (memcached_key_test(keys, key_length, number_of_keys) == MEMCACHED_BAD_KEY_PROVIDED))
-    return MEMCACHED_BAD_KEY_PROVIDED;
-
-  if (master_key && master_key_length)
-  {
-    if (ptr->flags.verify_key && (memcached_key_test((const char * const *)&master_key, &master_key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
-      return MEMCACHED_BAD_KEY_PROVIDED;
-    master_server_key= memcached_generate_hash(ptr, master_key, master_key_length);
-    is_master_key_set= true;
-  }
-
-  /*
-    Here is where we pay for the non-block API. We need to remove any data sitting
-    in the queue before we start our get.
-
-    It might be optimum to bounce the connection if count > some number.
-  */
-  for (x= 0; x < ptr->number_of_hosts; x++)
-  {
-    if (memcached_server_response_count(&ptr->hosts[x]))
-    {
-      char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-
-      if (ptr->flags.no_block)
-        (void)memcached_io_write(&ptr->hosts[x], NULL, 0, 1);
-
-      while(memcached_server_response_count(&ptr->hosts[x]))
-        (void)memcached_response(&ptr->hosts[x], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, &ptr->result);
-    }
-  }
-
-  if (ptr->flags.binary_protocol)
-    return binary_mget_by_key(ptr, master_server_key, is_master_key_set, keys,
-                              key_length, number_of_keys, mget_mode);
-
-  if (ptr->flags.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.
-  */
-  for (x= 0; x < number_of_keys; x++)
-  {
-    unsigned int server_key;
-
-    if (is_master_key_set)
-      server_key= master_server_key;
-    else
-      server_key= memcached_generate_hash(ptr, keys[x], key_length[x]);
-
-    if (memcached_server_response_count(&ptr->hosts[server_key]) == 0)
-    {
-      rc= memcached_connect(&ptr->hosts[server_key]);
-
-      if (rc != MEMCACHED_SUCCESS)
-        continue;
-
-      if ((memcached_io_write(&ptr->hosts[server_key], get_command, get_command_length, 0)) == -1)
-      {
-        rc= MEMCACHED_SOME_ERRORS;
-        continue;
-      }
-      WATCHPOINT_ASSERT(ptr->hosts[server_key].cursor_active == 0);
-      memcached_server_response_increment(&ptr->hosts[server_key]);
-      WATCHPOINT_ASSERT(ptr->hosts[server_key].cursor_active == 1);
-    }
-
-    /* Only called when we have a prefix key */
-    if (ptr->prefix_key[0] != 0)
-    {
-      if ((memcached_io_write(&ptr->hosts[server_key], ptr->prefix_key, ptr->prefix_key_length, 0)) == -1)
-      {
-        memcached_server_response_reset(&ptr->hosts[server_key]);
-        rc= MEMCACHED_SOME_ERRORS;
-        continue;
-      }
-    }
-
-    if ((memcached_io_write(&ptr->hosts[server_key], keys[x], key_length[x], 0)) == -1)
-    {
-      memcached_server_response_reset(&ptr->hosts[server_key]);
-      rc= MEMCACHED_SOME_ERRORS;
-      continue;
-    }
-
-    if ((memcached_io_write(&ptr->hosts[server_key], " ", 1, 0)) == -1)
-    {
-      memcached_server_response_reset(&ptr->hosts[server_key]);
-      rc= MEMCACHED_SOME_ERRORS;
-      continue;
-    }
-  }
-
-  /*
-    Should we muddle on if some servers are dead?
-  */
-  for (x= 0; x < ptr->number_of_hosts; x++)
-  {
-    if (memcached_server_response_count(&ptr->hosts[x]))
-    {
-      /* We need to do something about non-connnected hosts in the future */
-      if ((memcached_io_write(&ptr->hosts[x], "\r\n", 2, 1)) == -1)
-      {
-        rc= MEMCACHED_SOME_ERRORS;
-      }
-    }
-  }
-
-  LIBMEMCACHED_MEMCACHED_MGET_END();
-  return rc;
-}
-
-memcached_return_t memcached_mget_by_key(memcached_st *ptr,
-                                         const char *master_key,
-                                         size_t master_key_length,
-                                         const char * const *keys,
-                                         const size_t *key_length,
-                                         size_t number_of_keys)
-{
-  return memcached_mget_by_key_real(ptr, master_key, master_key_length, keys,
-                                    key_length, number_of_keys, true);
-}
-
-memcached_return_t memcached_mget_execute(memcached_st *ptr,
-                                          const char * const *keys,
-                                          const size_t *key_length,
-                                          size_t number_of_keys,
-                                          memcached_execute_fn *callback,
-                                          void *context,
-                                          unsigned int number_of_callbacks)
-{
-  return memcached_mget_execute_by_key(ptr, NULL, 0, keys, key_length,
-                                       number_of_keys, callback,
-                                       context, number_of_callbacks);
-}
-
-memcached_return_t memcached_mget_execute_by_key(memcached_st *ptr,
-                                                 const char *master_key,
-                                                 size_t master_key_length,
-                                                 const char * const *keys,
-                                                 const size_t *key_length,
-                                                 size_t number_of_keys,
-                                                 memcached_execute_fn *callback,
-                                                 void *context,
-                                                 unsigned int number_of_callbacks)
-{
-  if ((ptr->flags.binary_protocol) == 0)
-    return MEMCACHED_NOT_SUPPORTED;
-
-  memcached_return_t rc;
-  memcached_callback_st *original_callbacks= ptr->callbacks;
-  memcached_callback_st cb= {
-    .callback= callback,
-    .context= context,
-    .number_of_callback= number_of_callbacks
-  };
-
-  ptr->callbacks= &cb;
-  rc= memcached_mget_by_key(ptr, master_key, master_key_length, keys,
-                            key_length, number_of_keys);
-  ptr->callbacks= original_callbacks;
-  return rc;
-}
-
-static memcached_return_t simple_binary_mget(memcached_st *ptr,
-                                             unsigned int master_server_key,
-                                             bool is_master_key_set,
-                                             const char * const *keys,
-                                             const size_t *key_length,
-                                             size_t number_of_keys, bool mget_mode)
-{
-  memcached_return_t rc= MEMCACHED_NOTFOUND;
-  uint32_t x;
-
-  int flush= number_of_keys == 1;
-
-  /*
-    If a server fails we warn about errors and start all over with sending keys
-    to the server.
-  */
-  for (x= 0; x < number_of_keys; x++)
-  {
-    unsigned int server_key;
-
-    if (is_master_key_set)
-      server_key= master_server_key;
-    else
-      server_key= memcached_generate_hash(ptr, keys[x], key_length[x]);
-
-    if (memcached_server_response_count(&ptr->hosts[server_key]) == 0)
-    {
-      rc= memcached_connect(&ptr->hosts[server_key]);
-      if (rc != MEMCACHED_SUCCESS)
-        continue;
-    }
-
-    protocol_binary_request_getk request= {.bytes= {0}};
-    request.message.header.request.magic= PROTOCOL_BINARY_REQ;
-    if (mget_mode)
-      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETKQ;
-    else
-      request.message.header.request.opcode= PROTOCOL_BINARY_CMD_GETK;
-
-    memcached_return_t vk;
-    vk= memcached_validate_key_length(key_length[x],
-                                      ptr->flags.binary_protocol);
-    unlikely (vk != MEMCACHED_SUCCESS)
-    {
-      if (x > 0)
-        memcached_io_reset(&ptr->hosts[server_key]);
-      return vk;
-    }
-
-    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((uint32_t) key_length[x]);
-
-    if ((memcached_io_write(&ptr->hosts[server_key], request.bytes,
-                            sizeof(request.bytes), 0) == -1) ||
-        (memcached_io_write(&ptr->hosts[server_key], keys[x],
-                            key_length[x], (char) flush) == -1))
-    {
-      memcached_server_response_reset(&ptr->hosts[server_key]);
-      rc= MEMCACHED_SOME_ERRORS;
-      continue;
-    }
-
-    /* We just want one pending response per server */
-    memcached_server_response_reset(&ptr->hosts[server_key]);
-    memcached_server_response_increment(&ptr->hosts[server_key]);
-    if ((x > 0 && x == ptr->io_key_prefetch) &&
-        memcached_flush_buffers(ptr) != MEMCACHED_SUCCESS)
-      rc= MEMCACHED_SOME_ERRORS;
-  }
-
-  if (mget_mode)
-  {
-    /*
-     * Send a noop command to flush the buffers
-   */
-    protocol_binary_request_noop request= {.bytes= {0}};
-    request.message.header.request.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], NULL, 0, 1) == -1)
-        {
-          memcached_server_response_reset(&ptr->hosts[x]);
-          memcached_io_reset(&ptr->hosts[x]);
-          rc= MEMCACHED_SOME_ERRORS;
-        }
-
-        if (memcached_io_write(&ptr->hosts[x], request.bytes,
-                               sizeof(request.bytes), 1) == -1)
-        {
-          memcached_server_response_reset(&ptr->hosts[x]);
-          memcached_io_reset(&ptr->hosts[x]);
-          rc= MEMCACHED_SOME_ERRORS;
-        }
-      }
-  }
-
-
-  return rc;
-}
-
-static memcached_return_t replication_binary_mget(memcached_st *ptr,
-                                                  uint32_t* hash,
-                                                  bool* dead_servers,
-                                                  const char *const *keys,
-                                                  const size_t *key_length,
-                                                  size_t number_of_keys)
-{
-  memcached_return_t rc= MEMCACHED_NOTFOUND;
-  uint32_t x, start= 0;
-  uint64_t randomize_read= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_RANDOMIZE_REPLICA_READ);
-
-  if (randomize_read)
-    start= (uint32_t)random() % (uint32_t)(ptr->number_of_replicas + 1);
-
-  /* Loop for each replica */
-  for (uint32_t replica= 0; replica <= ptr->number_of_replicas; ++replica)
-  {
-    bool success= true;
-
-    for (x= 0; x < number_of_keys; ++x)
-    {
-      if (hash[x] == ptr->number_of_hosts)
-        continue; /* Already successfully sent */
-
-      uint32_t server= hash[x] + replica;
-
-      /* In case of randomized reads */
-      if (randomize_read && ((server + start) <= (hash[x] + ptr->number_of_replicas)))
-        server += start;
-
-      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= {
-        .message.header.request= {
-          .magic= PROTOCOL_BINARY_REQ,
-          .opcode= PROTOCOL_BINARY_CMD_GETK,
-          .keylen= htons((uint16_t)key_length[x]),
-          .datatype= PROTOCOL_BINARY_RAW_BYTES,
-          .bodylen= htonl((uint32_t)key_length[x])
-        }
-      };
-
-      /*
-       * We need to disable buffering to actually know that the request was
-       * successfully sent to the server (so that we should expect a result
-       * back). It would be nice to do this in buffered mode, but then it
-       * would be complex to handle all error situations if we got to send
-       * some of the messages, and then we failed on writing out some others
-       * and we used the callback interface from memcached_mget_execute so
-       * that we might have processed some of the responses etc. For now,
-       * just make sure we work _correctly_
-     */
-      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], 1) == -1))
-      {
-        memcached_io_reset(&ptr->hosts[server]);
-        dead_servers[server]= true;
-        success= false;
-        continue;
-      }
-
-      memcached_server_response_increment(&ptr->hosts[server]);
-      hash[x]= ptr->number_of_hosts;
-    }
-
-    if (success)
-      break;
-  }
-
-  return rc;
-}
-
-static memcached_return_t binary_mget_by_key(memcached_st *ptr,
-                                             unsigned int master_server_key,
-                                             bool is_master_key_set,
-                                             const char * const *keys,
-                                             const size_t *key_length,
-                                             size_t number_of_keys,
-                                             bool mget_mode)
-{
-  memcached_return_t 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, mget_mode);
-  }
-  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;
-}
diff --git a/libmemcached/memcached_get.h b/libmemcached/memcached_get.h
deleted file mode 100644 (file)
index bb04a15..0000000
+++ /dev/null
@@ -1,84 +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: Get functions for libmemcached
- *
- */
-
-#ifndef LIBMEMCACHED_MEMCACHED_GET_H
-#define LIBMEMCACHED_MEMCACHED_GET_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Public defines */
-LIBMEMCACHED_API
-char *memcached_get(memcached_st *ptr, 
-                    const char *key, size_t key_length,
-                    size_t *value_length, 
-                    uint32_t *flags,
-                    memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_mget(memcached_st *ptr, 
-                                  const char * const *keys, 
-                                  const size_t *key_length, 
-                                  size_t number_of_keys);
-
-LIBMEMCACHED_API
-char *memcached_get_by_key(memcached_st *ptr, 
-                           const char *master_key, size_t master_key_length, 
-                           const char *key, size_t key_length, 
-                           size_t *value_length, 
-                           uint32_t *flags,
-                           memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_mget_by_key(memcached_st *ptr, 
-                                         const char *master_key, size_t 
-                                         master_key_length,
-                                         const char * const *keys, 
-                                         const size_t *key_length, 
-                                         size_t number_of_keys);
-
-LIBMEMCACHED_API
-char *memcached_fetch(memcached_st *ptr, 
-                      char *key, size_t *key_length, 
-                      size_t *value_length, uint32_t *flags, 
-                      memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_result_st *memcached_fetch_result(memcached_st *ptr, 
-                                            memcached_result_st *result,
-                                            memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_mget_execute(memcached_st *ptr,
-                                          const char * const *keys,
-                                          const size_t *key_length,
-                                          size_t number_of_keys,
-                                          memcached_execute_fn *callback,
-                                          void *context,
-                                          unsigned int number_of_callbacks);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_mget_execute_by_key(memcached_st *ptr,
-                                                 const char *master_key,
-                                                 size_t master_key_length,
-                                                 const char * const *keys,
-                                                 const size_t *key_length,
-                                                 size_t number_of_keys,
-                                                 memcached_execute_fn *callback,
-                                                 void *context,
-                                                 unsigned int number_of_callbacks);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LIBMEMCACHED_MEMCACHED_GET_H */
diff --git a/libmemcached/memcached_hash.c b/libmemcached/memcached_hash.c
deleted file mode 100644 (file)
index 395020a..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-#include "common.h"
-
-
-/* Defines */
-static uint64_t FNV_64_INIT= UINT64_C(0xcbf29ce484222325);
-static uint64_t FNV_64_PRIME= UINT64_C(0x100000001b3);
-
-static uint32_t FNV_32_INIT= 2166136261UL;
-static uint32_t FNV_32_PRIME= 16777619;
-
-/* Prototypes */
-static uint32_t internal_generate_hash(const char *key, size_t key_length);
-static uint32_t internal_generate_md5(const char *key, size_t key_length);
-
-uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash_t hash_algorithm)
-{
-  uint32_t hash= 1; /* Just here to remove compile warning */
-  uint32_t x= 0;
-
-  switch (hash_algorithm)
-  {
-  case MEMCACHED_HASH_DEFAULT:
-    hash= internal_generate_hash(key, key_length);
-    break;
-  case MEMCACHED_HASH_MD5:
-    hash= internal_generate_md5(key, key_length);
-    break;
-  case MEMCACHED_HASH_CRC:
-    hash= ((hash_crc32(key, key_length) >> 16) & 0x7fff);
-    if (hash == 0)
-      hash= 1;
-    break;
-    /* FNV hash'es lifted from Dustin Sallings work */
-  case MEMCACHED_HASH_FNV1_64:
-    {
-      /* Thanks to pierre@demartines.com for the pointer */
-      uint64_t temp_hash;
-
-      temp_hash= FNV_64_INIT;
-      for (x= 0; x < key_length; x++)
-      {
-        temp_hash *= FNV_64_PRIME;
-        temp_hash ^= (uint64_t)key[x];
-      }
-      hash= (uint32_t)temp_hash;
-    }
-    break;
-  case MEMCACHED_HASH_FNV1A_64:
-    {
-      hash= (uint32_t) FNV_64_INIT;
-      for (x= 0; x < key_length; x++)
-      {
-        uint32_t val= (uint32_t)key[x];
-        hash ^= val;
-        hash *= (uint32_t) FNV_64_PRIME;
-      }
-    }
-    break;
-  case MEMCACHED_HASH_FNV1_32:
-    {
-      hash= FNV_32_INIT;
-      for (x= 0; x < key_length; x++)
-      {
-        uint32_t val= (uint32_t)key[x];
-        hash *= FNV_32_PRIME;
-        hash ^= val;
-      }
-    }
-    break;
-  case MEMCACHED_HASH_FNV1A_32:
-    {
-      hash= FNV_32_INIT;
-      for (x= 0; x < key_length; x++)
-      {
-        uint32_t val= (uint32_t)key[x];
-        hash ^= val;
-        hash *= FNV_32_PRIME;
-      }
-    }
-    break;
-    case MEMCACHED_HASH_HSIEH:
-    {
-#ifdef HAVE_HSIEH_HASH
-      hash= hsieh_hash(key, key_length);
-#endif
-      break;
-    }
-    case MEMCACHED_HASH_MURMUR:
-    {
-      hash= murmur_hash(key, key_length);
-      break;
-    }
-    case MEMCACHED_HASH_JENKINS:
-    {
-      hash=jenkins_hash(key, key_length, 13);
-      break;
-    }
-    default:
-    {
-      WATCHPOINT_ASSERT(hash_algorithm);
-      break;
-    }
-  }
-  return hash;
-}
-
-uint32_t generate_hash(memcached_st *ptr, const char *key, size_t key_length)
-{
-  uint32_t hash= 1; /* Just here to remove compile warning */
-
-
-  WATCHPOINT_ASSERT(ptr->number_of_hosts);
-
-  if (ptr->number_of_hosts == 1)
-    return 0;
-
-  hash= memcached_generate_hash_value(key, key_length, ptr->hash);
-  WATCHPOINT_ASSERT(hash);
-  return hash;
-}
-
-static uint32_t dispatch_host(memcached_st *ptr, uint32_t hash)
-{
-  switch (ptr->distribution)
-  {
-  case MEMCACHED_DISTRIBUTION_CONSISTENT:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
-    {
-      uint32_t num= ptr->continuum_points_counter;
-      WATCHPOINT_ASSERT(ptr->continuum);
-
-      hash= hash;
-      memcached_continuum_item_st *begin, *end, *left, *right, *middle;
-      begin= left= ptr->continuum;
-      end= right= ptr->continuum + num;
-
-      while (left < right)
-      {
-        middle= left + (right - left) / 2;
-        if (middle->value < hash)
-          left= middle + 1;
-        else
-          right= middle;
-      }
-      if (right == end)
-        right= begin;
-      return right->index;
-    }
-  case MEMCACHED_DISTRIBUTION_MODULA:
-    return hash % ptr->number_of_hosts;
-  case MEMCACHED_DISTRIBUTION_RANDOM:
-    return (uint32_t) random() % ptr->number_of_hosts;
-  default:
-    WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
-    return hash % ptr->number_of_hosts;
-  }
-
-  /* NOTREACHED */
-}
-
-/*
-  One day make this public, and have it return the actual memcached_server_st
-  to the calling application.
-*/
-uint32_t memcached_generate_hash(memcached_st *ptr, const char *key, size_t key_length)
-{
-  uint32_t hash= 1; /* Just here to remove compile warning */
-
-  WATCHPOINT_ASSERT(ptr->number_of_hosts);
-
-  if (ptr->number_of_hosts == 1)
-    return 0;
-
-  if (ptr->flags.hash_with_prefix_key)
-  {
-    size_t temp_length= ptr->prefix_key_length + key_length;
-    char temp[temp_length];
-
-    if (temp_length > MEMCACHED_MAX_KEY -1)
-      return 0;
-
-    strncpy(temp, ptr->prefix_key, ptr->prefix_key_length);
-    strncpy(temp + ptr->prefix_key_length, key, key_length);
-    hash= generate_hash(ptr, temp, temp_length);
-  }
-  else
-  {
-    hash= generate_hash(ptr, key, key_length);
-  }
-
-  WATCHPOINT_ASSERT(hash);
-
-  if (memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS) && ptr->next_distribution_rebuild) {
-    struct timeval now;
-
-    if (gettimeofday(&now, NULL) == 0 &&
-        now.tv_sec > ptr->next_distribution_rebuild)
-      run_distribution(ptr);
-  }
-
-  return dispatch_host(ptr, hash);
-}
-
-static uint32_t internal_generate_hash(const char *key, size_t key_length)
-{
-  const char *ptr= key;
-  uint32_t value= 0;
-
-  while (key_length--)
-  {
-    uint32_t val= (uint32_t) *ptr++;
-    value += val;
-    value += (value << 10);
-    value ^= (value >> 6);
-  }
-  value += (value << 3);
-  value ^= (value >> 11);
-  value += (value << 15);
-
-  return value == 0 ? 1 : (uint32_t) value;
-}
-
-static uint32_t internal_generate_md5(const char *key, size_t key_length)
-{
-  unsigned char results[16];
-
-  md5_signature((unsigned char*)key, (unsigned int)key_length, results);
-
-  return ((uint32_t) (results[3] & 0xFF) << 24)
-    | ((uint32_t) (results[2] & 0xFF) << 16)
-    | ((uint32_t) (results[1] & 0xFF) << 8)
-    | (results[0] & 0xFF);
-}
diff --git a/libmemcached/memcached_hosts.c b/libmemcached/memcached_hosts.c
deleted file mode 100644 (file)
index 8cc5f3e..0000000
+++ /dev/null
@@ -1,514 +0,0 @@
-#include "common.h"
-#include <math.h>
-
-/* Protoypes (static) */
-static memcached_return_t server_add(memcached_st *ptr, const char *hostname,
-                                     in_port_t port,
-                                     uint32_t weight,
-                                     memcached_connection_t type);
-memcached_return_t update_continuum(memcached_st *ptr);
-
-static int compare_servers(const void *p1, const void *p2)
-{
-  int return_value;
-  memcached_server_st *a= (memcached_server_st *)p1;
-  memcached_server_st *b= (memcached_server_st *)p2;
-
-  return_value= strcmp(a->hostname, b->hostname);
-
-  if (return_value == 0)
-  {
-    return_value= (int) (a->port - b->port);
-  }
-
-  return return_value;
-}
-
-static void sort_hosts(memcached_st *ptr)
-{
-  if (ptr->number_of_hosts)
-  {
-    qsort(ptr->hosts, ptr->number_of_hosts, sizeof(memcached_server_st), compare_servers);
-    ptr->hosts[0].count= (uint16_t) ptr->number_of_hosts;
-  }
-}
-
-
-memcached_return_t run_distribution(memcached_st *ptr)
-{
-  switch (ptr->distribution)
-  {
-  case MEMCACHED_DISTRIBUTION_CONSISTENT:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA:
-  case MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY:
-    return update_continuum(ptr);
-  case MEMCACHED_DISTRIBUTION_MODULA:
-    if (ptr->flags.use_sort_hosts)
-      sort_hosts(ptr);
-    break;
-  case MEMCACHED_DISTRIBUTION_RANDOM:
-    break;
-  default:
-    WATCHPOINT_ASSERT(0); /* We have added a distribution without extending the logic */
-  }
-
-  ptr->last_disconnected_server = NULL;
-
-  return MEMCACHED_SUCCESS;
-}
-
-void server_list_free(memcached_st *ptr, memcached_server_st *servers)
-{
-  unsigned int x;
-
-  if (servers == NULL)
-    return;
-
-  for (x= 0; x < servers->count; x++)
-    if (servers[x].address_info)
-    {
-      freeaddrinfo(servers[x].address_info);
-      servers[x].address_info= NULL;
-    }
-
-  if (ptr)
-    ptr->call_free(ptr, servers);
-  else
-    free(servers);
-}
-
-static uint32_t ketama_server_hash(const char *key, unsigned int key_length, int alignment)
-{
-  unsigned char results[16];
-
-  md5_signature((unsigned char*)key, key_length, results);
-  return ((uint32_t) (results[3 + alignment * 4] & 0xFF) << 24)
-    | ((uint32_t) (results[2 + alignment * 4] & 0xFF) << 16)
-    | ((uint32_t) (results[1 + alignment * 4] & 0xFF) << 8)
-    | (results[0 + alignment * 4] & 0xFF);
-}
-
-static int continuum_item_cmp(const void *t1, const void *t2)
-{
-  memcached_continuum_item_st *ct1= (memcached_continuum_item_st *)t1;
-  memcached_continuum_item_st *ct2= (memcached_continuum_item_st *)t2;
-
-  /* Why 153? Hmmm... */
-  WATCHPOINT_ASSERT(ct1->value != 153);
-  if (ct1->value == ct2->value)
-    return 0;
-  else if (ct1->value > ct2->value)
-    return 1;
-  else
-    return -1;
-}
-
-memcached_return_t update_continuum(memcached_st *ptr)
-{
-  uint32_t host_index;
-  uint32_t continuum_index= 0;
-  uint32_t value;
-  memcached_server_st *list;
-  uint32_t pointer_index;
-  uint32_t pointer_counter= 0;
-  uint32_t pointer_per_server= MEMCACHED_POINTS_PER_SERVER;
-  uint32_t pointer_per_hash= 1;
-  uint64_t total_weight= 0;
-  uint64_t is_ketama_weighted= 0;
-  uint64_t is_auto_ejecting= 0;
-  uint32_t points_per_server= 0;
-  uint32_t live_servers= 0;
-  struct timeval now;
-
-  if (gettimeofday(&now, NULL) != 0)
-  {
-    ptr->cached_errno = errno;
-    return MEMCACHED_ERRNO;
-  }
-
-  list = ptr->hosts;
-
-  /* count live servers (those without a retry delay set) */
-  is_auto_ejecting= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS);
-  if (is_auto_ejecting)
-  {
-    live_servers= 0;
-    ptr->next_distribution_rebuild= 0;
-    for (host_index= 0; host_index < ptr->number_of_hosts; ++host_index)
-    {
-      if (list[host_index].next_retry <= now.tv_sec)
-        live_servers++;
-      else
-      {
-        if (ptr->next_distribution_rebuild == 0 || list[host_index].next_retry < ptr->next_distribution_rebuild)
-          ptr->next_distribution_rebuild= list[host_index].next_retry;
-      }
-    }
-  }
-  else
-    live_servers= ptr->number_of_hosts;
-
-  is_ketama_weighted= memcached_behavior_get(ptr, MEMCACHED_BEHAVIOR_KETAMA_WEIGHTED);
-  points_per_server= (uint32_t) (is_ketama_weighted ? MEMCACHED_POINTS_PER_SERVER_KETAMA : MEMCACHED_POINTS_PER_SERVER);
-
-  if (live_servers == 0)
-    return MEMCACHED_SUCCESS;
-
-  if (live_servers > ptr->continuum_count)
-  {
-    memcached_continuum_item_st *new_ptr;
-
-    new_ptr= ptr->call_realloc(ptr, ptr->continuum,
-                               sizeof(memcached_continuum_item_st) * (live_servers + MEMCACHED_CONTINUUM_ADDITION) * points_per_server);
-
-    if (new_ptr == 0)
-      return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-
-    ptr->continuum= new_ptr;
-    ptr->continuum_count= live_servers + MEMCACHED_CONTINUUM_ADDITION;
-  }
-
-  if (is_ketama_weighted)
-  {
-    for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index)
-    {
-      if (list[host_index].weight == 0)
-      {
-        list[host_index].weight = 1;
-      }
-      if (!is_auto_ejecting || list[host_index].next_retry <= now.tv_sec)
-        total_weight += list[host_index].weight;
-    }
-  }
-
-  for (host_index = 0; host_index < ptr->number_of_hosts; ++host_index)
-  {
-    if (is_auto_ejecting && list[host_index].next_retry > now.tv_sec)
-      continue;
-
-    if (is_ketama_weighted)
-    {
-        float pct = (float)list[host_index].weight / (float)total_weight;
-        pointer_per_server= (uint32_t) ((floorf((float) (pct * MEMCACHED_POINTS_PER_SERVER_KETAMA / 4 * (float)live_servers + 0.0000000001))) * 4);
-        pointer_per_hash= 4;
-#ifdef DEBUG
-        printf("ketama_weighted:%s|%d|%llu|%u\n",
-               list[host_index].hostname,
-               list[host_index].port,
-               (unsigned long long)list[host_index].weight,
-               pointer_per_server);
-#endif
-    }
-
-
-    if (ptr->distribution == MEMCACHED_DISTRIBUTION_CONSISTENT_KETAMA_SPY)
-    {
-      for (pointer_index= 0;
-           pointer_index < pointer_per_server / pointer_per_hash;
-           pointer_index++)
-      {
-        char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= "";
-        size_t sort_host_length;
-
-        // Spymemcached ketema key format is: hostname/ip:port-index
-        // If hostname is not available then: /ip:port-index
-        sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
-                                            "/%s:%d-%d",
-                                            list[host_index].hostname,
-                                            list[host_index].port,
-                                            pointer_index);
-#ifdef DEBUG
-        printf("update_continuum: key is %s\n", sort_host);
-#endif
-
-        WATCHPOINT_ASSERT(sort_host_length);
-
-        if (is_ketama_weighted)
-        {
-          unsigned int i;
-          for (i = 0; i < pointer_per_hash; i++)
-          {
-             value= ketama_server_hash(sort_host, (uint32_t) sort_host_length, (int) i);
-             ptr->continuum[continuum_index].index= host_index;
-             ptr->continuum[continuum_index++].value= value;
-          }
-        }
-        else
-        {
-          value= memcached_generate_hash_value(sort_host, sort_host_length, ptr->hash_continuum);
-          ptr->continuum[continuum_index].index= host_index;
-          ptr->continuum[continuum_index++].value= value;
-        }
-      }
-    }
-    else
-    {
-      for (pointer_index= 1;
-           pointer_index <= pointer_per_server / pointer_per_hash;
-           pointer_index++)
-      {
-        char sort_host[MEMCACHED_MAX_HOST_SORT_LENGTH]= "";
-        size_t sort_host_length;
-
-        if (list[host_index].port == MEMCACHED_DEFAULT_PORT)
-        {
-          sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
-                                              "%s-%d",
-                                              list[host_index].hostname,
-                                              pointer_index - 1);
-        }
-        else
-        {
-          sort_host_length= (size_t) snprintf(sort_host, MEMCACHED_MAX_HOST_SORT_LENGTH,
-                                              "%s:%d-%d",
-                                              list[host_index].hostname,
-                                              list[host_index].port, pointer_index - 1);
-        }
-
-        WATCHPOINT_ASSERT(sort_host_length);
-
-        if (is_ketama_weighted)
-        {
-          unsigned int i;
-          for (i = 0; i < pointer_per_hash; i++)
-          {
-             value= ketama_server_hash(sort_host, (uint32_t) sort_host_length, (int) i);
-             ptr->continuum[continuum_index].index= host_index;
-             ptr->continuum[continuum_index++].value= value;
-          }
-        }
-        else
-        {
-          value= memcached_generate_hash_value(sort_host, sort_host_length, ptr->hash_continuum);
-          ptr->continuum[continuum_index].index= host_index;
-          ptr->continuum[continuum_index++].value= value;
-        }
-      }
-    }
-
-    pointer_counter+= pointer_per_server;
-  }
-
-  WATCHPOINT_ASSERT(ptr);
-  WATCHPOINT_ASSERT(ptr->continuum);
-  WATCHPOINT_ASSERT(ptr->number_of_hosts * MEMCACHED_POINTS_PER_SERVER <= MEMCACHED_CONTINUUM_SIZE);
-  ptr->continuum_points_counter= pointer_counter;
-  qsort(ptr->continuum, ptr->continuum_points_counter, sizeof(memcached_continuum_item_st), continuum_item_cmp);
-
-#ifdef DEBUG
-  for (pointer_index= 0; ptr->number_of_hosts && pointer_index < ((live_servers * MEMCACHED_POINTS_PER_SERVER) - 1); pointer_index++)
-  {
-    WATCHPOINT_ASSERT(ptr->continuum[pointer_index].value <= ptr->continuum[pointer_index + 1].value);
-  }
-#endif
-
-  return MEMCACHED_SUCCESS;
-}
-
-
-memcached_return_t memcached_server_push(memcached_st *ptr, memcached_server_st *list)
-{
-  unsigned int x;
-  uint16_t count;
-  memcached_server_st *new_host_list;
-
-  if (!list)
-    return MEMCACHED_SUCCESS;
-
-  count= list[0].count;
-  new_host_list= ptr->call_realloc(ptr, ptr->hosts,
-                                   sizeof(memcached_server_st) * (count + ptr->number_of_hosts));
-
-  if (!new_host_list)
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-
-  ptr->hosts= new_host_list;
-
-  for (x= 0; x < count; x++)
-  {
-    if ((ptr->flags.use_udp && list[x].type != MEMCACHED_CONNECTION_UDP)
-            || ((list[x].type == MEMCACHED_CONNECTION_UDP)
-            && ! (ptr->flags.use_udp)) )
-      return MEMCACHED_INVALID_HOST_PROTOCOL;
-
-    WATCHPOINT_ASSERT(list[x].hostname[0] != 0);
-    memcached_server_create(ptr, &ptr->hosts[ptr->number_of_hosts]);
-    /* TODO check return type */
-    (void)memcached_server_create_with(ptr, &ptr->hosts[ptr->number_of_hosts], list[x].hostname,
-                                       list[x].port, list[x].weight, list[x].type);
-    ptr->number_of_hosts++;
-  }
-  ptr->hosts[0].count= (uint16_t) ptr->number_of_hosts;
-
-  return run_distribution(ptr);
-}
-
-memcached_return_t memcached_server_add_unix_socket(memcached_st *ptr,
-                                                    const char *filename)
-{
-  return memcached_server_add_unix_socket_with_weight(ptr, filename, 0);
-}
-
-memcached_return_t memcached_server_add_unix_socket_with_weight(memcached_st *ptr,
-                                                                const char *filename,
-                                                                uint32_t weight)
-{
-  if (!filename)
-    return MEMCACHED_FAILURE;
-
-  return server_add(ptr, filename, 0, weight, MEMCACHED_CONNECTION_UNIX_SOCKET);
-}
-
-memcached_return_t memcached_server_add_udp(memcached_st *ptr,
-                                            const char *hostname,
-                                            in_port_t port)
-{
-  return memcached_server_add_udp_with_weight(ptr, hostname, port, 0);
-}
-
-memcached_return_t memcached_server_add_udp_with_weight(memcached_st *ptr,
-                                                        const char *hostname,
-                                                        in_port_t port,
-                                                        uint32_t weight)
-{
-  if (!port)
-    port= MEMCACHED_DEFAULT_PORT;
-
-  if (!hostname)
-    hostname= "localhost";
-
-  return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_UDP);
-}
-
-memcached_return_t memcached_server_add(memcached_st *ptr,
-                                        const char *hostname,
-                                        in_port_t port)
-{
-  return memcached_server_add_with_weight(ptr, hostname, port, 0);
-}
-
-memcached_return_t memcached_server_add_with_weight(memcached_st *ptr,
-                                                    const char *hostname,
-                                                    in_port_t port,
-                                                    uint32_t weight)
-{
-  if (!port)
-    port= MEMCACHED_DEFAULT_PORT;
-
-  if (!hostname)
-    hostname= "localhost";
-
-  return server_add(ptr, hostname, port, weight, MEMCACHED_CONNECTION_TCP);
-}
-
-static memcached_return_t server_add(memcached_st *ptr, const char *hostname,
-                                     in_port_t port,
-                                     uint32_t weight,
-                                     memcached_connection_t type)
-{
-  memcached_server_st *new_host_list;
-
-  if ( (ptr->flags.use_udp && type != MEMCACHED_CONNECTION_UDP)
-      || ( (type == MEMCACHED_CONNECTION_UDP) && (! ptr->flags.use_udp) ) )
-    return MEMCACHED_INVALID_HOST_PROTOCOL;
-
-  new_host_list= ptr->call_realloc(ptr, ptr->hosts,
-                                   sizeof(memcached_server_st) * (ptr->number_of_hosts+1));
-
-  if (new_host_list == NULL)
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-
-  ptr->hosts= new_host_list;
-
-  /* TODO: Check return type */
-  (void)memcached_server_create_with(ptr, &ptr->hosts[ptr->number_of_hosts], hostname, port, weight, type);
-  ptr->number_of_hosts++;
-  ptr->hosts[0].count= (uint16_t) ptr->number_of_hosts;
-
-  return run_distribution(ptr);
-}
-
-memcached_return_t memcached_server_remove(memcached_server_st *st_ptr)
-{
-  uint32_t x, host_index;
-  memcached_st *ptr= st_ptr->root;
-  memcached_server_st *list= ptr->hosts;
-
-  for (x= 0, host_index= 0; x < ptr->number_of_hosts; x++)
-  {
-    if (strncmp(list[x].hostname, st_ptr->hostname, MEMCACHED_MAX_HOST_LENGTH) != 0 || list[x].port != st_ptr->port)
-    {
-      if (host_index != x)
-        memcpy(list+host_index, list+x, sizeof(memcached_server_st));
-      host_index++;
-    }
-  }
-  ptr->number_of_hosts= host_index;
-
-  if (st_ptr->address_info)
-  {
-    freeaddrinfo(st_ptr->address_info);
-    st_ptr->address_info= NULL;
-  }
-  run_distribution(ptr);
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_server_st *memcached_server_list_append(memcached_server_st *ptr,
-                                                  const char *hostname, in_port_t port,
-                                                  memcached_return_t *error)
-{
-  return memcached_server_list_append_with_weight(ptr, hostname, port, 0, error);
-}
-
-memcached_server_st *memcached_server_list_append_with_weight(memcached_server_st *ptr,
-                                                              const char *hostname, in_port_t port,
-                                                              uint32_t weight,
-                                                              memcached_return_t *error)
-{
-  unsigned int count;
-  memcached_server_st *new_host_list;
-
-  if (hostname == NULL || error == NULL)
-    return NULL;
-
-  if (!port)
-    port= MEMCACHED_DEFAULT_PORT;
-
-  /* Increment count for hosts */
-  count= 1;
-  if (ptr != NULL)
-  {
-    count+= ptr[0].count;
-  }
-
-  new_host_list= (memcached_server_st *)realloc(ptr, sizeof(memcached_server_st) * count);
-  if (!new_host_list)
-  {
-    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-    return NULL;
-  }
-
-  /* TODO: Check return type */
-  memcached_server_create_with(NULL, &new_host_list[count-1], hostname, port, weight, MEMCACHED_CONNECTION_TCP);
-
-  /* Backwards compatibility hack */
-  new_host_list[0].count= (uint16_t) count;
-
-  *error= MEMCACHED_SUCCESS;
-  return new_host_list;
-}
-
-unsigned int memcached_server_list_count(memcached_server_st *ptr)
-{
-  if (ptr == NULL)
-    return 0;
-
-  return ptr[0].count;
-}
-
-void memcached_server_list_free(memcached_server_st *ptr)
-{
-  server_list_free(NULL, ptr);
-}
diff --git a/libmemcached/memcached_internal.h b/libmemcached/memcached_internal.h
deleted file mode 100644 (file)
index 3e4415d..0000000
+++ /dev/null
@@ -1,35 +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: Internal functions used by the library. Not for public use!
- *
- */
-
-#ifndef LIBMEMCACHED_MEMCACHED_INTERNAL_H
-#define LIBMEMCACHED_MEMCACHED_INTERNAL_H
-
-#if defined(BUILDING_LIBMEMCACHED)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-LIBMEMCACHED_LOCAL
-void libmemcached_free(memcached_st *ptr, void *mem);
-LIBMEMCACHED_LOCAL
-void *libmemcached_malloc(memcached_st *ptr, const size_t size);
-LIBMEMCACHED_LOCAL
-void *libmemcached_realloc(memcached_st *ptr, void *mem, const size_t size);
-LIBMEMCACHED_LOCAL
-void *libmemcached_calloc(memcached_st *ptr, size_t nelem, size_t size);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* BUILDING_LIBMEMCACHED */
-#endif /* LIBMEMCACHED_MEMCACHED_INTERNAL_H */
diff --git a/libmemcached/memcached_io.c b/libmemcached/memcached_io.c
deleted file mode 100644 (file)
index fd86437..0000000
+++ /dev/null
@@ -1,644 +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: Server IO, Not public!
- *
- */
-
-
-#include "common.h"
-#include "memcached_io.h"
-#include <sys/select.h>
-#include <poll.h>
-
-typedef enum {
-  MEM_READ,
-  MEM_WRITE
-} memc_read_or_write;
-
-static ssize_t io_flush(memcached_server_st *ptr, memcached_return_t *error);
-static void increment_udp_message_id(memcached_server_st *ptr);
-
-static memcached_return_t io_wait(memcached_server_st *ptr,
-                                  memc_read_or_write read_or_write)
-{
-  struct pollfd fds= {
-    .fd= ptr->fd,
-    .events = POLLIN
-  };
-  int error;
-
-  unlikely (read_or_write == MEM_WRITE) /* write */
-    fds.events= POLLOUT;
-
-  /*
-   ** We are going to block on write, but at least on Solaris we might block
-   ** on write if we haven't read anything from our input buffer..
-   ** Try to purge the input buffer if we don't do any flow control in the
-   ** application layer (just sending a lot of data etc)
-   ** The test is moved down in the purge function to avoid duplication of
-   ** the test.
- */
-  if (read_or_write == MEM_WRITE)
-  {
-    memcached_return_t rc= memcached_purge(ptr);
-    if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_STORED)
-      return MEMCACHED_FAILURE;
-  }
-
-  int timeout= ptr->root->poll_timeout;
-  if (ptr->root->flags.no_block == false)
-    timeout= -1;
-
-  error= poll(&fds, 1, timeout);
-
-  if (error == 1)
-    return MEMCACHED_SUCCESS;
-  else if (error == 0)
-    return MEMCACHED_TIMEOUT;
-
-  /* Imposssible for anything other then -1 */
-  WATCHPOINT_ASSERT(error == -1);
-  memcached_quit_server(ptr, 1);
-
-  return MEMCACHED_FAILURE;
-}
-
-/**
- * Try to fill the input buffer for a server with as much
- * data as possible.
- *
- * @param ptr the server to pack
- */
-static bool repack_input_buffer(memcached_server_st *ptr)
-{
-  if (ptr->read_ptr != ptr->read_buffer)
-  {
-    /* Move all of the data to the beginning of the buffer so
-     ** that we can fit more data into the buffer...
-   */
-    memmove(ptr->read_buffer, ptr->read_ptr, ptr->read_buffer_length);
-    ptr->read_ptr= ptr->read_buffer;
-    ptr->read_data_length= ptr->read_buffer_length;
-  }
-
-  /* There is room in the buffer, try to fill it! */
-  if (ptr->read_buffer_length != MEMCACHED_MAX_BUFFER)
-  {
-    /* Just try a single read to grab what's available */
-    ssize_t nr= read(ptr->fd,
-                     ptr->read_ptr + ptr->read_data_length,
-                     MEMCACHED_MAX_BUFFER - ptr->read_data_length);
-
-    if (nr > 0)
-    {
-      ptr->read_data_length+= (size_t)nr;
-      ptr->read_buffer_length+= (size_t)nr;
-      return true;
-    }
-  }
-  return false;
-}
-
-/**
- * If the we have callbacks connected to this server structure
- * we may start process the input queue and fire the callbacks
- * for the incomming messages. This function is _only_ called
- * when the input buffer is full, so that we _know_ that we have
- * at least _one_ message to process.
- *
- * @param ptr the server to star processing iput messages for
- * @return true if we processed anything, false otherwise
- */
-static bool process_input_buffer(memcached_server_st *ptr)
-{
-  /*
-   ** We might be able to process some of the response messages if we
-   ** have a callback set up
- */
-  if (ptr->root->callbacks != NULL && ptr->root->flags.use_udp == false)
-  {
-    /*
-     * We might have responses... try to read them out and fire
-     * callbacks
-   */
-    memcached_callback_st cb= *ptr->root->callbacks;
-
-    char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-    memcached_return_t error;
-    error= memcached_response(ptr, buffer, sizeof(buffer),
-                              &ptr->root->result);
-    if (error == MEMCACHED_SUCCESS)
-    {
-      for (unsigned int x= 0; x < cb.number_of_callback; x++)
-      {
-        error= (*cb.callback[x])(ptr->root, &ptr->root->result, cb.context);
-        if (error != MEMCACHED_SUCCESS)
-          break;
-      }
-
-      /* @todo what should I do with the error message??? */
-    }
-    /* @todo what should I do with other error messages?? */
-    return true;
-  }
-
-  return false;
-}
-
-#ifdef UNUSED
-void memcached_io_preread(memcached_st *ptr)
-{
-  unsigned int x;
-
-  return;
-
-  for (x= 0; x < ptr->number_of_hosts; x++)
-  {
-    if (memcached_server_response_count(ptr, x) &&
-        ptr->hosts[x].read_data_length < MEMCACHED_MAX_BUFFER )
-    {
-      size_t data_read;
-
-      data_read= read(ptr->hosts[x].fd,
-                      ptr->hosts[x].read_ptr + ptr->hosts[x].read_data_length,
-                      MEMCACHED_MAX_BUFFER - ptr->hosts[x].read_data_length);
-      if (data_read == -1)
-        continue;
-
-      ptr->hosts[x].read_buffer_length+= data_read;
-      ptr->hosts[x].read_data_length+= data_read;
-    }
-  }
-}
-#endif
-
-memcached_return_t memcached_io_read(memcached_server_st *ptr,
-                                     void *buffer, size_t length, ssize_t *nread)
-{
-  char *buffer_ptr;
-
-  buffer_ptr= buffer;
-
-  while (length)
-  {
-    if (!ptr->read_buffer_length)
-    {
-      ssize_t data_read;
-
-      while (1)
-      {
-        data_read= read(ptr->fd, ptr->read_buffer, MEMCACHED_MAX_BUFFER);
-        if (data_read > 0)
-          break;
-        else if (data_read == -1)
-        {
-          ptr->cached_errno= errno;
-          memcached_return_t rc= MEMCACHED_UNKNOWN_READ_FAILURE;
-          switch (errno)
-          {
-          case EAGAIN:
-          case EINTR:
-            if ((rc= io_wait(ptr, MEM_READ)) == MEMCACHED_SUCCESS)
-              continue;
-            /* fall through */
-
-          default:
-            {
-              memcached_quit_server(ptr, 1);
-              *nread= -1;
-              return rc;
-            }
-          }
-        }
-        else
-        {
-          /*
-            EOF. Any data received so far is incomplete
-            so discard it. This always reads by byte in case of TCP
-            and protocol enforcement happens at memcached_response()
-            looking for '\n'. We do not care for UDB which requests 8 bytes
-            at once. Generally, this means that connection went away. Since
-            for blocking I/O we do not return 0 and for non-blocking case
-            it will return EGAIN if data is not immediatly available.
-          */
-          memcached_quit_server(ptr, 1);
-          *nread= -1;
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-        }
-      }
-
-      ptr->io_bytes_sent = 0;
-      ptr->read_data_length= (size_t) data_read;
-      ptr->read_buffer_length= (size_t) data_read;
-      ptr->read_ptr= ptr->read_buffer;
-    }
-
-    if (length > 1)
-    {
-      size_t difference;
-
-      difference= (length > ptr->read_buffer_length) ? ptr->read_buffer_length : length;
-
-      memcpy(buffer_ptr, ptr->read_ptr, difference);
-      length -= difference;
-      ptr->read_ptr+= difference;
-      ptr->read_buffer_length-= difference;
-      buffer_ptr+= difference;
-    }
-    else
-    {
-      *buffer_ptr= *ptr->read_ptr;
-      ptr->read_ptr++;
-      ptr->read_buffer_length--;
-      buffer_ptr++;
-      break;
-    }
-  }
-
-  ptr->server_failure_counter= 0;
-  *nread = (ssize_t)(buffer_ptr - (char*)buffer);
-  return MEMCACHED_SUCCESS;
-}
-
-ssize_t memcached_io_write(memcached_server_st *ptr,
-                           const void *buffer, size_t length, char with_flush)
-{
-  size_t original_length;
-  const char* buffer_ptr;
-
-  WATCHPOINT_ASSERT(ptr->fd != -1);
-
-  original_length= length;
-  buffer_ptr= buffer;
-
-  while (length)
-  {
-    char *write_ptr;
-    size_t should_write;
-    size_t buffer_end;
-
-    if (ptr->type == MEMCACHED_CONNECTION_UDP)
-    {
-      //UDP does not support partial writes
-      buffer_end= MAX_UDP_DATAGRAM_LENGTH;
-      should_write= length;
-      if (ptr->write_buffer_offset + should_write > buffer_end)
-        return -1;
-    }
-    else
-    {
-      buffer_end= MEMCACHED_MAX_BUFFER;
-      should_write= buffer_end - ptr->write_buffer_offset;
-      should_write= (should_write < length) ? should_write : length;
-    }
-
-    write_ptr= ptr->write_buffer + ptr->write_buffer_offset;
-    memcpy(write_ptr, buffer_ptr, should_write);
-    ptr->write_buffer_offset+= should_write;
-    buffer_ptr+= should_write;
-    length-= should_write;
-
-    if (ptr->write_buffer_offset == buffer_end && ptr->type != MEMCACHED_CONNECTION_UDP)
-    {
-      memcached_return_t rc;
-      ssize_t sent_length;
-
-      WATCHPOINT_ASSERT(ptr->fd != -1);
-      sent_length= io_flush(ptr, &rc);
-      if (sent_length == -1)
-        return -1;
-
-      /* If io_flush calls memcached_purge, sent_length may be 0 */
-      unlikely (sent_length != 0)
-      {
-        WATCHPOINT_ASSERT(sent_length == (ssize_t)buffer_end);
-      }
-    }
-  }
-
-  if (with_flush)
-  {
-    memcached_return_t rc;
-    WATCHPOINT_ASSERT(ptr->fd != -1);
-    if (io_flush(ptr, &rc) == -1)
-      return -1;
-  }
-
-  return (ssize_t) original_length;
-}
-
-memcached_return_t memcached_io_close(memcached_server_st *ptr)
-{
-  int r;
-
-  if (ptr->fd == -1)
-    return MEMCACHED_SUCCESS;
-
-  /* in case of death shutdown to avoid blocking at close() */
-  if (1)
-  {
-    r= shutdown(ptr->fd, SHUT_RDWR);
-
-#ifdef DEBUG
-    if (r && errno != ENOTCONN)
-    {
-      WATCHPOINT_NUMBER(ptr->fd);
-      WATCHPOINT_ERRNO(errno);
-      WATCHPOINT_ASSERT(errno);
-    }
-#endif
-  }
-
-  r= close(ptr->fd);
-#ifdef DEBUG
-  if (r != 0)
-    WATCHPOINT_ERRNO(errno);
-#endif
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_server_st *memcached_io_get_readable_server(memcached_st *memc)
-{
-#define MAX_SERVERS_TO_POLL 100
-  struct pollfd fds[MAX_SERVERS_TO_POLL];
-  unsigned int host_index= 0;
-
-  for (unsigned int x= 0;
-       x< memc->number_of_hosts && host_index < MAX_SERVERS_TO_POLL;
-       ++x)
-  {
-    if (memc->hosts[x].read_buffer_length > 0) /* I have data in the buffer */
-      return &memc->hosts[x];
-
-    if (memcached_server_response_count(&memc->hosts[x]) > 0)
-    {
-      fds[host_index].events = POLLIN;
-      fds[host_index].revents = 0;
-      fds[host_index].fd = memc->hosts[x].fd;
-      ++host_index;
-    }
-  }
-
-  if (host_index < 2)
-  {
-    /* We have 0 or 1 server with pending events.. */
-    for (unsigned int x= 0; x< memc->number_of_hosts; ++x)
-      if (memcached_server_response_count(&memc->hosts[x]) > 0)
-        return &memc->hosts[x];
-
-    return NULL;
-  }
-
-  int err= poll(fds, host_index, memc->poll_timeout);
-  switch (err) {
-  case -1:
-    memc->cached_errno = errno;
-    /* FALLTHROUGH */
-  case 0:
-    break;
-  default:
-    for (unsigned int x= 0; x < host_index; ++x)
-      if (fds[x].revents & POLLIN)
-        for (unsigned int y= 0; y < memc->number_of_hosts; ++y)
-          if (memc->hosts[y].fd == fds[x].fd)
-            return &memc->hosts[y];
-  }
-
-  return NULL;
-}
-
-static ssize_t io_flush(memcached_server_st *ptr,
-                        memcached_return_t *error)
-{
-  /*
-   ** We might want to purge the input buffer if we haven't consumed
-   ** any output yet... The test for the limits is the purge is inline
-   ** in the purge function to avoid duplicating the logic..
- */
-  {
-    memcached_return_t rc;
-    WATCHPOINT_ASSERT(ptr->fd != -1);
-    rc= memcached_purge(ptr);
-
-    if (rc != MEMCACHED_SUCCESS && rc != MEMCACHED_STORED)
-      return -1;
-  }
-  ssize_t sent_length;
-  size_t return_length;
-  char *local_write_ptr= ptr->write_buffer;
-  size_t write_length= ptr->write_buffer_offset;
-
-  *error= MEMCACHED_SUCCESS;
-
-  WATCHPOINT_ASSERT(ptr->fd != -1);
-
-  // UDP Sanity check, make sure that we are not sending somthing too big
-  if (ptr->type == MEMCACHED_CONNECTION_UDP && write_length > MAX_UDP_DATAGRAM_LENGTH)
-    return -1;
-
-  if (ptr->write_buffer_offset == 0 || (ptr->type == MEMCACHED_CONNECTION_UDP
-                                        && ptr->write_buffer_offset == UDP_DATAGRAM_HEADER_LENGTH))
-    return 0;
-
-  /* Looking for memory overflows */
-#if defined(DEBUG)
-  if (write_length == MEMCACHED_MAX_BUFFER)
-    WATCHPOINT_ASSERT(ptr->write_buffer == local_write_ptr);
-  WATCHPOINT_ASSERT((ptr->write_buffer + MEMCACHED_MAX_BUFFER) >= (local_write_ptr + write_length));
-#endif
-
-  return_length= 0;
-  while (write_length)
-  {
-    WATCHPOINT_ASSERT(ptr->fd != -1);
-    WATCHPOINT_ASSERT(write_length > 0);
-    sent_length= 0;
-    if (ptr->type == MEMCACHED_CONNECTION_UDP)
-      increment_udp_message_id(ptr);
-    sent_length= write(ptr->fd, local_write_ptr, write_length);
-
-    if (sent_length == -1)
-    {
-      ptr->cached_errno= errno;
-      switch (errno)
-      {
-      case ENOBUFS:
-        continue;
-      case EAGAIN:
-        {
-          /*
-           * We may be blocked on write because the input buffer
-           * is full. Let's check if we have room in our input
-           * buffer for more data and retry the write before
-           * waiting..
-         */
-          if (repack_input_buffer(ptr) ||
-              process_input_buffer(ptr))
-            continue;
-
-          memcached_return_t rc;
-          rc= io_wait(ptr, MEM_WRITE);
-
-          if (rc == MEMCACHED_SUCCESS || rc == MEMCACHED_TIMEOUT)
-            continue;
-
-          memcached_quit_server(ptr, 1);
-          return -1;
-        }
-      default:
-        memcached_quit_server(ptr, 1);
-        *error= MEMCACHED_ERRNO;
-        return -1;
-      }
-    }
-
-    if (ptr->type == MEMCACHED_CONNECTION_UDP &&
-        (size_t)sent_length != write_length)
-    {
-      memcached_quit_server(ptr, 1);
-      return -1;
-    }
-
-    ptr->io_bytes_sent += (uint32_t) sent_length;
-
-    local_write_ptr+= sent_length;
-    write_length-= (uint32_t) sent_length;
-    return_length+= (uint32_t) sent_length;
-  }
-
-  WATCHPOINT_ASSERT(write_length == 0);
-  // Need to study this assert() WATCHPOINT_ASSERT(return_length ==
-  // ptr->write_buffer_offset);
-
-  // if we are a udp server, the begining of the buffer is reserverd for
-  // the upd frame header
-  if (ptr->type == MEMCACHED_CONNECTION_UDP)
-    ptr->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
-  else
-    ptr->write_buffer_offset= 0;
-
-  return (ssize_t) return_length;
-}
-
-/*
-  Eventually we will just kill off the server with the problem.
-*/
-void memcached_io_reset(memcached_server_st *ptr)
-{
-  memcached_quit_server(ptr, 1);
-}
-
-/**
- * Read a given number of bytes from the server and place it into a specific
- * buffer. Reset the IO channel on this server if an error occurs.
- */
-memcached_return_t memcached_safe_read(memcached_server_st *ptr,
-                                       void *dta,
-                                       size_t size)
-{
-  size_t offset= 0;
-  char *data= dta;
-
-  while (offset < size)
-  {
-    ssize_t nread;
-    memcached_return_t rc= memcached_io_read(ptr, data + offset, size - offset,
-                                             &nread);
-    if (rc != MEMCACHED_SUCCESS)
-      return rc;
-
-    offset+= (size_t) nread;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_io_readline(memcached_server_st *ptr,
-                                         char *buffer_ptr,
-                                         size_t size)
-{
-  bool line_complete= false;
-  size_t total_nr= 0;
-
-  while (!line_complete)
-  {
-    if (ptr->read_buffer_length == 0)
-    {
-      /*
-       * We don't have any data in the buffer, so let's fill the read
-       * buffer. Call the standard read function to avoid duplicating
-       * the logic.
-     */
-      ssize_t nread;
-      memcached_return_t rc= memcached_io_read(ptr, buffer_ptr, 1, &nread);
-      if (rc != MEMCACHED_SUCCESS)
-        return rc;
-
-      if (*buffer_ptr == '\n')
-        line_complete= true;
-
-      ++buffer_ptr;
-      ++total_nr;
-    }
-
-    /* Now let's look in the buffer and copy as we go! */
-    while (ptr->read_buffer_length && total_nr < size && !line_complete)
-    {
-      *buffer_ptr = *ptr->read_ptr;
-      if (*buffer_ptr == '\n')
-        line_complete = true;
-      --ptr->read_buffer_length;
-      ++ptr->read_ptr;
-      ++total_nr;
-      ++buffer_ptr;
-    }
-
-    if (total_nr == size)
-      return MEMCACHED_PROTOCOL_ERROR;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-/*
- * The udp request id consists of two seperate sections
- *   1) The thread id
- *   2) The message number
- * The thread id should only be set when the memcached_st struct is created
- * and should not be changed.
- *
- * The message num is incremented for each new message we send, this function
- * extracts the message number from message_id, increments it and then
- * writes the new value back into the header
- */
-static void increment_udp_message_id(memcached_server_st *ptr)
-{
-  struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
-  uint16_t cur_req= get_udp_datagram_request_id(header);
-  int msg_num= get_msg_num_from_request_id(cur_req);
-  int thread_id= get_thread_id_from_request_id(cur_req);
-
-  if (((++msg_num) & UDP_REQUEST_ID_THREAD_MASK) != 0)
-    msg_num= 0;
-
-  header->request_id= htons((uint16_t) (thread_id | msg_num));
-}
-
-memcached_return_t memcached_io_init_udp_header(memcached_server_st *ptr, uint16_t thread_id)
-{
-  if (thread_id > UDP_REQUEST_ID_MAX_THREAD_ID)
-    return MEMCACHED_FAILURE;
-
-  struct udp_datagram_header_st *header= (struct udp_datagram_header_st *)ptr->write_buffer;
-  header->request_id= htons((uint16_t) (generate_udp_request_thread_id(thread_id)));
-  header->num_datagrams= htons(1);
-  header->sequence_number= htons(0);
-
-  return MEMCACHED_SUCCESS;
-}
diff --git a/libmemcached/memcached_io.h b/libmemcached/memcached_io.h
deleted file mode 100644 (file)
index 03d63b5..0000000
+++ /dev/null
@@ -1,71 +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: Server IO, Not public!
- *
- */
-
-#ifndef LIBMEMCACHED_MEMCACHED_IO_H
-#define LIBMEMCACHED_MEMCACHED_IO_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(BUILDING_LIBMEMCACHED)
-
-#include "libmemcached/memcached.h"
-
-#define MAX_UDP_DATAGRAM_LENGTH 1400
-#define UDP_DATAGRAM_HEADER_LENGTH 8
-#define UDP_REQUEST_ID_MSG_SIG_DIGITS 10
-#define UDP_REQUEST_ID_THREAD_MASK 0xFFFF << UDP_REQUEST_ID_MSG_SIG_DIGITS
-#define get_udp_datagram_request_id(A) ntohs((A)->request_id)
-#define get_udp_datagram_seq_num(A) ntohs((A)->sequence_number)
-#define get_udp_datagram_num_datagrams(A) ntohs((A)->num_datagrams)
-#define get_msg_num_from_request_id(A) ( (A) & (~(UDP_REQUEST_ID_THREAD_MASK)) )
-#define get_thread_id_from_request_id(A) ( (A) & (UDP_REQUEST_ID_THREAD_MASK) ) >> UDP_REQUEST_ID_MSG_SIG_DIGITS
-#define generate_udp_request_thread_id(A) (A) << UDP_REQUEST_ID_MSG_SIG_DIGITS
-#define UDP_REQUEST_ID_MAX_THREAD_ID get_thread_id_from_request_id(0xFFFF)
-
-struct udp_datagram_header_st {
-  uint16_t request_id;
-  uint16_t sequence_number;
-  uint16_t num_datagrams;
-  uint16_t reserved;
-};
-
-ssize_t memcached_io_write(memcached_server_st *ptr,
-                           const void *buffer, size_t length, char with_flush);
-void memcached_io_reset(memcached_server_st *ptr);
-memcached_return_t memcached_io_read(memcached_server_st *ptr,
-                                     void *buffer, size_t length, ssize_t *nread);
-/* Read a line (terminated by '\n') into the buffer */
-memcached_return_t memcached_io_readline(memcached_server_st *ptr,
-                                         char *buffer_ptr,
-                                         size_t size);
-memcached_return_t memcached_io_close(memcached_server_st *ptr);
-/* Read n bytes of data from the server and store them in dta */
-memcached_return_t memcached_safe_read(memcached_server_st *ptr, 
-                                       void *dta, 
-                                       size_t size);
-/* Read a single response from the server */
-memcached_return_t memcached_read_one_response(memcached_server_st *ptr,
-                                               char *buffer, size_t buffer_length,
-                                               memcached_result_st *result);
-memcached_return_t memcached_io_init_udp_header(memcached_server_st *ptr,
-                                                uint16_t thread_id);
-
-memcached_server_st *memcached_io_get_readable_server(memcached_st *memc);
-
-#endif /* BUILDING_LIBMEMCACHED */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LIBMEMCACHED_MEMCACHED_IO_H */
diff --git a/libmemcached/memcached_key.c b/libmemcached/memcached_key.c
deleted file mode 100644 (file)
index 3b16b27..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#include "common.h"
-
-memcached_return_t memcached_key_test(const char * const *keys, 
-                                      const size_t *key_length, 
-                                      size_t number_of_keys)
-{
-  uint32_t x;
-  memcached_return_t rc;
-
-  for (x= 0; x < number_of_keys; x++)
-  {
-    size_t y;
-
-    rc= memcached_validate_key_length(*(key_length + x), false);
-    if (rc != MEMCACHED_SUCCESS)
-      return rc;
-    
-    for (y= 0; y < *(key_length + x); y++)
-    {
-      if ((isgraph(keys[x][y])) == 0)
-        return MEMCACHED_BAD_KEY_PROVIDED;
-    }
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
diff --git a/libmemcached/memcached_parse.c b/libmemcached/memcached_parse.c
deleted file mode 100644 (file)
index 73cc9df..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/* 
-  I debated about putting this in the client library since it does an 
-  action I don't really believe belongs in the library.
-
-  Frankly its too damn useful not to be here though.
-*/
-
-#include "common.h"
-
-memcached_server_st *memcached_servers_parse(const char *server_strings)
-{
-  char *string;
-  uint32_t port;
-  uint32_t weight;
-  const char *begin_ptr;
-  const char *end_ptr;
-  memcached_server_st *servers= NULL;
-  memcached_return_t rc;
-
-  WATCHPOINT_ASSERT(server_strings);
-
-  end_ptr= server_strings + strlen(server_strings);
-
-  for (begin_ptr= server_strings, string= index(server_strings, ','); 
-       begin_ptr != end_ptr; 
-       string= index(begin_ptr, ','))
-  {
-    char buffer[HUGE_STRING_LEN];
-    char *ptr, *ptr2;
-    port= 0;
-    weight= 0;
-
-    if (string)
-    {
-      memcpy(buffer, begin_ptr, (size_t) (string - begin_ptr));
-      buffer[(unsigned int)(string - begin_ptr)]= 0;
-      begin_ptr= string+1;
-    }
-    else
-    {
-      size_t length= strlen(begin_ptr);
-      memcpy(buffer, begin_ptr, length);
-      buffer[length]= 0;
-      begin_ptr= end_ptr;
-    }
-
-    ptr= index(buffer, ':');
-
-    if (ptr)
-    {
-      ptr[0]= 0;
-
-      ptr++;
-
-      port= (uint32_t) strtoul(ptr, (char **)NULL, 10);
-
-      ptr2= index(ptr, ' ');
-      if (! ptr2)
-        ptr2= index(ptr, ':');
-      if (ptr2)
-      {
-        ptr2++;
-        weight = (uint32_t) strtoul(ptr2, (char **)NULL, 10);
-      }
-    }
-
-    servers= memcached_server_list_append_with_weight(servers, buffer, port, weight, &rc);
-
-    if (isspace(*begin_ptr))
-      begin_ptr++;
-  }
-
-  return servers;
-}
diff --git a/libmemcached/memcached_pool.h b/libmemcached/memcached_pool.h
deleted file mode 100644 (file)
index 84dab3d..0000000
+++ /dev/null
@@ -1,51 +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: Connection pool implementation for libmemcached.
- *
- */
-
-
-#ifndef MEMCACHED_POOL_H
-#define MEMCACHED_POOL_H
-
-#include <libmemcached/memcached.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct memcached_pool_st;
-typedef struct memcached_pool_st memcached_pool_st;
-
-LIBMEMCACHED_API
-memcached_pool_st *memcached_pool_create(memcached_st* mmc, uint32_t initial, 
-                                         uint32_t max);
-LIBMEMCACHED_API
-memcached_st* memcached_pool_destroy(memcached_pool_st* pool);
-LIBMEMCACHED_API
-memcached_st* memcached_pool_pop(memcached_pool_st* pool,
-                                 bool block,
-                                 memcached_return_t* rc);
-LIBMEMCACHED_API
-memcached_return_t memcached_pool_push(memcached_pool_st* pool, 
-                                     memcached_st* mmc);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_pool_behavior_set(memcached_pool_st *ptr,
-                                               memcached_behavior_t flag,
-                                               uint64_t data);
-LIBMEMCACHED_API
-memcached_return_t memcached_pool_behavior_get(memcached_pool_st *ptr,
-                                               memcached_behavior_t flag,
-                                               uint64_t *value);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* MEMCACHED_POOL_H */
diff --git a/libmemcached/memcached_purge.c b/libmemcached/memcached_purge.c
deleted file mode 100644 (file)
index 9042142..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-#include "common.h"
-#include "memcached_io.h"
-#include "memcached_constants.h"
-
-memcached_return_t memcached_purge(memcached_server_st *ptr)
-{
-  uint32_t x;
-  memcached_return_t ret= MEMCACHED_SUCCESS;
-
-  if (ptr->root->options.is_purging || /* already purging */
-      (memcached_server_response_count(ptr) < ptr->root->io_msg_watermark &&
-       ptr->io_bytes_sent < ptr->root->io_bytes_watermark) ||
-      (ptr->io_bytes_sent >= ptr->root->io_bytes_watermark &&
-       memcached_server_response_count(ptr) < 2))
-  {
-    return MEMCACHED_SUCCESS;
-  }
-
-  /* memcached_io_write and memcached_response may call memcached_purge
-    so we need to be able stop any recursion.. */
-  ptr->root->options.is_purging= true;
-
-  WATCHPOINT_ASSERT(ptr->fd != -1);
-  /* Force a flush of the buffer to ensure that we don't have the n-1 pending
-    requests buffered up.. */
-  if (memcached_io_write(ptr, NULL, 0, 1) == -1)
-  {
-    ptr->root->options.is_purging= true;
-    return MEMCACHED_WRITE_FAILURE;
-  }
-  WATCHPOINT_ASSERT(ptr->fd != -1);
-
-  uint32_t no_msg= memcached_server_response_count(ptr) - 1;
-  if (no_msg > 0)
-  {
-    memcached_result_st result;
-    memcached_result_st *result_ptr;
-    char buffer[SMALL_STRING_LEN];
-
-    /*
-     * We need to increase the timeout, because we might be waiting for
-     * data to be sent from the server (the commands was in the output buffer
-     * and just flushed
-   */
-    int32_t timeo= ptr->root->poll_timeout;
-    ptr->root->poll_timeout= 2000;
-
-    result_ptr= memcached_result_create(ptr->root, &result);
-    WATCHPOINT_ASSERT(result_ptr);
-
-    for (x= 0; x < no_msg; x++)
-    {
-      memcached_result_reset(result_ptr);
-      memcached_return_t rc= memcached_read_one_response(ptr, buffer,
-                                                         sizeof (buffer),
-                                                         result_ptr);
-      /*
-       * Purge doesn't care for what kind of command results that is received.
-       * The only kind of errors I care about if is I'm out of sync with the
-       * protocol or have problems reading data from the network..
-     */
-      if (rc== MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_UNKNOWN_READ_FAILURE)
-      {
-        WATCHPOINT_ERROR(rc);
-        ret = rc;
-        memcached_io_reset(ptr);
-      }
-    }
-
-    memcached_result_free(result_ptr);
-    ptr->root->poll_timeout= timeo;
-  }
-  ptr->root->options.is_purging= false;
-
-  return ret;
-}
diff --git a/libmemcached/memcached_quit.c b/libmemcached/memcached_quit.c
deleted file mode 100644 (file)
index 3c117ad..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#include "common.h"
-
-/*
-  This closes all connections (forces flush of input as well).
-
-  Maybe add a host specific, or key specific version?
-
-  The reason we send "quit" is that in case we have buffered IO, this
-  will force data to be completed.
-*/
-
-void memcached_quit_server(memcached_server_st *ptr, uint8_t io_death)
-{
-  if (ptr->fd != -1)
-  {
-    if (io_death == 0 && ptr->type != MEMCACHED_CONNECTION_UDP)
-    {
-      memcached_return_t rc;
-      char buffer[MEMCACHED_MAX_BUFFER];
-
-      if (ptr->root->flags.binary_protocol)
-      {
-        protocol_binary_request_quit request = {.bytes= {0}};
-        request.message.header.request.magic = PROTOCOL_BINARY_REQ;
-        request.message.header.request.opcode = PROTOCOL_BINARY_CMD_QUIT;
-        request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
-        rc= memcached_do(ptr, request.bytes, sizeof(request.bytes), 1);
-      }
-      else
-        rc= memcached_do(ptr, "quit\r\n", 6, 1);
-
-      WATCHPOINT_ASSERT(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_FETCH_NOTFINISHED);
-
-      /* read until socket is closed, or there is an error
-       * closing the socket before all data is read
-       * results in server throwing away all data which is
-       * not read
-       */
-      ssize_t nread;
-      while (memcached_io_read(ptr, buffer, sizeof(buffer)/sizeof(*buffer),
-                               &nread) == MEMCACHED_SUCCESS);
-
-      /*
-       * memcached_io_read may call memcached_quit_server with io_death if
-       * it encounters problems, but we don't care about those occurences.
-       * The intention of that loop is to drain the data sent from the
-       * server to ensure that the server processed all of the data we
-       * sent to the server.
-       */
-      ptr->server_failure_counter= 0;
-    }
-    memcached_io_close(ptr);
-
-    ptr->fd= -1;
-    ptr->write_buffer_offset= (size_t) ((ptr->type == MEMCACHED_CONNECTION_UDP) ? UDP_DATAGRAM_HEADER_LENGTH : 0);
-    ptr->read_buffer_length= 0;
-    ptr->read_ptr= ptr->read_buffer;
-    memcached_server_response_reset(ptr);
-  }
-
-  if(io_death) ptr->server_failure_counter++;
-}
-
-void memcached_quit(memcached_st *ptr)
-{
-  unsigned int x;
-
-  if (ptr->hosts == NULL ||
-      ptr->number_of_hosts == 0)
-    return;
-
-  if (ptr->hosts && ptr->number_of_hosts)
-  {
-    for (x= 0; x < ptr->number_of_hosts; x++)
-      memcached_quit_server(&ptr->hosts[x], 0);
-  }
-}
diff --git a/libmemcached/memcached_response.c b/libmemcached/memcached_response.c
deleted file mode 100644 (file)
index cb29742..0000000
+++ /dev/null
@@ -1,520 +0,0 @@
-/*
-  Memcached library
-
-  memcached_response() is used to determine the return result
-  from an issued command.
-*/
-
-#include "common.h"
-#include "memcached_io.h"
-
-static memcached_return_t textual_read_one_response(memcached_server_st *ptr,
-                                                  char *buffer, size_t buffer_length,
-                                                  memcached_result_st *result);
-static memcached_return_t binary_read_one_response(memcached_server_st *ptr,
-                                                 char *buffer, size_t buffer_length,
-                                                 memcached_result_st *result);
-
-memcached_return_t memcached_read_one_response(memcached_server_st *ptr,
-                                             char *buffer, size_t buffer_length,
-                                             memcached_result_st *result)
-{
-  memcached_server_response_decrement(ptr);
-
-  if (result == NULL)
-    result = &ptr->root->result;
-
-  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 ||
-           rc == MEMCACHED_PROTOCOL_ERROR ||
-           rc == MEMCACHED_CLIENT_ERROR ||
-           rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
-     memcached_io_reset(ptr);
-
-  return rc;
-}
-
-memcached_return_t memcached_response(memcached_server_st *ptr, 
-                                    char *buffer, size_t buffer_length,
-                                    memcached_result_st *result)
-{
-  /* We may have old commands in the buffer not set, first purge */
-  if (ptr->root->flags.no_block)
-    (void)memcached_io_write(ptr, NULL, 0, 1);
-
-  /*
-   * The previous implementation purged all pending requests and just
-   * returned the last one. Purge all pending messages to ensure backwards
-   * compatibility. 
-   */
-  if (ptr->root->flags.binary_protocol == false)
-    while (memcached_server_response_count(ptr) > 1)
-    {
-      memcached_return_t rc= memcached_read_one_response(ptr, buffer, buffer_length, result);
-      
-      unlikely (rc != MEMCACHED_END &&
-                rc != MEMCACHED_STORED &&
-                rc != MEMCACHED_SUCCESS &&
-                rc != MEMCACHED_STAT && 
-                rc != MEMCACHED_DELETED &&
-                rc != MEMCACHED_NOTFOUND &&
-                rc != MEMCACHED_NOTSTORED && 
-                rc != MEMCACHED_DATA_EXISTS)
-       return rc;
-    }
-
-  return memcached_read_one_response(ptr, buffer, buffer_length, result);
-}
-
-static memcached_return_t textual_value_fetch(memcached_server_st *ptr,
-                                            char *buffer,
-                                            memcached_result_st *result)
-{
-  memcached_return_t rc= MEMCACHED_SUCCESS;
-  char *string_ptr;
-  char *end_ptr;
-  char *next_ptr;
-  size_t value_length;
-  size_t to_read;
-  char *value_ptr;
-
-  if (ptr->root->flags.use_udp)
-    return MEMCACHED_NOT_SUPPORTED;
-
-  WATCHPOINT_ASSERT(ptr->root);
-  end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
-
-  memcached_result_reset(result);
-
-  string_ptr= buffer;
-  string_ptr+= 6; /* "VALUE " */
-
-
-  /* We load the key */
-  {
-    char *key;
-    size_t prefix_length;
-
-    key= result->key;
-    result->key_length= 0;
-
-    for (prefix_length= ptr->root->prefix_key_length; !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
-    {
-      if (prefix_length == 0)
-      {
-        *key= *string_ptr;
-        key++;
-        result->key_length++;
-      }
-      else
-        prefix_length--;
-    }
-    result->key[result->key_length]= 0;
-  }
-
-  if (end_ptr == string_ptr)
-    goto read_error;
-
-  /* Flags fetch move past space */
-  string_ptr++;
-  if (end_ptr == string_ptr)
-    goto read_error;
-  for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
-  result->flags= (uint32_t) strtoul(next_ptr, &string_ptr, 10);
-
-  if (end_ptr == string_ptr)
-    goto read_error;
-
-  /* Length fetch move past space*/
-  string_ptr++;
-  if (end_ptr == string_ptr)
-    goto read_error;
-
-  for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
-  value_length= (size_t)strtoull(next_ptr, &string_ptr, 10);
-
-  if (end_ptr == string_ptr)
-    goto read_error;
-
-  /* Skip spaces */
-  if (*string_ptr == '\r')
-  {
-    /* Skip past the \r\n */
-    string_ptr+= 2;
-  }
-  else
-  {
-    string_ptr++;
-    for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
-    result->cas= strtoull(next_ptr, &string_ptr, 10);
-  }
-
-  if (end_ptr < string_ptr)
-    goto read_error;
-
-  /* We add two bytes so that we can walk the \r\n */
-  rc= memcached_string_check(&result->value, value_length+2);
-  if (rc != MEMCACHED_SUCCESS)
-  {
-    value_length= 0;
-    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-  }
-
-  value_ptr= memcached_string_value(&result->value);
-  /* 
-    We read the \r\n into the string since not doing so is more 
-    cycles then the waster of memory to do so.
-
-    We are null terminating through, which will most likely make
-    some people lazy about using the return length.
-  */
-  to_read= (value_length) + 2;
-  ssize_t read_length= 0;
-  memcached_return_t rrc= memcached_io_read(ptr, value_ptr, to_read, &read_length);
-  if (rrc != MEMCACHED_SUCCESS)
-    return rrc;
-
-  if (read_length != (ssize_t)(value_length + 2))
-  {
-    goto read_error;
-  }
-
-/* This next bit blows the API, but this is internal....*/
-  {
-    char *char_ptr;
-    char_ptr= memcached_string_value(&result->value);;
-    char_ptr[value_length]= 0;
-    char_ptr[value_length + 1]= 0;
-    memcached_string_set_length(&result->value, value_length);
-  }
-
-  return MEMCACHED_SUCCESS;
-
-read_error:
-  memcached_io_reset(ptr);
-
-  return MEMCACHED_PARTIAL_READ;
-}
-
-static memcached_return_t textual_read_one_response(memcached_server_st *ptr,
-                                                  char *buffer, size_t buffer_length,
-                                                  memcached_result_st *result)
-{
-  memcached_return_t rc= memcached_io_readline(ptr, buffer, buffer_length);
-  if (rc != MEMCACHED_SUCCESS)
-    return rc;
-
-  switch(buffer[0])
-  {
-  case 'V': /* VALUE || VERSION */
-    if (buffer[1] == 'A') /* VALUE */
-    {
-      /* We add back in one because we will need to search for END */
-      memcached_server_response_increment(ptr);
-      return textual_value_fetch(ptr, buffer, result);
-    }
-    else if (buffer[1] == 'E') /* VERSION */
-    {
-      return MEMCACHED_SUCCESS;
-    }
-    else
-    {
-      WATCHPOINT_STRING(buffer);
-      WATCHPOINT_ASSERT(0);
-      return MEMCACHED_UNKNOWN_READ_FAILURE;
-    }
-  case 'O': /* OK */
-    return MEMCACHED_SUCCESS;
-  case 'S': /* STORED STATS SERVER_ERROR */
-    {
-      if (buffer[2] == 'A') /* STORED STATS */
-      {
-        memcached_server_response_increment(ptr);
-        return MEMCACHED_STAT;
-      }
-      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 *)ptr->root->call_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;
-       }
-      else if (buffer[1] == 'T')
-        return MEMCACHED_STORED;
-      else
-      {
-        WATCHPOINT_STRING(buffer);
-        WATCHPOINT_ASSERT(0);
-        return MEMCACHED_UNKNOWN_READ_FAILURE;
-      }
-    }
-  case 'D': /* DELETED */
-    return MEMCACHED_DELETED;
-  case 'N': /* NOT_FOUND */
-    {
-      if (buffer[4] == 'F')
-        return MEMCACHED_NOTFOUND;
-      else if (buffer[4] == 'S')
-        return MEMCACHED_NOTSTORED;
-      else
-        return MEMCACHED_UNKNOWN_READ_FAILURE;
-    }
-  case 'E': /* PROTOCOL ERROR or END */
-    {
-      if (buffer[1] == 'N')
-        return MEMCACHED_END;
-      else if (buffer[1] == 'R')
-        return MEMCACHED_PROTOCOL_ERROR;
-      else if (buffer[1] == 'X')
-        return MEMCACHED_DATA_EXISTS;
-      else
-        return MEMCACHED_UNKNOWN_READ_FAILURE;
-    }
-  case 'I': /* CLIENT ERROR */
-      /* We add back in one because we will need to search for END */
-      memcached_server_response_increment(ptr);
-    return MEMCACHED_ITEM;
-  case 'C': /* CLIENT ERROR */
-    return MEMCACHED_CLIENT_ERROR;
-  default:
-    {
-      unsigned long long auto_return_value;
-
-      if (sscanf(buffer, "%llu", &auto_return_value) == 1)
-        return MEMCACHED_SUCCESS;
-
-      return MEMCACHED_UNKNOWN_READ_FAILURE;
-    }
-  }
-
-  /* NOTREACHED */
-}
-
-char *memcached_result_value(memcached_result_st *ptr)
-{
-  memcached_string_st *sptr= &ptr->value;
-  return memcached_string_value(sptr);
-}
-
-size_t memcached_result_length(memcached_result_st *ptr)
-{
-  memcached_string_st *sptr= &ptr->value;
-  return memcached_string_length(sptr);
-}
-
-static memcached_return_t binary_read_one_response(memcached_server_st *ptr,
-                                                 char *buffer, size_t buffer_length,
-                                                 memcached_result_st *result)
-{
-  protocol_binary_response_header header;
-   
-  unlikely (memcached_safe_read(ptr, &header.bytes, 
-                                sizeof(header.bytes)) != MEMCACHED_SUCCESS)
-    return MEMCACHED_UNKNOWN_READ_FAILURE;
-
-  unlikely (header.response.magic != PROTOCOL_BINARY_RES) 
-    return MEMCACHED_PROTOCOL_ERROR;
-
-  /*
-  ** Convert the header to host local endian!
-  */
-  header.response.keylen= ntohs(header.response.keylen);
-  header.response.status= ntohs(header.response.status);
-  header.response.bodylen= ntohl(header.response.bodylen);
-  header.response.cas= ntohll(header.response.cas);
-  uint32_t bodylen= header.response.bodylen;
-
-  if (header.response.status == 0) 
-  {
-    switch (header.response.opcode)
-    {
-    case PROTOCOL_BINARY_CMD_GETKQ:
-      /*
-       * We didn't increment the response counter for the GETKQ packet
-       * (only the final NOOP), so we need to increment the counter again.
-       */ 
-      memcached_server_response_increment(ptr); 
-      /* FALLTHROUGH */
-    case PROTOCOL_BINARY_CMD_GETK:
-      {
-        uint16_t keylen= header.response.keylen;
-        memcached_result_reset(result);
-        result->cas= header.response.cas;
-
-        if (memcached_safe_read(ptr, &result->flags,
-                                sizeof (result->flags)) != MEMCACHED_SUCCESS)
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-
-        result->flags= ntohl(result->flags);
-        bodylen -= header.response.extlen;
-
-        result->key_length= keylen;
-        if (memcached_safe_read(ptr, result->key, keylen) != MEMCACHED_SUCCESS) 
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-
-        bodylen -= keylen;
-        if (memcached_string_check(&result->value,
-                                   bodylen) != MEMCACHED_SUCCESS) 
-          return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-
-        char *vptr= memcached_string_value(&result->value);
-        if (memcached_safe_read(ptr, vptr, bodylen) != MEMCACHED_SUCCESS) 
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-
-        memcached_string_set_length(&result->value, bodylen);  
-      } 
-      break;
-    case PROTOCOL_BINARY_CMD_INCREMENT:
-    case PROTOCOL_BINARY_CMD_DECREMENT:
-      {
-        if (bodylen != sizeof(uint64_t) || buffer_length != sizeof(uint64_t)) 
-          return MEMCACHED_PROTOCOL_ERROR;
-
-        WATCHPOINT_ASSERT(bodylen == buffer_length);
-        uint64_t val;
-        if (memcached_safe_read(ptr, &val, sizeof(val)) != MEMCACHED_SUCCESS) 
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-
-        val= ntohll(val);
-        memcpy(buffer, &val, sizeof(val));
-      } 
-      break;
-    case PROTOCOL_BINARY_CMD_VERSION:
-      {
-        memset(buffer, 0, buffer_length);
-        if (bodylen >= buffer_length)
-          /* not enough space in buffer.. should not happen... */
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-        else if (memcached_safe_read(ptr, buffer, bodylen) != MEMCACHED_SUCCESS)
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-      } 
-      break;
-    case PROTOCOL_BINARY_CMD_FLUSH:
-    case PROTOCOL_BINARY_CMD_QUIT:
-    case PROTOCOL_BINARY_CMD_SET:
-    case PROTOCOL_BINARY_CMD_ADD:
-    case PROTOCOL_BINARY_CMD_REPLACE:
-    case PROTOCOL_BINARY_CMD_APPEND:
-    case PROTOCOL_BINARY_CMD_PREPEND:
-    case PROTOCOL_BINARY_CMD_DELETE:
-      {
-        WATCHPOINT_ASSERT(bodylen == 0);
-        return MEMCACHED_SUCCESS;
-      } 
-    case PROTOCOL_BINARY_CMD_NOOP:
-      {
-        WATCHPOINT_ASSERT(bodylen == 0);
-        return MEMCACHED_END;
-      }
-    case PROTOCOL_BINARY_CMD_STAT:
-      {
-        if (bodylen == 0)
-          return MEMCACHED_END;
-        else if (bodylen + 1 > buffer_length)
-          /* not enough space in buffer.. should not happen... */
-          return MEMCACHED_UNKNOWN_READ_FAILURE;
-        else 
-        {
-          size_t keylen= header.response.keylen;            
-          memset(buffer, 0, buffer_length);
-          if (memcached_safe_read(ptr, buffer, keylen) != MEMCACHED_SUCCESS ||
-              memcached_safe_read(ptr, buffer + keylen + 1, 
-                                  bodylen - keylen) != MEMCACHED_SUCCESS)
-            return MEMCACHED_UNKNOWN_READ_FAILURE;
-        }
-      } 
-      break;
-    default:
-      {
-        /* Command not implemented yet! */
-        WATCHPOINT_ASSERT(0);
-        return MEMCACHED_PROTOCOL_ERROR;
-      }        
-    }
-  } 
-  else if (header.response.bodylen) 
-  {
-     /* What should I do with the error message??? just discard it for now */
-    char hole[SMALL_STRING_LEN];
-    while (bodylen > 0) 
-    {
-      size_t nr= (bodylen > SMALL_STRING_LEN) ? SMALL_STRING_LEN : bodylen;
-      if (memcached_safe_read(ptr, hole, nr) != MEMCACHED_SUCCESS)
-        return MEMCACHED_UNKNOWN_READ_FAILURE;
-      bodylen-= (uint32_t) nr;
-    }
-
-    /* This might be an error from one of the quiet commands.. if
-     * so, just throw it away and get the next one. What about creating
-     * a callback to the user with the error information?
-     */
-    switch (header.response.opcode)
-    {
-    case PROTOCOL_BINARY_CMD_SETQ:
-    case PROTOCOL_BINARY_CMD_ADDQ:
-    case PROTOCOL_BINARY_CMD_REPLACEQ:
-    case PROTOCOL_BINARY_CMD_APPENDQ:
-    case PROTOCOL_BINARY_CMD_PREPENDQ:
-      return binary_read_one_response(ptr, buffer, buffer_length, result);
-    default:
-      break;
-    }
-  }
-
-  memcached_return_t rc= MEMCACHED_SUCCESS;
-  unlikely(header.response.status != 0) 
-    switch (header.response.status) 
-    {
-    case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT:
-      rc= MEMCACHED_NOTFOUND;
-      break;
-    case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS:
-      rc= MEMCACHED_DATA_EXISTS;
-      break;
-    case PROTOCOL_BINARY_RESPONSE_NOT_STORED:
-      rc= MEMCACHED_NOTSTORED;
-      break;
-    case PROTOCOL_BINARY_RESPONSE_E2BIG:
-      rc= MEMCACHED_E2BIG;
-      break;
-    case PROTOCOL_BINARY_RESPONSE_ENOMEM:
-      rc= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-      break;
-    case PROTOCOL_BINARY_RESPONSE_EINVAL:
-    case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
-    default:
-      /* @todo fix the error mappings */
-      rc= MEMCACHED_PROTOCOL_ERROR;
-      break;
-    }
-    
-  return rc;
-}
diff --git a/libmemcached/memcached_result.c b/libmemcached/memcached_result.c
deleted file mode 100644 (file)
index 14a0774..0000000
+++ /dev/null
@@ -1,81 +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: Functions to manipulate the result structure.
- *
- */
-
-/* 
-  memcached_result_st are used to internally represent the return values from
-  memcached. We use a structure so that long term as identifiers are added 
-  to memcached we will be able to absorb new attributes without having 
-  to addjust the entire API.
-*/
-#include "common.h"
-
-memcached_result_st *memcached_result_create(memcached_st *memc, 
-                                             memcached_result_st *ptr)
-{
-  WATCHPOINT_ASSERT(memc && memc->options.is_initialized);
-
-  /* Saving malloc calls :) */
-  if (ptr)
-  {
-    memset(ptr, 0, sizeof(memcached_result_st));
-  }
-  else
-  {
-    ptr= memc->call_malloc(memc, sizeof(memcached_result_st));
-
-    if (ptr == NULL)
-      return NULL;
-    ptr->options.is_allocated= true;
-  }
-
-  ptr->options.is_initialized= true;
-
-  ptr->root= memc;
-  memcached_string_create(memc, &ptr->value, 0);
-  WATCHPOINT_ASSERT_INITIALIZED(&ptr->value);
-  WATCHPOINT_ASSERT(ptr->value.string == NULL);
-
-  return ptr;
-}
-
-void memcached_result_reset(memcached_result_st *ptr)
-{
-  ptr->key_length= 0;
-  memcached_string_reset(&ptr->value);
-  ptr->flags= 0;
-  ptr->cas= 0;
-  ptr->expiration= 0;
-}
-
-/*
-  NOTE turn into macro
-*/
-memcached_return_t memcached_result_set_value(memcached_result_st *ptr, const char *value, size_t length)
-{
-  return memcached_string_append(&ptr->value, value, length);
-}
-
-void memcached_result_free(memcached_result_st *ptr)
-{
-  if (ptr == NULL)
-    return;
-
-  memcached_string_free(&ptr->value);
-
-  if (memcached_is_allocated(ptr))
-  {
-    free(ptr);
-  }
-  else
-  {
-    ptr->options.is_initialized= false;
-  }
-}
diff --git a/libmemcached/memcached_result.h b/libmemcached/memcached_result.h
deleted file mode 100644 (file)
index 4b0c12e..0000000
+++ /dev/null
@@ -1,65 +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: Functions to manipulate the result structure.
- *
- */
-
-#ifndef __MEMCACHED_RESULT_H__
-#define __MEMCACHED_RESULT_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct memcached_result_st {
-  struct {
-    bool is_allocated:1;
-    bool is_initialized:1;
-  } options;
-  uint32_t flags;
-  time_t expiration;
-  memcached_st *root;
-  size_t key_length;
-  uint64_t cas;
-  memcached_string_st value;
-  char key[MEMCACHED_MAX_KEY];
-  /* Add result callback function */
-};
-
-/* Result Struct */
-LIBMEMCACHED_API
-void memcached_result_free(memcached_result_st *result);
-LIBMEMCACHED_API
-void memcached_result_reset(memcached_result_st *ptr);
-LIBMEMCACHED_API
-memcached_result_st *memcached_result_create(memcached_st *ptr, 
-                                             memcached_result_st *result);
-#define memcached_result_key_value(A) (A)->key
-#define memcached_result_key_length(A) (A)->key_length
-#define memcached_result_string_st(A) ((A)->value)
-#ifdef FIX
-#define memcached_result_value(A) memcached_string_value((A)->value)
-#define memcached_result_length(A) memcached_string_length((A)->value)
-#else
-LIBMEMCACHED_API
-char *memcached_result_value(memcached_result_st *ptr);
-LIBMEMCACHED_API
-size_t memcached_result_length(memcached_result_st *ptr);
-#endif
-#define memcached_result_flags(A) (A)->flags
-#define memcached_result_cas(A) (A)->cas
-LIBMEMCACHED_API
-memcached_return_t memcached_result_set_value(memcached_result_st *ptr, const char *value, size_t length);
-#define memcached_result_set_flags(A,B) (A)->flags=(B)
-#define memcached_result_set_expiration(A,B) (A)->expiration=(B)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MEMCACHED_RESULT_H__ */
diff --git a/libmemcached/memcached_server.c b/libmemcached/memcached_server.c
deleted file mode 100644 (file)
index 2cff36d..0000000
+++ /dev/null
@@ -1,179 +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: String structure used for libmemcached.
- *
- */
-
-/*
-  This is a partial implementation for fetching/creating memcached_server_st objects.
-*/
-#include "common.h"
-
-memcached_server_st *memcached_server_create(memcached_st *memc, memcached_server_st *ptr)
-{
-  if (ptr == NULL)
-  {
-    ptr= (memcached_server_st *)calloc(1, sizeof(memcached_server_st));
-
-    if (!ptr)
-      return NULL; /*  MEMCACHED_MEMORY_ALLOCATION_FAILURE */
-
-    ptr->options.is_allocated= true;
-  }
-  else
-  {
-    memset(ptr, 0, sizeof(memcached_server_st));
-  }
-
-  ptr->root= memc;
-
-  return ptr;
-}
-
-memcached_server_st *memcached_server_create_with(memcached_st *memc, memcached_server_st *host,
-                                                  const char *hostname, in_port_t port,
-                                                  uint32_t weight, memcached_connection_t type)
-{
-  host= memcached_server_create(memc, host);
-
-  if (host == NULL)
-    return NULL;
-
-  strncpy(host->hostname, hostname, MEMCACHED_MAX_HOST_LENGTH - 1);
-  host->root= memc ? memc : NULL;
-  host->port= port;
-  host->weight= weight;
-  host->fd= -1;
-  host->type= type;
-  host->read_ptr= host->read_buffer;
-  if (memc)
-    host->next_retry= memc->retry_timeout;
-  if (type == MEMCACHED_CONNECTION_UDP)
-  {
-    host->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
-    memcached_io_init_udp_header(host, 0);
-  }
-
-  return host;
-}
-
-void memcached_server_free(memcached_server_st *ptr)
-{
-  memcached_quit_server(ptr, 0);
-
-  if (ptr->cached_server_error)
-    free(ptr->cached_server_error);
-
-  if (ptr->address_info)
-    freeaddrinfo(ptr->address_info);
-
-
-  if (memcached_is_allocated(ptr))
-  {
-    ptr->root->call_free(ptr->root, ptr);
-  }
-  else
-  {
-    memset(ptr, 0, sizeof(memcached_server_st));
-  }
-}
-
-/*
-  If we do not have a valid object to clone from, we toss an error.
-*/
-memcached_server_st *memcached_server_clone(memcached_server_st *clone, memcached_server_st *ptr)
-{
-  memcached_server_st *rv= NULL;
-
-  /* We just do a normal create if ptr is missing */
-  if (ptr == NULL)
-    return NULL;
-
-  rv = memcached_server_create_with(ptr->root, clone,
-                                    ptr->hostname, ptr->port, ptr->weight,
-                                    ptr->type);
-  if (rv != NULL)
-  {
-    rv->cached_errno= ptr->cached_errno;
-    if (ptr->cached_server_error)
-      rv->cached_server_error= strdup(ptr->cached_server_error);
-  }
-
-  return rv;
-
-}
-
-memcached_return_t memcached_server_cursor(memcached_st *ptr,
-                                           memcached_server_fn *callback,
-                                           void *context,
-                                           uint32_t number_of_callbacks)
-{
-  unsigned int y;
-
-  for (y= 0; y < ptr->number_of_hosts; y++)
-  {
-    unsigned int x;
-
-    for (x= 0; x < number_of_callbacks; x++)
-    {
-      unsigned int iferror;
-
-      iferror= (*callback[x])(ptr, &ptr->hosts[y], context);
-
-      if (iferror)
-        continue;
-    }
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_server_st *memcached_server_by_key(memcached_st *ptr,  const char *key, size_t key_length, memcached_return_t *error)
-{
-  uint32_t server_key;
-
-  *error= memcached_validate_key_length(key_length,
-                                        ptr->flags.binary_protocol);
-  unlikely (*error != MEMCACHED_SUCCESS)
-    return NULL;
-
-  unlikely (ptr->number_of_hosts == 0)
-  {
-    *error= MEMCACHED_NO_SERVERS;
-    return NULL;
-  }
-
-  if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
-  {
-    *error= MEMCACHED_BAD_KEY_PROVIDED;
-    return NULL;
-  }
-
-  server_key= memcached_generate_hash(ptr, key, key_length);
-
-  return memcached_server_clone(NULL, &ptr->hosts[server_key]);
-
-}
-
-const char *memcached_server_error(memcached_server_st *ptr)
-{
-  if (ptr)
-    return ptr->cached_server_error;
-  else
-    return NULL;
-}
-
-void memcached_server_error_reset(memcached_server_st *ptr)
-{
-  ptr->cached_server_error[0]= 0;
-}
-
-memcached_server_st *memcached_server_get_last_disconnect(memcached_st *ptr)
-{
-  return ptr->last_disconnected_server;
-}
diff --git a/libmemcached/memcached_server.h b/libmemcached/memcached_server.h
deleted file mode 100644 (file)
index f2d92dc..0000000
+++ /dev/null
@@ -1,101 +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: String structure used for libmemcached.
- *
- */
-
-#ifndef __MEMCACHED_SERVER_H__
-#define __MEMCACHED_SERVER_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct memcached_server_st {
-  struct {
-    bool is_allocated:1;
-  } options;
-  bool sockaddr_inited;
-  uint16_t count;
-  uint32_t cursor_active;
-  in_port_t port;
-  int cached_errno;
-  int fd;
-  uint32_t io_bytes_sent; /* # bytes sent since last read */
-  uint32_t server_failure_counter;
-  uint32_t weight;
-  uint8_t major_version;
-  uint8_t micro_version;
-  uint8_t minor_version;
-  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;
-  struct addrinfo *address_info;
-  time_t next_retry;
-  memcached_st *root;
-  uint64_t limit_maxbytes;
-  char read_buffer[MEMCACHED_MAX_BUFFER];
-  char write_buffer[MEMCACHED_MAX_BUFFER];
-  char hostname[MEMCACHED_MAX_HOST_LENGTH];
-};
-
-#define memcached_server_count(A) (A)->number_of_hosts
-#define memcached_server_name(A,B) (B).hostname
-#define memcached_server_port(A,B) (B).port
-#define memcached_server_list(A) (A)->hosts
-#define memcached_server_response_count(A) (A)->cursor_active
-
-LIBMEMCACHED_API
-memcached_return_t memcached_server_cursor(memcached_st *ptr,
-                                           memcached_server_fn *callback,
-                                           void *context,
-                                           uint32_t number_of_callbacks);
-
-LIBMEMCACHED_API
-memcached_server_st *memcached_server_by_key(memcached_st *ptr,  const char *key,
-                                             size_t key_length, memcached_return_t *error);
-
-LIBMEMCACHED_API
-const char *memcached_server_error(memcached_server_st *ptr);
-
-LIBMEMCACHED_API
-void memcached_server_error_reset(memcached_server_st *ptr);
-
-/* These should not currently be used by end users */
-/* TODO: Is the above comment valid? If so, how can we unit test these if they
- * aren't exported. If not, we should remove the comment */
-LIBMEMCACHED_API
-memcached_server_st *memcached_server_create(memcached_st *memc, memcached_server_st *ptr);
-
-LIBMEMCACHED_API
-memcached_server_st *memcached_server_create_with(memcached_st *memc, memcached_server_st *host,
-                                                  const char *hostname, in_port_t port,
-                                                  uint32_t weight, memcached_connection_t type);
-
-LIBMEMCACHED_API
-void memcached_server_free(memcached_server_st *ptr);
-LIBMEMCACHED_API
-memcached_server_st *memcached_server_clone(memcached_server_st *clone, memcached_server_st *ptr);
-LIBMEMCACHED_API
-memcached_analysis_st *memcached_analyze(memcached_st *memc, memcached_stat_st *memc_stat,
-                                         memcached_return_t *error);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_server_remove(memcached_server_st *st_ptr);
-
-LIBMEMCACHED_API
-memcached_server_st *memcached_server_get_last_disconnect(memcached_st *ptr);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MEMCACHED_SERVER_H__ */
diff --git a/libmemcached/memcached_stats.c b/libmemcached/memcached_stats.c
deleted file mode 100644 (file)
index e5f9a20..0000000
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
-*/
-
-#include "common.h"
-
-static const char *memcached_stat_keys[] = {
-  "pid",
-  "uptime",
-  "time",
-  "version",
-  "pointer_size",
-  "rusage_user",
-  "rusage_system",
-  "curr_items",
-  "total_items",
-  "bytes",
-  "curr_connections",
-  "total_connections",
-  "connection_structures",
-  "cmd_get",
-  "cmd_set",
-  "get_hits",
-  "get_misses",
-  "evictions",
-  "bytes_read",
-  "bytes_written",
-  "limit_maxbytes",
-  "threads",
-  NULL
-};
-
-
-static memcached_return_t set_data(memcached_stat_st *memc_stat, char *key, char *value)
-{
-
-  if (strlen(key) < 1) 
-  {
-    WATCHPOINT_STRING(key);
-    return MEMCACHED_UNKNOWN_STAT_KEY;
-  }
-  else if (!strcmp("pid", key))
-  {
-    memc_stat->pid= (uint32_t) strtol(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("uptime", key))
-  {
-    memc_stat->uptime= (uint32_t) strtol(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("time", key))
-  {
-    memc_stat->time= (uint32_t) strtol(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("version", key))
-  {
-    memcpy(memc_stat->version, value, strlen(value));
-    memc_stat->version[strlen(value)]= 0;
-  }
-  else if (!strcmp("pointer_size", key))
-  {
-    memc_stat->pointer_size= (uint32_t) strtol(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("rusage_user", key))
-  {
-    char *walk_ptr;
-    for (walk_ptr= value; (!ispunct(*walk_ptr)); walk_ptr++);
-    *walk_ptr= 0;
-    walk_ptr++;
-    memc_stat->rusage_user_seconds= (uint32_t) strtol(value, (char **)NULL, 10);
-    memc_stat->rusage_user_microseconds= (uint32_t) strtol(walk_ptr, (char **)NULL, 10);
-  }
-  else if (!strcmp("rusage_system", key))
-  {
-    char *walk_ptr;
-    for (walk_ptr= value; (!ispunct(*walk_ptr)); walk_ptr++);
-    *walk_ptr= 0;
-    walk_ptr++;
-    memc_stat->rusage_system_seconds= (uint32_t) strtol(value, (char **)NULL, 10);
-    memc_stat->rusage_system_microseconds= (uint32_t) strtol(walk_ptr, (char **)NULL, 10);
-  }
-  else if (!strcmp("curr_items", key))
-  {
-    memc_stat->curr_items= (uint32_t) strtol(value, (char **)NULL, 10); 
-  }
-  else if (!strcmp("total_items", key))
-  {
-    memc_stat->total_items= (uint32_t) strtol(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("bytes_read", key))
-  {
-    memc_stat->bytes_read= (uint32_t) strtoll(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("bytes_written", key))
-  {
-    memc_stat->bytes_written= (uint32_t) strtoll(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("bytes", key))
-  {
-    memc_stat->bytes= (uint32_t) strtoll(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("curr_connections", key))
-  {
-    memc_stat->curr_connections= (uint32_t) strtoll(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("total_connections", key))
-  {
-    memc_stat->total_connections= (uint32_t) strtoll(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("connection_structures", key))
-  {
-    memc_stat->connection_structures= (uint32_t) strtol(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("cmd_get", key))
-  {
-    memc_stat->cmd_get= (uint64_t) strtoll(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("cmd_set", key))
-  {
-    memc_stat->cmd_set= (uint64_t) strtoll(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("get_hits", key))
-  {
-    memc_stat->get_hits= (uint64_t) strtoll(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("get_misses", key))
-  {
-    memc_stat->get_misses= (uint64_t)strtoll(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("evictions", key))
-  {
-    memc_stat->evictions= (uint64_t)strtoll(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("limit_maxbytes", key))
-  {
-    memc_stat->limit_maxbytes= (uint64_t) strtoll(value, (char **)NULL, 10);
-  }
-  else if (!strcmp("threads", key))
-  {
-    memc_stat->threads= (uint32_t) strtol(value, (char **)NULL, 10);
-  }
-  else if (!(strcmp("delete_misses", key) == 0 ||/* New stats in the 1.3 beta */
-             strcmp("delete_hits", key) == 0 ||/* Just swallow them for now.. */
-             strcmp("incr_misses", key) == 0 ||
-             strcmp("incr_hits", key) == 0 ||
-             strcmp("decr_misses", key) == 0 ||
-             strcmp("decr_hits", key) == 0 ||
-             strcmp("cas_misses", key) == 0 ||
-             strcmp("cas_hits", key) == 0 ||
-             strcmp("cas_badval", key) == 0 ||
-             strcmp("cmd_flush", key) == 0 ||
-             strcmp("accepting_conns", key) == 0 ||
-             strcmp("listen_disabled_num", key) == 0 ||
-             strcmp("conn_yields", key) == 0))
-  {
-    WATCHPOINT_STRING(key);
-    return MEMCACHED_UNKNOWN_STAT_KEY;
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-char *memcached_stat_get_value(memcached_st *ptr, memcached_stat_st *memc_stat, 
-                               const char *key, memcached_return_t *error)
-{
-  char buffer[SMALL_STRING_LEN];
-  int length;
-  char *ret;
-
-  *error= MEMCACHED_SUCCESS;
-
-  if (!memcmp("pid", key, strlen("pid")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->pid);
-  else if (!memcmp("uptime", key, strlen("uptime")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->uptime);
-  else if (!memcmp("time", key, strlen("time")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->time);
-  else if (!memcmp("version", key, strlen("version")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%s", memc_stat->version);
-  else if (!memcmp("pointer_size", key, strlen("pointer_size")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->pointer_size);
-  else if (!memcmp("rusage_user", key, strlen("rusage_user")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%u.%u", memc_stat->rusage_user_seconds, memc_stat->rusage_user_microseconds);
-  else if (!memcmp("rusage_system", key, strlen("rusage_system")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%u.%u", memc_stat->rusage_system_seconds, memc_stat->rusage_system_microseconds);
-  else if (!memcmp("curr_items", key, strlen("curr_items")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->curr_items);
-  else if (!memcmp("total_items", key, strlen("total_items")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->total_items);
-  else if (!memcmp("curr_connections", key, strlen("curr_connections")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->curr_connections);
-  else if (!memcmp("total_connections", key, strlen("total_connections")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->total_connections);
-  else if (!memcmp("connection_structures", key, strlen("connection_structures")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->connection_structures);
-  else if (!memcmp("cmd_get", key, strlen("cmd_get")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->cmd_get);
-  else if (!memcmp("cmd_set", key, strlen("cmd_set")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->cmd_set);
-  else if (!memcmp("get_hits", key, strlen("get_hits")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->get_hits);
-  else if (!memcmp("get_misses", key, strlen("get_misses")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->get_misses);
-  else if (!memcmp("evictions", key, strlen("evictions")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->evictions);
-  else if (!memcmp("bytes_read", key, strlen("bytes_read")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes_read);
-  else if (!memcmp("bytes_written", key, strlen("bytes_written")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes_written);
-  else if (!memcmp("bytes", key, strlen("bytes")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes);
-  else if (!memcmp("limit_maxbytes", key, strlen("limit_maxbytes")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->limit_maxbytes);
-  else if (!memcmp("threads", key, strlen("threads")))
-    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->threads);
-  else
-  {
-    *error= MEMCACHED_NOTFOUND;
-    return NULL;
-  }
-
-  ret= ptr->call_malloc(ptr, (size_t) (length + 1));
-  memcpy(ret, buffer, (size_t) length);
-  ret[length]= '\0';
-
-  return ret;
-}
-
-static memcached_return_t binary_stats_fetch(memcached_st *ptr,
-                                             memcached_stat_st *memc_stat,
-                                             char *args,
-                                             unsigned int server_key)
-{
-  memcached_return_t rc;
-
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  protocol_binary_request_stats request= {.bytes= {0}};
-  request.message.header.request.magic= PROTOCOL_BINARY_REQ;
-  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_STAT;
-  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-
-  if (args != NULL) 
-  {
-    size_t len= strlen(args);
-
-    rc= memcached_validate_key_length(len, true);
-    unlikely (rc != MEMCACHED_SUCCESS)
-      return rc;
-
-    request.message.header.request.keylen= htons((uint16_t)len);
-    request.message.header.request.bodylen= htonl((uint32_t) len);
-
-    if ((memcached_do(&ptr->hosts[server_key], request.bytes, 
-                      sizeof(request.bytes), 0) != MEMCACHED_SUCCESS) ||
-        (memcached_io_write(&ptr->hosts[server_key], args, len, 1) == -1)) 
-    {
-      memcached_io_reset(&ptr->hosts[server_key]);
-      return MEMCACHED_WRITE_FAILURE;
-    }
-  }
-  else
-  {
-    if (memcached_do(&ptr->hosts[server_key], request.bytes, 
-                     sizeof(request.bytes), 1) != MEMCACHED_SUCCESS) 
-    {
-      memcached_io_reset(&ptr->hosts[server_key]);
-      return MEMCACHED_WRITE_FAILURE;
-    }
-  }
-
-  memcached_server_response_decrement(&ptr->hosts[server_key]);  
-  do 
-  {
-    rc= memcached_response(&ptr->hosts[server_key], buffer, 
-                           sizeof(buffer), NULL);
-    if (rc == MEMCACHED_END)
-      break;
-
-    unlikely (rc != MEMCACHED_SUCCESS) 
-    {
-      memcached_io_reset(&ptr->hosts[server_key]);
-      return rc;
-    }
-
-    unlikely((set_data(memc_stat, buffer, buffer + strlen(buffer) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY)
-    {
-      WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
-      WATCHPOINT_ASSERT(0);
-    }
-  } while (1);
-
-  /* shit... memcached_response will decrement the counter, so I need to
-   ** reset it.. todo: look at this and try to find a better solution.
- */
-  ptr->hosts[server_key].cursor_active= 0;
-
-  return MEMCACHED_SUCCESS;
-}
-
-static memcached_return_t ascii_stats_fetch(memcached_st *ptr,
-                                            memcached_stat_st *memc_stat,
-                                            char *args,
-                                            unsigned int server_key)
-{
-  memcached_return_t rc;
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  size_t send_length;
-
-  if (args)
-    send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
-                                   "stats %s\r\n", args);
-  else
-    send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
-                                   "stats\r\n");
-
-  if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
-    return MEMCACHED_WRITE_FAILURE;
-
-  rc= memcached_do(&ptr->hosts[server_key], buffer, send_length, 1);
-  if (rc != MEMCACHED_SUCCESS)
-    goto error;
-
-  while (1)
-  {
-    rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
-
-    if (rc == MEMCACHED_STAT)
-    {
-      char *string_ptr, *end_ptr;
-      char *key, *value;
-
-      string_ptr= buffer;
-      string_ptr+= 5; /* Move past STAT */
-      for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++);
-      key= string_ptr;
-      key[(size_t)(end_ptr-string_ptr)]= 0;
-
-      string_ptr= end_ptr + 1;
-      for (end_ptr= string_ptr; !(isspace(*end_ptr)); end_ptr++);
-      value= string_ptr;
-      value[(size_t)(end_ptr-string_ptr)]= 0;
-      string_ptr= end_ptr + 2;
-      unlikely((set_data(memc_stat, key, value)) == MEMCACHED_UNKNOWN_STAT_KEY)
-      {
-        WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
-        WATCHPOINT_ASSERT(0);
-      }
-    }
-    else
-      break;
-  }
-
-error:
-  if (rc == MEMCACHED_END)
-    return MEMCACHED_SUCCESS;
-  else
-    return rc;
-}
-
-memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_return_t *error)
-{
-  unsigned int x;
-  memcached_return_t rc;
-  memcached_stat_st *stats;
-
-  unlikely (ptr->flags.use_udp)
-  {
-    *error= MEMCACHED_NOT_SUPPORTED;
-    return NULL;
-  }
-
-  stats= ptr->call_calloc(ptr, ptr->number_of_hosts, sizeof(memcached_stat_st));
-
-  if (!stats)
-  {
-    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-    return NULL;
-  }
-
-  rc= MEMCACHED_SUCCESS;
-  for (x= 0; x < ptr->number_of_hosts; x++)
-  {
-    memcached_return_t temp_return;
-
-    if (ptr->flags.binary_protocol)
-      temp_return= binary_stats_fetch(ptr, stats + x, args, x);
-    else
-      temp_return= ascii_stats_fetch(ptr, stats + x, args, x);
-
-    if (temp_return != MEMCACHED_SUCCESS)
-      rc= MEMCACHED_SOME_ERRORS;
-  }
-
-  *error= rc;
-  return stats;
-}
-
-memcached_return_t memcached_stat_servername(memcached_stat_st *memc_stat, char *args, 
-                                             const char *hostname, in_port_t port)
-{
-  memcached_return_t rc;
-  memcached_st memc;
-  memcached_st *memc_ptr;
-
-  memc_ptr= memcached_create(&memc);
-  WATCHPOINT_ASSERT(memc_ptr);
-
-  memcached_server_add(&memc, hostname, port);
-
-  if (memc.flags.binary_protocol)
-    rc= binary_stats_fetch(&memc, memc_stat, args, 0);
-  else
-    rc= ascii_stats_fetch(&memc, memc_stat, args, 0);
-
-  memcached_free(&memc);
-
-  return rc;
-}
-
-/* 
-  We make a copy of the keys since at some point in the not so distant future
-  we will add support for "found" keys.
-*/
-char ** memcached_stat_get_keys(memcached_st *ptr, memcached_stat_st *memc_stat, 
-                                memcached_return_t *error)
-{
-  (void) memc_stat;
-  char **list;
-  size_t length= sizeof(memcached_stat_keys);
-
-  list= ptr->call_malloc(ptr, length);
-
-  if (!list)
-  {
-    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-    return NULL;
-  }
-
-  memcpy(list, memcached_stat_keys, sizeof(memcached_stat_keys));
-
-  *error= MEMCACHED_SUCCESS;
-
-  return list;
-}
-
-void memcached_stat_free(memcached_st *ptr, memcached_stat_st *memc_stat)
-{
-  if (memc_stat == NULL)
-  {
-    WATCHPOINT_ASSERT(0); /* Be polite, but when debugging catch this as an error */
-    return;
-  }
-
-  if (ptr)
-    ptr->call_free(ptr, memc_stat);
-  else
-    free(memc_stat);
-}
diff --git a/libmemcached/memcached_storage.c b/libmemcached/memcached_storage.c
deleted file mode 100644 (file)
index c6a556f..0000000
+++ /dev/null
@@ -1,520 +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: Storage related functions, aka set, replace,..
- *
- */
-
-#include "common.h"
-#include "memcached_io.h"
-
-typedef enum {
-  SET_OP,
-  REPLACE_OP,
-  ADD_OP,
-  PREPEND_OP,
-  APPEND_OP,
-  CAS_OP,
-} memcached_storage_action_t;
-
-/* Inline this */
-static inline const char *storage_op_string(memcached_storage_action_t verb)
-{
-  switch (verb)
-  {
-  case SET_OP:
-    return "set ";
-  case REPLACE_OP:
-    return "replace ";
-  case ADD_OP:
-    return "add ";
-  case PREPEND_OP:
-    return "prepend ";
-  case APPEND_OP:
-    return "append ";
-  case CAS_OP:
-    return "cas ";
-  default:
-    return "tosserror"; /* This is impossible, fixes issue for compiler warning in VisualStudio */
-  }
-
-  /* NOTREACHED */
-}
-
-static memcached_return_t 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, 
-                                                time_t expiration,
-                                                uint32_t flags,
-                                                uint64_t cas,
-                                                memcached_storage_action_t verb);
-
-static inline memcached_return_t memcached_send(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, 
-                                                time_t expiration,
-                                                uint32_t flags,
-                                                uint64_t cas,
-                                                memcached_storage_action_t verb)
-{
-  char to_write;
-  size_t write_length;
-  ssize_t sent_length;
-  memcached_return_t rc;
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  unsigned int server_key;
-
-  WATCHPOINT_ASSERT(!(value == NULL && value_length > 0));
-
-  rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol);
-  unlikely (rc != MEMCACHED_SUCCESS)
-    return rc;
-
-  unlikely (ptr->number_of_hosts == 0)
-    return MEMCACHED_NO_SERVERS;
-
-  if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
-    return MEMCACHED_BAD_KEY_PROVIDED;
-
-  if (ptr->flags.binary_protocol)
-  {
-    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= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
-                                    "%s %s%.*s %u %llu %zu %llu%s\r\n", 
-                                    storage_op_string(verb),
-                                    ptr->prefix_key,
-                                    (int)key_length, key, flags, 
-                                    (unsigned long long)expiration, value_length, 
-                                    (unsigned long long)cas,
-                                    (ptr->flags.no_reply) ? " noreply" : "");
-  }
-  else
-  {
-    char *buffer_ptr= buffer;
-    const char *command= storage_op_string(verb);
-
-    /* Copy in the command, no space needed, we handle that in the command function*/
-    memcpy(buffer_ptr, command, strlen(command));
-
-    /* Copy in the key prefix, switch to the buffer_ptr */
-    buffer_ptr= memcpy(buffer_ptr + strlen(command) , ptr->prefix_key, strlen(ptr->prefix_key));
-
-    /* Copy in the key, adjust point if a key prefix was used. */
-    buffer_ptr= memcpy(buffer_ptr + (ptr->prefix_key ? strlen(ptr->prefix_key) : 0), 
-                       key, key_length);
-    buffer_ptr+= key_length;
-    buffer_ptr[0]=  ' '; 
-    buffer_ptr++;
-
-    write_length= (size_t)(buffer_ptr - buffer);
-    write_length+= (size_t) snprintf(buffer_ptr, MEMCACHED_DEFAULT_COMMAND_SIZE, 
-                                     "%u %llu %zu%s\r\n", 
-                                     flags, 
-                                     (unsigned long long)expiration, value_length,
-                                     ptr->flags.no_reply ? " noreply" : "");
-  }
-
-  if (ptr->flags.use_udp && ptr->flags.buffer_requests)
-  {
-    size_t cmd_size= write_length + value_length + 2;
-    if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
-      return MEMCACHED_WRITE_FAILURE;
-    if (cmd_size + ptr->hosts[server_key].write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
-      memcached_io_write(&ptr->hosts[server_key], NULL, 0, 1);
-  }
-
-  if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
-  {
-    rc= MEMCACHED_WRITE_FAILURE;
-    goto error;
-  }
-
-  /* Send command header */
-  rc=  memcached_do(&ptr->hosts[server_key], buffer, write_length, 0);
-  if (rc != MEMCACHED_SUCCESS)
-    goto error;
-
-  /* Send command body */
-  if ((sent_length= memcached_io_write(&ptr->hosts[server_key], value, value_length, 0)) == -1)
-  {
-    rc= MEMCACHED_WRITE_FAILURE;
-    goto error;
-  }
-
-  if (ptr->flags.buffer_requests && verb == SET_OP)
-  {
-    to_write= 0;
-  }
-  else
-  {
-    to_write= 1;
-  }
-
-  if ((sent_length= memcached_io_write(&ptr->hosts[server_key], "\r\n", 2, to_write)) == -1)
-  {
-    rc= MEMCACHED_WRITE_FAILURE;
-    goto error;
-  }
-
-  if (ptr->flags.no_reply)
-    return (to_write == 0) ? MEMCACHED_BUFFERED : MEMCACHED_SUCCESS;
-
-  if (to_write == 0)
-    return MEMCACHED_BUFFERED;
-
-  rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
-
-  if (rc == MEMCACHED_STORED)
-    return MEMCACHED_SUCCESS;
-  else 
-    return rc;
-
-error:
-  memcached_io_reset(&ptr->hosts[server_key]);
-
-  return rc;
-}
-
-
-memcached_return_t memcached_set(memcached_st *ptr, const char *key, size_t key_length, 
-                                 const char *value, size_t value_length, 
-                                 time_t expiration,
-                                 uint32_t flags)
-{
-  memcached_return_t rc;
-  LIBMEMCACHED_MEMCACHED_SET_START();
-  rc= memcached_send(ptr, key, key_length, 
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, SET_OP);
-  LIBMEMCACHED_MEMCACHED_SET_END();
-  return rc;
-}
-
-memcached_return_t memcached_add(memcached_st *ptr, 
-                                 const char *key, size_t key_length,
-                                 const char *value, size_t value_length, 
-                                 time_t expiration,
-                                 uint32_t flags)
-{
-  memcached_return_t rc;
-  LIBMEMCACHED_MEMCACHED_ADD_START();
-  rc= memcached_send(ptr, key, key_length, 
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, ADD_OP);
-  LIBMEMCACHED_MEMCACHED_ADD_END();
-  return rc;
-}
-
-memcached_return_t memcached_replace(memcached_st *ptr, 
-                                     const char *key, size_t key_length,
-                                     const char *value, size_t value_length, 
-                                     time_t expiration,
-                                     uint32_t flags)
-{
-  memcached_return_t rc;
-  LIBMEMCACHED_MEMCACHED_REPLACE_START();
-  rc= memcached_send(ptr, key, key_length, 
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, REPLACE_OP);
-  LIBMEMCACHED_MEMCACHED_REPLACE_END();
-  return rc;
-}
-
-memcached_return_t memcached_prepend(memcached_st *ptr, 
-                                     const char *key, size_t key_length,
-                                     const char *value, size_t value_length, 
-                                     time_t expiration,
-                                     uint32_t flags)
-{
-  memcached_return_t rc;
-  rc= memcached_send(ptr, key, key_length, 
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, PREPEND_OP);
-  return rc;
-}
-
-memcached_return_t memcached_append(memcached_st *ptr, 
-                                    const char *key, size_t key_length,
-                                    const char *value, size_t value_length, 
-                                    time_t expiration,
-                                    uint32_t flags)
-{
-  memcached_return_t rc;
-  rc= memcached_send(ptr, key, key_length, 
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, APPEND_OP);
-  return rc;
-}
-
-memcached_return_t memcached_cas(memcached_st *ptr, 
-                                 const char *key, size_t key_length,
-                                 const char *value, size_t value_length, 
-                                 time_t expiration,
-                                 uint32_t flags,
-                                 uint64_t cas)
-{
-  memcached_return_t rc;
-  rc= memcached_send(ptr, key, key_length, 
-                     key, key_length, value, value_length,
-                     expiration, flags, cas, CAS_OP);
-  return rc;
-}
-
-memcached_return_t memcached_set_by_key(memcached_st *ptr, 
-                                        const char *master_key __attribute__((unused)), 
-                                        size_t master_key_length __attribute__((unused)), 
-                                        const char *key, size_t key_length, 
-                                        const char *value, size_t value_length, 
-                                        time_t expiration,
-                                        uint32_t flags)
-{
-  memcached_return_t rc;
-  LIBMEMCACHED_MEMCACHED_SET_START();
-  rc= memcached_send(ptr, master_key, master_key_length, 
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, SET_OP);
-  LIBMEMCACHED_MEMCACHED_SET_END();
-  return rc;
-}
-
-memcached_return_t memcached_add_by_key(memcached_st *ptr, 
-                                        const char *master_key, size_t master_key_length,
-                                        const char *key, size_t key_length,
-                                        const char *value, size_t value_length, 
-                                        time_t expiration,
-                                        uint32_t flags)
-{
-  memcached_return_t rc;
-  LIBMEMCACHED_MEMCACHED_ADD_START();
-  rc= memcached_send(ptr, master_key, master_key_length, 
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, ADD_OP);
-  LIBMEMCACHED_MEMCACHED_ADD_END();
-  return rc;
-}
-
-memcached_return_t memcached_replace_by_key(memcached_st *ptr, 
-                                            const char *master_key, size_t master_key_length,
-                                            const char *key, size_t key_length,
-                                            const char *value, size_t value_length, 
-                                            time_t expiration,
-                                            uint32_t flags)
-{
-  memcached_return_t rc;
-  LIBMEMCACHED_MEMCACHED_REPLACE_START();
-  rc= memcached_send(ptr, master_key, master_key_length, 
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, REPLACE_OP);
-  LIBMEMCACHED_MEMCACHED_REPLACE_END();
-  return rc;
-}
-
-memcached_return_t memcached_prepend_by_key(memcached_st *ptr, 
-                                            const char *master_key, size_t master_key_length,
-                                            const char *key, size_t key_length,
-                                            const char *value, size_t value_length, 
-                                            time_t expiration,
-                                            uint32_t flags)
-{
-  memcached_return_t rc;
-  rc= memcached_send(ptr, master_key, master_key_length, 
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, PREPEND_OP);
-  return rc;
-}
-
-memcached_return_t memcached_append_by_key(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, 
-                                           time_t expiration,
-                                           uint32_t flags)
-{
-  memcached_return_t rc;
-  rc= memcached_send(ptr, master_key, master_key_length, 
-                     key, key_length, value, value_length,
-                     expiration, flags, 0, APPEND_OP);
-  return rc;
-}
-
-memcached_return_t memcached_cas_by_key(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, 
-                                        time_t expiration,
-                                        uint32_t flags,
-                                        uint64_t cas)
-{
-  memcached_return_t rc;
-  rc= memcached_send(ptr, master_key, master_key_length, 
-                     key, key_length, value, value_length,
-                     expiration, flags, cas, CAS_OP);
-  return rc;
-}
-
-static inline uint8_t get_com_code(memcached_storage_action_t verb, bool noreply)
-{
-  /* 0 isn't a value we want, but GCC 4.2 seems to think ret can otherwise
-   * be used uninitialized in this function. FAIL */
-  uint8_t ret= 0;
-
-  if (noreply)
-    switch (verb)
-    {
-    case SET_OP:
-      ret=PROTOCOL_BINARY_CMD_SETQ;
-      break;
-    case ADD_OP:
-      ret=PROTOCOL_BINARY_CMD_ADDQ;
-      break;
-    case CAS_OP: /* FALLTHROUGH */
-    case REPLACE_OP:
-      ret=PROTOCOL_BINARY_CMD_REPLACEQ;
-      break;
-    case APPEND_OP:
-      ret=PROTOCOL_BINARY_CMD_APPENDQ;
-      break;
-    case PREPEND_OP:
-      ret=PROTOCOL_BINARY_CMD_PREPENDQ;
-      break;
-    default:
-      WATCHPOINT_ASSERT(verb);
-      break;
-    }
-  else
-    switch (verb)
-    {
-    case SET_OP:
-      ret=PROTOCOL_BINARY_CMD_SET;
-      break;
-    case ADD_OP:
-      ret=PROTOCOL_BINARY_CMD_ADD;
-      break;
-    case CAS_OP: /* FALLTHROUGH */
-    case REPLACE_OP:
-      ret=PROTOCOL_BINARY_CMD_REPLACE;
-      break;
-    case APPEND_OP:
-      ret=PROTOCOL_BINARY_CMD_APPEND;
-      break;
-    case PREPEND_OP:
-      ret=PROTOCOL_BINARY_CMD_PREPEND;
-      break;
-    default:
-      WATCHPOINT_ASSERT(verb);
-      break;
-    }
-
-  return ret;
-}
-
-
-
-static memcached_return_t 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, 
-                                                time_t expiration,
-                                                uint32_t flags,
-                                                uint64_t cas,
-                                                memcached_storage_action_t verb)
-{
-  uint8_t 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.no_reply;
-
-  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);
-  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! */
-  else 
-  {
-    request.message.header.request.extlen= 8;
-    request.message.body.flags= htonl(flags);   
-    request.message.body.expiration= htonl((uint32_t)expiration);
-  }
-
-  request.message.header.request.bodylen= htonl((uint32_t) (key_length + value_length + 
-                                                            request.message.header.request.extlen));
-
-  if (cas)
-    request.message.header.request.cas= htonll(cas);
-
-  flush= (uint8_t) ((server->root->flags.buffer_requests && verb == SET_OP) ? 0 : 1);
-
-  if (server->root->flags.use_udp && !flush)
-  {
-    size_t cmd_size= send_length + key_length + value_length;
-
-    if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
-      return MEMCACHED_WRITE_FAILURE;
-    if (cmd_size + server->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
-      memcached_io_write(server,NULL,0, 1);
-  }
-
-  /* write the header */
-  if ((memcached_do(server, (const char*)request.bytes, send_length, 0) != MEMCACHED_SUCCESS) ||
-      (memcached_io_write(server, key, key_length, 0) == -1) ||
-      (memcached_io_write(server, value, value_length, (char) flush) == -1)) 
-  {
-    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 (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, (char) flush) == -1))
-        memcached_io_reset(srv);
-      else
-        memcached_server_response_decrement(srv);
-    }
-  }
-
-  if (flush == 0)
-    return MEMCACHED_BUFFERED;
-
-  if (noreply)
-    return MEMCACHED_SUCCESS;
-
-  return memcached_response(server, NULL, 0, NULL);   
-}
-
diff --git a/libmemcached/memcached_storage.h b/libmemcached/memcached_storage.h
deleted file mode 100644 (file)
index d4f4995..0000000
+++ /dev/null
@@ -1,110 +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: Storage related functions, aka set, replace,..
- *
- */
-
-#ifndef __MEMCACHED_STORAGE_H__
-#define __MEMCACHED_STORAGE_H__
-
-#include "libmemcached/memcached_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* All of the functions for adding data to the server */
-LIBMEMCACHED_API
-memcached_return_t memcached_set(memcached_st *ptr, const char *key, size_t key_length, 
-                                 const char *value, size_t value_length, 
-                                 time_t expiration,
-                                 uint32_t  flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_add(memcached_st *ptr, const char *key, size_t key_length,
-                                 const char *value, size_t value_length, 
-                                 time_t expiration,
-                                 uint32_t  flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_replace(memcached_st *ptr, const char *key, size_t key_length,
-                                     const char *value, size_t value_length, 
-                                     time_t expiration,
-                                     uint32_t  flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_append(memcached_st *ptr, 
-                                    const char *key, size_t key_length,
-                                    const char *value, size_t value_length, 
-                                    time_t expiration,
-                                    uint32_t flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_prepend(memcached_st *ptr, 
-                                     const char *key, size_t key_length,
-                                     const char *value, size_t value_length, 
-                                     time_t expiration,
-                                     uint32_t flags);
-LIBMEMCACHED_API
-memcached_return_t memcached_cas(memcached_st *ptr, 
-                                 const char *key, size_t key_length,
-                                 const char *value, size_t value_length, 
-                                 time_t expiration,
-                                 uint32_t flags,
-                                 uint64_t cas);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_set_by_key(memcached_st *ptr, 
-                                        const char *master_key, size_t master_key_length, 
-                                        const char *key, size_t key_length, 
-                                        const char *value, size_t value_length, 
-                                        time_t expiration,
-                                        uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_add_by_key(memcached_st *ptr, 
-                                        const char *master_key, size_t master_key_length,
-                                        const char *key, size_t key_length,
-                                        const char *value, size_t value_length, 
-                                        time_t expiration,
-                                        uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_replace_by_key(memcached_st *ptr, 
-                                            const char *master_key, size_t master_key_length,
-                                            const char *key, size_t key_length,
-                                            const char *value, size_t value_length, 
-                                            time_t expiration,
-                                            uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_prepend_by_key(memcached_st *ptr, 
-                                            const char *master_key, size_t master_key_length,
-                                            const char *key, size_t key_length,
-                                            const char *value, size_t value_length, 
-                                            time_t expiration,
-                                            uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_append_by_key(memcached_st *ptr, 
-                                           const char *master_key, size_t master_key_length,
-                                           const char *key, size_t key_length,
-                                           const char *value, size_t value_length, 
-                                           time_t expiration,
-                                           uint32_t flags);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_cas_by_key(memcached_st *ptr, 
-                                        const char *master_key, size_t master_key_length,
-                                        const char *key, size_t key_length,
-                                        const char *value, size_t value_length, 
-                                        time_t expiration,
-                                        uint32_t flags,
-                                        uint64_t cas);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MEMCACHED_STORAGE_H__ */
diff --git a/libmemcached/memcached_strerror.c b/libmemcached/memcached_strerror.c
deleted file mode 100644 (file)
index f1d651c..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "common.h"
-
-const char *memcached_strerror(memcached_st *ptr __attribute__((unused)), memcached_return_t rc)
-{
-  switch (rc)
-  {
-  case MEMCACHED_SUCCESS:
-    return "SUCCESS";
-  case MEMCACHED_FAILURE:
-    return "FAILURE";
-  case MEMCACHED_HOST_LOOKUP_FAILURE:
-    return "HOSTNAME LOOKUP FAILURE";
-  case MEMCACHED_CONNECTION_FAILURE:
-    return "CONNECTION FAILURE";
-  case MEMCACHED_CONNECTION_BIND_FAILURE:
-    return "CONNECTION BIND FAILURE";
-  case MEMCACHED_READ_FAILURE:
-    return "READ FAILURE";
-  case MEMCACHED_UNKNOWN_READ_FAILURE:
-    return "UNKNOWN READ FAILURE";
-  case MEMCACHED_PROTOCOL_ERROR:
-    return "PROTOCOL ERROR";
-  case MEMCACHED_CLIENT_ERROR:
-    return "CLIENT ERROR";
-  case MEMCACHED_SERVER_ERROR:
-    return "SERVER ERROR";
-  case MEMCACHED_WRITE_FAILURE:
-    return "WRITE FAILURE";
-  case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE:
-    return "CONNECTION SOCKET CREATE FAILURE";
-  case MEMCACHED_DATA_EXISTS:
-    return "CONNECTION DATA EXISTS";
-  case MEMCACHED_DATA_DOES_NOT_EXIST:
-    return "CONNECTION DATA DOES NOT EXIST";
-  case MEMCACHED_NOTSTORED:
-    return "NOT STORED";
-  case MEMCACHED_STORED:
-    return "STORED";
-  case MEMCACHED_NOTFOUND:
-    return "NOT FOUND";
-  case MEMCACHED_MEMORY_ALLOCATION_FAILURE:
-    return "MEMORY ALLOCATION FAILURE";
-  case MEMCACHED_PARTIAL_READ:
-    return "PARTIAL READ";
-  case MEMCACHED_SOME_ERRORS:
-    return "SOME ERRORS WERE REPORTED";
-  case MEMCACHED_NO_SERVERS:
-    return "NO SERVERS DEFINED";
-  case MEMCACHED_END:
-    return "SERVER END";
-  case MEMCACHED_DELETED:
-    return "SERVER DELETE";
-  case MEMCACHED_VALUE:
-    return "SERVER VALUE";
-  case MEMCACHED_STAT:
-    return "STAT VALUE";
-  case MEMCACHED_ITEM:
-    return "ITEM VALUE";
-  case MEMCACHED_ERRNO:
-    return "SYSTEM ERROR";
-  case MEMCACHED_FAIL_UNIX_SOCKET:
-    return "COULD NOT OPEN UNIX SOCKET";
-  case MEMCACHED_NOT_SUPPORTED:
-    return "ACTION NOT SUPPORTED";
-  case MEMCACHED_FETCH_NOTFINISHED:
-    return "FETCH WAS NOT COMPLETED";
-  case MEMCACHED_NO_KEY_PROVIDED:
-    return "A KEY LENGTH OF ZERO WAS PROVIDED";
-  case MEMCACHED_BUFFERED:
-    return "ACTION QUEUED";
-  case MEMCACHED_TIMEOUT:
-    return "A TIMEOUT OCCURRED";
-  case MEMCACHED_BAD_KEY_PROVIDED:
-    return "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE";
-  case MEMCACHED_INVALID_HOST_PROTOCOL:
-    return "THE HOST TRANSPORT PROTOCOL DOES NOT MATCH THAT OF THE CLIENT";
-  case MEMCACHED_SERVER_MARKED_DEAD:
-    return "SERVER IS MARKED DEAD";
-  case MEMCACHED_UNKNOWN_STAT_KEY:
-    return "ENCOUNTERED AN UNKNOWN STAT KEY";
-  case MEMCACHED_E2BIG:
-    return "ITEM TOO BIG";
-  case MEMCACHED_INVALID_ARGUMENTS:
-     return "INVALID ARGUMENTS";
-  case MEMCACHED_MAXIMUM_RETURN:
-    return "Gibberish returned!";
-  default:
-    return "Gibberish returned!";
-  }
-}
diff --git a/libmemcached/memcached_string.c b/libmemcached/memcached_string.c
deleted file mode 100644 (file)
index 838ca41..0000000
+++ /dev/null
@@ -1,171 +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: String structure used for libmemcached.
- *
- */
-
-#include "common.h"
-
-inline static memcached_return_t _string_check(memcached_string_st *string, size_t need)
-{
-  if (need && need > (size_t)(string->current_size - (size_t)(string->end - string->string)))
-  {
-    size_t current_offset= (size_t) (string->end - string->string);
-    char *new_value;
-    size_t adjust;
-    size_t new_size;
-
-    /* This is the block multiplier. To keep it larger and surive division errors we must round it up */
-    adjust= (need - (size_t)(string->current_size - (size_t)(string->end - string->string))) / string->block_size;
-    adjust++;
-
-    new_size= sizeof(char) * (size_t)((adjust * string->block_size) + string->current_size);
-    /* Test for overflow */
-    if (new_size < need)
-      return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-
-    new_value= string->root->call_realloc(string->root, string->string, new_size);
-
-    if (new_value == NULL)
-      return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
-
-    string->string= new_value;
-    string->end= string->string + current_offset;
-
-    string->current_size+= (string->block_size * adjust);
-  }
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_string_st *memcached_string_create(memcached_st *memc, memcached_string_st *string, size_t initial_size)
-{
-  memcached_return_t rc;
-
-  /* Saving malloc calls :) */
-  if (string)
-  {
-    WATCHPOINT_ASSERT(memc->options.is_safe && string->options.is_initialized == false);
-
-    memset(string, 0, sizeof(memcached_string_st));
-  }
-  else
-  {
-    string= memc->call_calloc(memc, 1, sizeof(memcached_string_st));
-
-    if (string == NULL)
-    {
-      return NULL;
-    }
-
-    string->options.is_allocated= true;
-  }
-  string->block_size= MEMCACHED_BLOCK_SIZE;
-  string->root= memc;
-
-  rc=  _string_check(string, initial_size);
-  if (rc != MEMCACHED_SUCCESS)
-  {
-    memc->call_free(memc, string);
-    return NULL;
-  }
-
-  string->options.is_initialized= true;
-
-  WATCHPOINT_ASSERT(string->string == string->end);
-
-  return string;
-}
-
-memcached_return_t memcached_string_append_character(memcached_string_st *string, 
-                                                   char character)
-{
-  memcached_return_t rc;
-
-  rc=  _string_check(string, 1);
-
-  if (rc != MEMCACHED_SUCCESS)
-    return rc;
-
-  *string->end= character;
-  string->end++;
-
-  return MEMCACHED_SUCCESS;
-}
-
-memcached_return_t memcached_string_append(memcached_string_st *string,
-                                         const char *value, size_t length)
-{
-  memcached_return_t rc;
-
-  rc= _string_check(string, length);
-
-  if (rc != MEMCACHED_SUCCESS)
-    return rc;
-
-  WATCHPOINT_ASSERT(length <= string->current_size);
-  WATCHPOINT_ASSERT(string->string);
-  WATCHPOINT_ASSERT(string->end >= string->string);
-
-  memcpy(string->end, value, length);
-  string->end+= length;
-
-  return MEMCACHED_SUCCESS;
-}
-
-char *memcached_string_c_copy(memcached_string_st *string)
-{
-  char *c_ptr;
-
-  if (memcached_string_length(string) == 0)
-    return NULL;
-
-  c_ptr= string->root->call_malloc(string->root, (memcached_string_length(string)+1) * sizeof(char));
-
-  if (c_ptr == NULL)
-    return NULL;
-
-  memcpy(c_ptr, memcached_string_value(string), memcached_string_length(string));
-  c_ptr[memcached_string_length(string)]= 0;
-
-  return c_ptr;
-}
-
-memcached_return_t memcached_string_reset(memcached_string_st *string)
-{
-  string->end= string->string;
-  
-  return MEMCACHED_SUCCESS;
-}
-
-void memcached_string_free(memcached_string_st *ptr)
-{
-  if (ptr == NULL)
-    return;
-
-  if (ptr->string)
-  {
-    ptr->root->call_free(ptr->root, ptr->string);
-  }
-
-  if (memcached_is_allocated(ptr))
-  {
-    ptr->root->call_free(ptr->root, ptr);
-  }
-  else
-  {
-    ptr->options.is_initialized= false;
-    memset(ptr, 0, sizeof(memcached_string_st));
-  }
-}
-
-memcached_return_t memcached_string_check(memcached_string_st *string, size_t need)
-{
-  return _string_check(string, need);
-}
-
diff --git a/libmemcached/memcached_string.h b/libmemcached/memcached_string.h
deleted file mode 100644 (file)
index d93bc0d..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: String structure used for libmemcached.
- *
- */
-
-#ifndef __MEMCACHED_STRING_H__
-#define __MEMCACHED_STRING_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct memcached_string_st {
-  memcached_st *root;
-  char *end;
-  char *string;
-  size_t current_size;
-  size_t block_size;
-  struct {
-    bool is_allocated:1;
-    bool is_initialized:1;
-  } options;
-};
-
-#define memcached_string_length(A) (size_t)((A)->end - (A)->string)
-#define memcached_string_set_length(A, B) (A)->end= (A)->string + B
-#define memcached_string_size(A) (A)->current_size
-#define memcached_string_value(A) (A)->string
-
-LIBMEMCACHED_API
-memcached_string_st *memcached_string_create(memcached_st *ptr,
-                                             memcached_string_st *string,
-                                             size_t initial_size);
-LIBMEMCACHED_API
-memcached_return_t memcached_string_check(memcached_string_st *string, size_t need);
-
-LIBMEMCACHED_API
-char *memcached_string_c_copy(memcached_string_st *string);
-
-LIBMEMCACHED_API
-memcached_return_t memcached_string_append_character(memcached_string_st *string,
-                                                     char character);
-LIBMEMCACHED_API
-memcached_return_t memcached_string_append(memcached_string_st *string,
-                                           const char *value, size_t length);
-LIBMEMCACHED_API
-memcached_return_t memcached_string_reset(memcached_string_st *string);
-
-LIBMEMCACHED_API
-void memcached_string_free(memcached_string_st *string);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MEMCACHED_STRING_H__ */
diff --git a/libmemcached/memcached_types.h b/libmemcached/memcached_types.h
deleted file mode 100644 (file)
index 58f0887..0000000
+++ /dev/null
@@ -1,76 +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: Types for libmemcached
- *
- */
-
-#ifndef LIBMEMCACHED_MEMCACHED_TYPES_H
-#define LIBMEMCACHED_MEMCACHED_TYPES_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct memcached_st memcached_st;
-typedef struct memcached_stat_st memcached_stat_st;
-typedef struct memcached_analysis_st memcached_analysis_st;
-typedef struct memcached_result_st memcached_result_st;
-typedef struct memcached_string_st memcached_string_st;
-typedef struct memcached_server_st memcached_server_st;
-typedef struct memcached_continuum_item_st memcached_continuum_item_st;
-typedef memcached_return_t (*memcached_clone_fn)(memcached_st *parent, memcached_st *clone);
-typedef memcached_return_t (*memcached_cleanup_fn)(memcached_st *ptr);
-typedef void (*memcached_free_fn)(memcached_st *ptr, void *mem);
-typedef void *(*memcached_malloc_fn)(memcached_st *ptr, const size_t size);
-typedef void *(*memcached_realloc_fn)(memcached_st *ptr, void *mem, const size_t size);
-typedef void *(*memcached_calloc_fn)(memcached_st *ptr, size_t nelem, const size_t elsize);
-typedef memcached_return_t (*memcached_execute_fn)(memcached_st *ptr, memcached_result_st *result, void *context);
-typedef memcached_return_t (*memcached_server_fn)(memcached_st *ptr, memcached_server_st *server, void *context);
-typedef memcached_return_t (*memcached_trigger_key_fn)(memcached_st *ptr,
-                                                       const char *key, size_t key_length,
-                                                       memcached_result_st *result);
-typedef memcached_return_t (*memcached_trigger_delete_key_fn)(memcached_st *ptr,
-                                                              const char *key, size_t key_length);
-
-typedef memcached_return_t (*memcached_dump_fn)(memcached_st *ptr,
-                                                  const char *key, size_t key_length, void *context);
-
-typedef struct {
-  memcached_execute_fn *callback;
-  void *context;
-  uint32_t number_of_callback;
-} memcached_callback_st;
-
-/**
-  @note The following definitions are just here for backwards compatibility.
-*/
-typedef memcached_return_t memcached_return;
-typedef memcached_server_distribution_t memcached_server_distribution;
-typedef memcached_behavior_t memcached_behavior;
-typedef memcached_callback_t memcached_callback;
-typedef memcached_hash_t memcached_hash;
-typedef memcached_connection_t memcached_connection;
-typedef memcached_clone_fn memcached_clone_func;
-typedef memcached_cleanup_fn memcached_cleanup_func;
-typedef memcached_free_fn memcached_free_function;
-typedef memcached_malloc_fn memcached_malloc_function;
-typedef memcached_realloc_fn memcached_realloc_function;
-typedef memcached_calloc_fn memcached_calloc_function;
-typedef memcached_execute_fn memcached_execute_function;
-typedef memcached_server_fn memcached_server_function;
-typedef memcached_trigger_key_fn memcached_trigger_key;
-typedef memcached_trigger_delete_key_fn memcached_trigger_delete_key;
-typedef memcached_dump_fn memcached_dump_func;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LIBMEMCACHED_MEMCACHED_TYPES_H */
index f06804b40d1ecffe1238443df8b06fd39a82f9af..c1a719d660eb50ffe1d5846c32c4f0f0b4162821 100644 (file)
@@ -15,6 +15,6 @@
 #ifndef MEMCACHED_UTIL_H
 #define MEMCACHED_UTIL_H
 
-#include <libmemcached/memcached_pool.h>
+#include <libmemcached/pool.h>
 
 #endif /* MEMCACHED_UTIL_H */
diff --git a/libmemcached/memcached_verbosity.c b/libmemcached/memcached_verbosity.c
deleted file mode 100644 (file)
index 3d34880..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-#include "common.h"
-
-memcached_return_t memcached_verbosity(memcached_st *ptr, unsigned int verbosity)
-{
-  unsigned int x;
-  size_t send_length;
-  memcached_return_t rc;
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-
-  send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
-                                 "verbosity %u\r\n", verbosity);
-  unlikely (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
-    return MEMCACHED_WRITE_FAILURE;
-
-  rc= MEMCACHED_SUCCESS;
-  for (x= 0; x < ptr->number_of_hosts; x++)
-  {
-    memcached_return_t rrc;
-
-    rrc= memcached_do(&ptr->hosts[x], buffer, send_length, 1);
-    if (rrc != MEMCACHED_SUCCESS)
-    {
-      rc= MEMCACHED_SOME_ERRORS;
-      continue;
-    }
-
-    unlikely (ptr->flags.use_udp)
-      continue;
-
-    rrc= memcached_response(&ptr->hosts[x], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
-    if (rrc != MEMCACHED_SUCCESS)
-      rc= MEMCACHED_SOME_ERRORS;
-  }
-
-  return rc;
-}
diff --git a/libmemcached/memcached_version.c b/libmemcached/memcached_version.c
deleted file mode 100644 (file)
index db2419c..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-#include "common.h"
-
-const char * memcached_lib_version(void) 
-{
-  return LIBMEMCACHED_VERSION_STRING;
-}
-
-static inline memcached_return_t memcached_version_binary(memcached_st *ptr);
-static inline memcached_return_t memcached_version_textual(memcached_st *ptr);
-
-memcached_return_t memcached_version(memcached_st *ptr)
-{
-  if (ptr->flags.use_udp)
-    return MEMCACHED_NOT_SUPPORTED;
-
-  if (ptr->flags.binary_protocol)
-    return memcached_version_binary(ptr);
-  else
-    return memcached_version_textual(ptr);      
-}
-
-static inline memcached_return_t memcached_version_textual(memcached_st *ptr)
-{
-  unsigned int x;
-  size_t send_length;
-  memcached_return_t rc;
-  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
-  char *response_ptr;
-  const char *command= "version\r\n";
-
-  send_length= strlen(command);
-
-  rc= MEMCACHED_SUCCESS;
-  for (x= 0; x < ptr->number_of_hosts; x++)
-  {
-    memcached_return_t rrc;
-
-    rrc= memcached_do(&ptr->hosts[x], command, send_length, 1);
-    if (rrc != MEMCACHED_SUCCESS)
-    {
-      rc= MEMCACHED_SOME_ERRORS;
-      continue;
-    }
-
-    rrc= memcached_response(&ptr->hosts[x], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
-    if (rrc != MEMCACHED_SUCCESS)
-    {
-      rc= MEMCACHED_SOME_ERRORS;
-      continue;
-    }
-
-    /* Find the space, and then move one past it to copy version */
-    response_ptr= index(buffer, ' ');
-    response_ptr++;
-
-    ptr->hosts[x].major_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
-    response_ptr= index(response_ptr, '.');
-    response_ptr++;
-    ptr->hosts[x].minor_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
-    response_ptr= index(response_ptr, '.');
-    response_ptr++;
-    ptr->hosts[x].micro_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
-  }
-
-  return rc;
-}
-
-static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
-{
-  memcached_return_t rc;
-  unsigned int x;
-  protocol_binary_request_version request= { .bytes= {0}};
-  request.message.header.request.magic= PROTOCOL_BINARY_REQ;
-  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
-  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
-
-  rc= MEMCACHED_SUCCESS;
-  for (x= 0; x < ptr->number_of_hosts; x++) 
-  {
-    memcached_return_t rrc;
-
-    rrc= memcached_do(&ptr->hosts[x], request.bytes, sizeof(request.bytes), 1);
-    if (rrc != MEMCACHED_SUCCESS) 
-    {
-      memcached_io_reset(&ptr->hosts[x]);
-      rc= MEMCACHED_SOME_ERRORS;
-      continue;
-    }
-  }
-
-  for (x= 0; x < ptr->number_of_hosts; x++) 
-    if (memcached_server_response_count(&ptr->hosts[x]) > 0) 
-    {
-      memcached_return_t rrc;
-      char buffer[32];
-      char *p;
-
-      rrc= memcached_response(&ptr->hosts[x], buffer, sizeof(buffer), NULL);
-      if (rrc != MEMCACHED_SUCCESS) 
-      {
-        memcached_io_reset(&ptr->hosts[x]);
-        rc= MEMCACHED_SOME_ERRORS;
-        continue;
-      }
-
-      ptr->hosts[x].major_version= (uint8_t)strtol(buffer, &p, 10);
-      ptr->hosts[x].minor_version= (uint8_t)strtol(p + 1, &p, 10);
-      ptr->hosts[x].micro_version= (uint8_t)strtol(p + 1, NULL, 10);
-    }
-
-  return rc;
-}
diff --git a/libmemcached/memcached_watchpoint.h b/libmemcached/memcached_watchpoint.h
deleted file mode 100644 (file)
index d8c593e..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/* LibMemcached
- * Copyright (C) 2006-2009 Brian Aker 
- * All rights reserved.
- *
- * Use and distribution licensed under the BSD license.  See
- * the COPYING file in the parent directory for full text.
- *
- * Summary: Localized copy of WATCHPOINT debug symbols
- *
- */
-
-#ifndef LIBMEMCACHED_MEMCACHED_WATCHPOINT_H
-#define LIBMEMCACHED_MEMCACHED_WATCHPOINT_H
-
-/* Some personal debugging functions */
-#if defined(DEBUG)
-
-#include <assert.h>
-
-#define WATCHPOINT fprintf(stderr, "\nWATCHPOINT %s:%d (%s)\n", __FILE__, __LINE__,__func__);fflush(stdout);
-#define WATCHPOINT_ERROR(A) fprintf(stderr, "\nWATCHPOINT %s:%d %s\n", __FILE__, __LINE__, memcached_strerror(NULL, A));fflush(stdout);
-#define WATCHPOINT_IFERROR(A) if(A != MEMCACHED_SUCCESS)fprintf(stderr, "\nWATCHPOINT %s:%d %s\n", __FILE__, __LINE__, memcached_strerror(NULL, A));fflush(stdout);
-#define WATCHPOINT_STRING(A) fprintf(stderr, "\nWATCHPOINT %s:%d (%s) %s\n", __FILE__, __LINE__,__func__,A);fflush(stdout);
-#define WATCHPOINT_STRING_LENGTH(A,B) fprintf(stderr, "\nWATCHPOINT %s:%d (%s) %.*s\n", __FILE__, __LINE__,__func__,(int)B,A);fflush(stdout);
-#define WATCHPOINT_NUMBER(A) fprintf(stderr, "\nWATCHPOINT %s:%d (%s) %zu\n", __FILE__, __LINE__,__func__,(size_t)(A));fflush(stdout);
-#define WATCHPOINT_ERRNO(A) fprintf(stderr, "\nWATCHPOINT %s:%d (%s) %s\n", __FILE__, __LINE__,__func__, strerror(A));fflush(stdout);
-#define WATCHPOINT_ASSERT_PRINT(A,B,C) if(!(A)){fprintf(stderr, "\nWATCHPOINT ASSERT %s:%d (%s) ", __FILE__, __LINE__,__func__);fprintf(stderr, (B),(C));fprintf(stderr,"\n");fflush(stdout);}assert((A));
-#define WATCHPOINT_ASSERT(A) assert((A));
-#define WATCHPOINT_ASSERT_INITIALIZED(A) (memcached_is_initialized((A));
-
-#else
-
-#define WATCHPOINT
-#define WATCHPOINT_ERROR(A)
-#define WATCHPOINT_IFERROR(A)
-#define WATCHPOINT_STRING(A)
-#define WATCHPOINT_NUMBER(A)
-#define WATCHPOINT_ERRNO(A)
-#define WATCHPOINT_ASSERT_PRINT(A,B,C)
-#define WATCHPOINT_ASSERT(A)
-#define WATCHPOINT_ASSERT_INITIALIZED(A)
-
-#endif /* DEBUG */
-
-#endif /* LIBMEMCACHED_MEMCACHED_WATCHPOINT_H */
diff --git a/libmemcached/parse.c b/libmemcached/parse.c
new file mode 100644 (file)
index 0000000..73cc9df
--- /dev/null
@@ -0,0 +1,74 @@
+/* 
+  I debated about putting this in the client library since it does an 
+  action I don't really believe belongs in the library.
+
+  Frankly its too damn useful not to be here though.
+*/
+
+#include "common.h"
+
+memcached_server_st *memcached_servers_parse(const char *server_strings)
+{
+  char *string;
+  uint32_t port;
+  uint32_t weight;
+  const char *begin_ptr;
+  const char *end_ptr;
+  memcached_server_st *servers= NULL;
+  memcached_return_t rc;
+
+  WATCHPOINT_ASSERT(server_strings);
+
+  end_ptr= server_strings + strlen(server_strings);
+
+  for (begin_ptr= server_strings, string= index(server_strings, ','); 
+       begin_ptr != end_ptr; 
+       string= index(begin_ptr, ','))
+  {
+    char buffer[HUGE_STRING_LEN];
+    char *ptr, *ptr2;
+    port= 0;
+    weight= 0;
+
+    if (string)
+    {
+      memcpy(buffer, begin_ptr, (size_t) (string - begin_ptr));
+      buffer[(unsigned int)(string - begin_ptr)]= 0;
+      begin_ptr= string+1;
+    }
+    else
+    {
+      size_t length= strlen(begin_ptr);
+      memcpy(buffer, begin_ptr, length);
+      buffer[length]= 0;
+      begin_ptr= end_ptr;
+    }
+
+    ptr= index(buffer, ':');
+
+    if (ptr)
+    {
+      ptr[0]= 0;
+
+      ptr++;
+
+      port= (uint32_t) strtoul(ptr, (char **)NULL, 10);
+
+      ptr2= index(ptr, ' ');
+      if (! ptr2)
+        ptr2= index(ptr, ':');
+      if (ptr2)
+      {
+        ptr2++;
+        weight = (uint32_t) strtoul(ptr2, (char **)NULL, 10);
+      }
+    }
+
+    servers= memcached_server_list_append_with_weight(servers, buffer, port, weight, &rc);
+
+    if (isspace(*begin_ptr))
+      begin_ptr++;
+  }
+
+  return servers;
+}
diff --git a/libmemcached/pool.h b/libmemcached/pool.h
new file mode 100644 (file)
index 0000000..84dab3d
--- /dev/null
@@ -0,0 +1,51 @@
+/* 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: Connection pool implementation for libmemcached.
+ *
+ */
+
+
+#ifndef MEMCACHED_POOL_H
+#define MEMCACHED_POOL_H
+
+#include <libmemcached/memcached.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct memcached_pool_st;
+typedef struct memcached_pool_st memcached_pool_st;
+
+LIBMEMCACHED_API
+memcached_pool_st *memcached_pool_create(memcached_st* mmc, uint32_t initial, 
+                                         uint32_t max);
+LIBMEMCACHED_API
+memcached_st* memcached_pool_destroy(memcached_pool_st* pool);
+LIBMEMCACHED_API
+memcached_st* memcached_pool_pop(memcached_pool_st* pool,
+                                 bool block,
+                                 memcached_return_t* rc);
+LIBMEMCACHED_API
+memcached_return_t memcached_pool_push(memcached_pool_st* pool, 
+                                     memcached_st* mmc);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_pool_behavior_set(memcached_pool_st *ptr,
+                                               memcached_behavior_t flag,
+                                               uint64_t data);
+LIBMEMCACHED_API
+memcached_return_t memcached_pool_behavior_get(memcached_pool_st *ptr,
+                                               memcached_behavior_t flag,
+                                               uint64_t *value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MEMCACHED_POOL_H */
diff --git a/libmemcached/purge.c b/libmemcached/purge.c
new file mode 100644 (file)
index 0000000..e3f857b
--- /dev/null
@@ -0,0 +1,74 @@
+#include "common.h"
+
+memcached_return_t memcached_purge(memcached_server_st *ptr)
+{
+  uint32_t x;
+  memcached_return_t ret= MEMCACHED_SUCCESS;
+
+  if (ptr->root->options.is_purging || /* already purging */
+      (memcached_server_response_count(ptr) < ptr->root->io_msg_watermark &&
+       ptr->io_bytes_sent < ptr->root->io_bytes_watermark) ||
+      (ptr->io_bytes_sent >= ptr->root->io_bytes_watermark &&
+       memcached_server_response_count(ptr) < 2))
+  {
+    return MEMCACHED_SUCCESS;
+  }
+
+  /* memcached_io_write and memcached_response may call memcached_purge
+    so we need to be able stop any recursion.. */
+  ptr->root->options.is_purging= true;
+
+  WATCHPOINT_ASSERT(ptr->fd != -1);
+  /* Force a flush of the buffer to ensure that we don't have the n-1 pending
+    requests buffered up.. */
+  if (memcached_io_write(ptr, NULL, 0, 1) == -1)
+  {
+    ptr->root->options.is_purging= true;
+    return MEMCACHED_WRITE_FAILURE;
+  }
+  WATCHPOINT_ASSERT(ptr->fd != -1);
+
+  uint32_t no_msg= memcached_server_response_count(ptr) - 1;
+  if (no_msg > 0)
+  {
+    memcached_result_st result;
+    memcached_result_st *result_ptr;
+    char buffer[SMALL_STRING_LEN];
+
+    /*
+     * We need to increase the timeout, because we might be waiting for
+     * data to be sent from the server (the commands was in the output buffer
+     * and just flushed
+   */
+    int32_t timeo= ptr->root->poll_timeout;
+    ptr->root->poll_timeout= 2000;
+
+    result_ptr= memcached_result_create(ptr->root, &result);
+    WATCHPOINT_ASSERT(result_ptr);
+
+    for (x= 0; x < no_msg; x++)
+    {
+      memcached_result_reset(result_ptr);
+      memcached_return_t rc= memcached_read_one_response(ptr, buffer,
+                                                         sizeof (buffer),
+                                                         result_ptr);
+      /*
+       * Purge doesn't care for what kind of command results that is received.
+       * The only kind of errors I care about if is I'm out of sync with the
+       * protocol or have problems reading data from the network..
+     */
+      if (rc== MEMCACHED_PROTOCOL_ERROR || rc == MEMCACHED_UNKNOWN_READ_FAILURE)
+      {
+        WATCHPOINT_ERROR(rc);
+        ret = rc;
+        memcached_io_reset(ptr);
+      }
+    }
+
+    memcached_result_free(result_ptr);
+    ptr->root->poll_timeout= timeo;
+  }
+  ptr->root->options.is_purging= false;
+
+  return ret;
+}
diff --git a/libmemcached/quit.c b/libmemcached/quit.c
new file mode 100644 (file)
index 0000000..3c117ad
--- /dev/null
@@ -0,0 +1,77 @@
+#include "common.h"
+
+/*
+  This closes all connections (forces flush of input as well).
+
+  Maybe add a host specific, or key specific version?
+
+  The reason we send "quit" is that in case we have buffered IO, this
+  will force data to be completed.
+*/
+
+void memcached_quit_server(memcached_server_st *ptr, uint8_t io_death)
+{
+  if (ptr->fd != -1)
+  {
+    if (io_death == 0 && ptr->type != MEMCACHED_CONNECTION_UDP)
+    {
+      memcached_return_t rc;
+      char buffer[MEMCACHED_MAX_BUFFER];
+
+      if (ptr->root->flags.binary_protocol)
+      {
+        protocol_binary_request_quit request = {.bytes= {0}};
+        request.message.header.request.magic = PROTOCOL_BINARY_REQ;
+        request.message.header.request.opcode = PROTOCOL_BINARY_CMD_QUIT;
+        request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
+        rc= memcached_do(ptr, request.bytes, sizeof(request.bytes), 1);
+      }
+      else
+        rc= memcached_do(ptr, "quit\r\n", 6, 1);
+
+      WATCHPOINT_ASSERT(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_FETCH_NOTFINISHED);
+
+      /* read until socket is closed, or there is an error
+       * closing the socket before all data is read
+       * results in server throwing away all data which is
+       * not read
+       */
+      ssize_t nread;
+      while (memcached_io_read(ptr, buffer, sizeof(buffer)/sizeof(*buffer),
+                               &nread) == MEMCACHED_SUCCESS);
+
+      /*
+       * memcached_io_read may call memcached_quit_server with io_death if
+       * it encounters problems, but we don't care about those occurences.
+       * The intention of that loop is to drain the data sent from the
+       * server to ensure that the server processed all of the data we
+       * sent to the server.
+       */
+      ptr->server_failure_counter= 0;
+    }
+    memcached_io_close(ptr);
+
+    ptr->fd= -1;
+    ptr->write_buffer_offset= (size_t) ((ptr->type == MEMCACHED_CONNECTION_UDP) ? UDP_DATAGRAM_HEADER_LENGTH : 0);
+    ptr->read_buffer_length= 0;
+    ptr->read_ptr= ptr->read_buffer;
+    memcached_server_response_reset(ptr);
+  }
+
+  if(io_death) ptr->server_failure_counter++;
+}
+
+void memcached_quit(memcached_st *ptr)
+{
+  unsigned int x;
+
+  if (ptr->hosts == NULL ||
+      ptr->number_of_hosts == 0)
+    return;
+
+  if (ptr->hosts && ptr->number_of_hosts)
+  {
+    for (x= 0; x < ptr->number_of_hosts; x++)
+      memcached_quit_server(&ptr->hosts[x], 0);
+  }
+}
diff --git a/libmemcached/response.c b/libmemcached/response.c
new file mode 100644 (file)
index 0000000..a87ac24
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+  Memcached library
+
+  memcached_response() is used to determine the return result
+  from an issued command.
+*/
+
+#include "common.h"
+
+static memcached_return_t textual_read_one_response(memcached_server_st *ptr,
+                                                  char *buffer, size_t buffer_length,
+                                                  memcached_result_st *result);
+static memcached_return_t binary_read_one_response(memcached_server_st *ptr,
+                                                 char *buffer, size_t buffer_length,
+                                                 memcached_result_st *result);
+
+memcached_return_t memcached_read_one_response(memcached_server_st *ptr,
+                                             char *buffer, size_t buffer_length,
+                                             memcached_result_st *result)
+{
+  memcached_server_response_decrement(ptr);
+
+  if (result == NULL)
+    result = &ptr->root->result;
+
+  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 ||
+           rc == MEMCACHED_PROTOCOL_ERROR ||
+           rc == MEMCACHED_CLIENT_ERROR ||
+           rc == MEMCACHED_MEMORY_ALLOCATION_FAILURE)
+     memcached_io_reset(ptr);
+
+  return rc;
+}
+
+memcached_return_t memcached_response(memcached_server_st *ptr, 
+                                    char *buffer, size_t buffer_length,
+                                    memcached_result_st *result)
+{
+  /* We may have old commands in the buffer not set, first purge */
+  if (ptr->root->flags.no_block)
+    (void)memcached_io_write(ptr, NULL, 0, 1);
+
+  /*
+   * The previous implementation purged all pending requests and just
+   * returned the last one. Purge all pending messages to ensure backwards
+   * compatibility. 
+   */
+  if (ptr->root->flags.binary_protocol == false)
+    while (memcached_server_response_count(ptr) > 1)
+    {
+      memcached_return_t rc= memcached_read_one_response(ptr, buffer, buffer_length, result);
+      
+      unlikely (rc != MEMCACHED_END &&
+                rc != MEMCACHED_STORED &&
+                rc != MEMCACHED_SUCCESS &&
+                rc != MEMCACHED_STAT && 
+                rc != MEMCACHED_DELETED &&
+                rc != MEMCACHED_NOTFOUND &&
+                rc != MEMCACHED_NOTSTORED && 
+                rc != MEMCACHED_DATA_EXISTS)
+       return rc;
+    }
+
+  return memcached_read_one_response(ptr, buffer, buffer_length, result);
+}
+
+static memcached_return_t textual_value_fetch(memcached_server_st *ptr,
+                                            char *buffer,
+                                            memcached_result_st *result)
+{
+  memcached_return_t rc= MEMCACHED_SUCCESS;
+  char *string_ptr;
+  char *end_ptr;
+  char *next_ptr;
+  size_t value_length;
+  size_t to_read;
+  char *value_ptr;
+
+  if (ptr->root->flags.use_udp)
+    return MEMCACHED_NOT_SUPPORTED;
+
+  WATCHPOINT_ASSERT(ptr->root);
+  end_ptr= buffer + MEMCACHED_DEFAULT_COMMAND_SIZE;
+
+  memcached_result_reset(result);
+
+  string_ptr= buffer;
+  string_ptr+= 6; /* "VALUE " */
+
+
+  /* We load the key */
+  {
+    char *key;
+    size_t prefix_length;
+
+    key= result->key;
+    result->key_length= 0;
+
+    for (prefix_length= ptr->root->prefix_key_length; !(iscntrl(*string_ptr) || isspace(*string_ptr)) ; string_ptr++)
+    {
+      if (prefix_length == 0)
+      {
+        *key= *string_ptr;
+        key++;
+        result->key_length++;
+      }
+      else
+        prefix_length--;
+    }
+    result->key[result->key_length]= 0;
+  }
+
+  if (end_ptr == string_ptr)
+    goto read_error;
+
+  /* Flags fetch move past space */
+  string_ptr++;
+  if (end_ptr == string_ptr)
+    goto read_error;
+  for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
+  result->flags= (uint32_t) strtoul(next_ptr, &string_ptr, 10);
+
+  if (end_ptr == string_ptr)
+    goto read_error;
+
+  /* Length fetch move past space*/
+  string_ptr++;
+  if (end_ptr == string_ptr)
+    goto read_error;
+
+  for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
+  value_length= (size_t)strtoull(next_ptr, &string_ptr, 10);
+
+  if (end_ptr == string_ptr)
+    goto read_error;
+
+  /* Skip spaces */
+  if (*string_ptr == '\r')
+  {
+    /* Skip past the \r\n */
+    string_ptr+= 2;
+  }
+  else
+  {
+    string_ptr++;
+    for (next_ptr= string_ptr; isdigit(*string_ptr); string_ptr++);
+    result->cas= strtoull(next_ptr, &string_ptr, 10);
+  }
+
+  if (end_ptr < string_ptr)
+    goto read_error;
+
+  /* We add two bytes so that we can walk the \r\n */
+  rc= memcached_string_check(&result->value, value_length+2);
+  if (rc != MEMCACHED_SUCCESS)
+  {
+    value_length= 0;
+    return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+  }
+
+  value_ptr= memcached_string_value(&result->value);
+  /* 
+    We read the \r\n into the string since not doing so is more 
+    cycles then the waster of memory to do so.
+
+    We are null terminating through, which will most likely make
+    some people lazy about using the return length.
+  */
+  to_read= (value_length) + 2;
+  ssize_t read_length= 0;
+  memcached_return_t rrc= memcached_io_read(ptr, value_ptr, to_read, &read_length);
+  if (rrc != MEMCACHED_SUCCESS)
+    return rrc;
+
+  if (read_length != (ssize_t)(value_length + 2))
+  {
+    goto read_error;
+  }
+
+/* This next bit blows the API, but this is internal....*/
+  {
+    char *char_ptr;
+    char_ptr= memcached_string_value(&result->value);;
+    char_ptr[value_length]= 0;
+    char_ptr[value_length + 1]= 0;
+    memcached_string_set_length(&result->value, value_length);
+  }
+
+  return MEMCACHED_SUCCESS;
+
+read_error:
+  memcached_io_reset(ptr);
+
+  return MEMCACHED_PARTIAL_READ;
+}
+
+static memcached_return_t textual_read_one_response(memcached_server_st *ptr,
+                                                  char *buffer, size_t buffer_length,
+                                                  memcached_result_st *result)
+{
+  memcached_return_t rc= memcached_io_readline(ptr, buffer, buffer_length);
+  if (rc != MEMCACHED_SUCCESS)
+    return rc;
+
+  switch(buffer[0])
+  {
+  case 'V': /* VALUE || VERSION */
+    if (buffer[1] == 'A') /* VALUE */
+    {
+      /* We add back in one because we will need to search for END */
+      memcached_server_response_increment(ptr);
+      return textual_value_fetch(ptr, buffer, result);
+    }
+    else if (buffer[1] == 'E') /* VERSION */
+    {
+      return MEMCACHED_SUCCESS;
+    }
+    else
+    {
+      WATCHPOINT_STRING(buffer);
+      WATCHPOINT_ASSERT(0);
+      return MEMCACHED_UNKNOWN_READ_FAILURE;
+    }
+  case 'O': /* OK */
+    return MEMCACHED_SUCCESS;
+  case 'S': /* STORED STATS SERVER_ERROR */
+    {
+      if (buffer[2] == 'A') /* STORED STATS */
+      {
+        memcached_server_response_increment(ptr);
+        return MEMCACHED_STAT;
+      }
+      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 *)ptr->root->call_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;
+       }
+      else if (buffer[1] == 'T')
+        return MEMCACHED_STORED;
+      else
+      {
+        WATCHPOINT_STRING(buffer);
+        WATCHPOINT_ASSERT(0);
+        return MEMCACHED_UNKNOWN_READ_FAILURE;
+      }
+    }
+  case 'D': /* DELETED */
+    return MEMCACHED_DELETED;
+  case 'N': /* NOT_FOUND */
+    {
+      if (buffer[4] == 'F')
+        return MEMCACHED_NOTFOUND;
+      else if (buffer[4] == 'S')
+        return MEMCACHED_NOTSTORED;
+      else
+        return MEMCACHED_UNKNOWN_READ_FAILURE;
+    }
+  case 'E': /* PROTOCOL ERROR or END */
+    {
+      if (buffer[1] == 'N')
+        return MEMCACHED_END;
+      else if (buffer[1] == 'R')
+        return MEMCACHED_PROTOCOL_ERROR;
+      else if (buffer[1] == 'X')
+        return MEMCACHED_DATA_EXISTS;
+      else
+        return MEMCACHED_UNKNOWN_READ_FAILURE;
+    }
+  case 'I': /* CLIENT ERROR */
+      /* We add back in one because we will need to search for END */
+      memcached_server_response_increment(ptr);
+    return MEMCACHED_ITEM;
+  case 'C': /* CLIENT ERROR */
+    return MEMCACHED_CLIENT_ERROR;
+  default:
+    {
+      unsigned long long auto_return_value;
+
+      if (sscanf(buffer, "%llu", &auto_return_value) == 1)
+        return MEMCACHED_SUCCESS;
+
+      return MEMCACHED_UNKNOWN_READ_FAILURE;
+    }
+  }
+
+  /* NOTREACHED */
+}
+
+char *memcached_result_value(memcached_result_st *ptr)
+{
+  memcached_string_st *sptr= &ptr->value;
+  return memcached_string_value(sptr);
+}
+
+size_t memcached_result_length(memcached_result_st *ptr)
+{
+  memcached_string_st *sptr= &ptr->value;
+  return memcached_string_length(sptr);
+}
+
+static memcached_return_t binary_read_one_response(memcached_server_st *ptr,
+                                                 char *buffer, size_t buffer_length,
+                                                 memcached_result_st *result)
+{
+  protocol_binary_response_header header;
+   
+  unlikely (memcached_safe_read(ptr, &header.bytes, 
+                                sizeof(header.bytes)) != MEMCACHED_SUCCESS)
+    return MEMCACHED_UNKNOWN_READ_FAILURE;
+
+  unlikely (header.response.magic != PROTOCOL_BINARY_RES) 
+    return MEMCACHED_PROTOCOL_ERROR;
+
+  /*
+  ** Convert the header to host local endian!
+  */
+  header.response.keylen= ntohs(header.response.keylen);
+  header.response.status= ntohs(header.response.status);
+  header.response.bodylen= ntohl(header.response.bodylen);
+  header.response.cas= ntohll(header.response.cas);
+  uint32_t bodylen= header.response.bodylen;
+
+  if (header.response.status == 0) 
+  {
+    switch (header.response.opcode)
+    {
+    case PROTOCOL_BINARY_CMD_GETKQ:
+      /*
+       * We didn't increment the response counter for the GETKQ packet
+       * (only the final NOOP), so we need to increment the counter again.
+       */ 
+      memcached_server_response_increment(ptr); 
+      /* FALLTHROUGH */
+    case PROTOCOL_BINARY_CMD_GETK:
+      {
+        uint16_t keylen= header.response.keylen;
+        memcached_result_reset(result);
+        result->cas= header.response.cas;
+
+        if (memcached_safe_read(ptr, &result->flags,
+                                sizeof (result->flags)) != MEMCACHED_SUCCESS)
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+
+        result->flags= ntohl(result->flags);
+        bodylen -= header.response.extlen;
+
+        result->key_length= keylen;
+        if (memcached_safe_read(ptr, result->key, keylen) != MEMCACHED_SUCCESS) 
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+
+        bodylen -= keylen;
+        if (memcached_string_check(&result->value,
+                                   bodylen) != MEMCACHED_SUCCESS) 
+          return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+
+        char *vptr= memcached_string_value(&result->value);
+        if (memcached_safe_read(ptr, vptr, bodylen) != MEMCACHED_SUCCESS) 
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+
+        memcached_string_set_length(&result->value, bodylen);  
+      } 
+      break;
+    case PROTOCOL_BINARY_CMD_INCREMENT:
+    case PROTOCOL_BINARY_CMD_DECREMENT:
+      {
+        if (bodylen != sizeof(uint64_t) || buffer_length != sizeof(uint64_t)) 
+          return MEMCACHED_PROTOCOL_ERROR;
+
+        WATCHPOINT_ASSERT(bodylen == buffer_length);
+        uint64_t val;
+        if (memcached_safe_read(ptr, &val, sizeof(val)) != MEMCACHED_SUCCESS) 
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+
+        val= ntohll(val);
+        memcpy(buffer, &val, sizeof(val));
+      } 
+      break;
+    case PROTOCOL_BINARY_CMD_VERSION:
+      {
+        memset(buffer, 0, buffer_length);
+        if (bodylen >= buffer_length)
+          /* not enough space in buffer.. should not happen... */
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+        else if (memcached_safe_read(ptr, buffer, bodylen) != MEMCACHED_SUCCESS)
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+      } 
+      break;
+    case PROTOCOL_BINARY_CMD_FLUSH:
+    case PROTOCOL_BINARY_CMD_QUIT:
+    case PROTOCOL_BINARY_CMD_SET:
+    case PROTOCOL_BINARY_CMD_ADD:
+    case PROTOCOL_BINARY_CMD_REPLACE:
+    case PROTOCOL_BINARY_CMD_APPEND:
+    case PROTOCOL_BINARY_CMD_PREPEND:
+    case PROTOCOL_BINARY_CMD_DELETE:
+      {
+        WATCHPOINT_ASSERT(bodylen == 0);
+        return MEMCACHED_SUCCESS;
+      } 
+    case PROTOCOL_BINARY_CMD_NOOP:
+      {
+        WATCHPOINT_ASSERT(bodylen == 0);
+        return MEMCACHED_END;
+      }
+    case PROTOCOL_BINARY_CMD_STAT:
+      {
+        if (bodylen == 0)
+          return MEMCACHED_END;
+        else if (bodylen + 1 > buffer_length)
+          /* not enough space in buffer.. should not happen... */
+          return MEMCACHED_UNKNOWN_READ_FAILURE;
+        else 
+        {
+          size_t keylen= header.response.keylen;            
+          memset(buffer, 0, buffer_length);
+          if (memcached_safe_read(ptr, buffer, keylen) != MEMCACHED_SUCCESS ||
+              memcached_safe_read(ptr, buffer + keylen + 1, 
+                                  bodylen - keylen) != MEMCACHED_SUCCESS)
+            return MEMCACHED_UNKNOWN_READ_FAILURE;
+        }
+      } 
+      break;
+    default:
+      {
+        /* Command not implemented yet! */
+        WATCHPOINT_ASSERT(0);
+        return MEMCACHED_PROTOCOL_ERROR;
+      }        
+    }
+  } 
+  else if (header.response.bodylen) 
+  {
+     /* What should I do with the error message??? just discard it for now */
+    char hole[SMALL_STRING_LEN];
+    while (bodylen > 0) 
+    {
+      size_t nr= (bodylen > SMALL_STRING_LEN) ? SMALL_STRING_LEN : bodylen;
+      if (memcached_safe_read(ptr, hole, nr) != MEMCACHED_SUCCESS)
+        return MEMCACHED_UNKNOWN_READ_FAILURE;
+      bodylen-= (uint32_t) nr;
+    }
+
+    /* This might be an error from one of the quiet commands.. if
+     * so, just throw it away and get the next one. What about creating
+     * a callback to the user with the error information?
+     */
+    switch (header.response.opcode)
+    {
+    case PROTOCOL_BINARY_CMD_SETQ:
+    case PROTOCOL_BINARY_CMD_ADDQ:
+    case PROTOCOL_BINARY_CMD_REPLACEQ:
+    case PROTOCOL_BINARY_CMD_APPENDQ:
+    case PROTOCOL_BINARY_CMD_PREPENDQ:
+      return binary_read_one_response(ptr, buffer, buffer_length, result);
+    default:
+      break;
+    }
+  }
+
+  memcached_return_t rc= MEMCACHED_SUCCESS;
+  unlikely(header.response.status != 0) 
+    switch (header.response.status) 
+    {
+    case PROTOCOL_BINARY_RESPONSE_KEY_ENOENT:
+      rc= MEMCACHED_NOTFOUND;
+      break;
+    case PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS:
+      rc= MEMCACHED_DATA_EXISTS;
+      break;
+    case PROTOCOL_BINARY_RESPONSE_NOT_STORED:
+      rc= MEMCACHED_NOTSTORED;
+      break;
+    case PROTOCOL_BINARY_RESPONSE_E2BIG:
+      rc= MEMCACHED_E2BIG;
+      break;
+    case PROTOCOL_BINARY_RESPONSE_ENOMEM:
+      rc= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+      break;
+    case PROTOCOL_BINARY_RESPONSE_EINVAL:
+    case PROTOCOL_BINARY_RESPONSE_UNKNOWN_COMMAND:
+    default:
+      /* @todo fix the error mappings */
+      rc= MEMCACHED_PROTOCOL_ERROR;
+      break;
+    }
+    
+  return rc;
+}
diff --git a/libmemcached/result.c b/libmemcached/result.c
new file mode 100644 (file)
index 0000000..14a0774
--- /dev/null
@@ -0,0 +1,81 @@
+/* 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: Functions to manipulate the result structure.
+ *
+ */
+
+/* 
+  memcached_result_st are used to internally represent the return values from
+  memcached. We use a structure so that long term as identifiers are added 
+  to memcached we will be able to absorb new attributes without having 
+  to addjust the entire API.
+*/
+#include "common.h"
+
+memcached_result_st *memcached_result_create(memcached_st *memc, 
+                                             memcached_result_st *ptr)
+{
+  WATCHPOINT_ASSERT(memc && memc->options.is_initialized);
+
+  /* Saving malloc calls :) */
+  if (ptr)
+  {
+    memset(ptr, 0, sizeof(memcached_result_st));
+  }
+  else
+  {
+    ptr= memc->call_malloc(memc, sizeof(memcached_result_st));
+
+    if (ptr == NULL)
+      return NULL;
+    ptr->options.is_allocated= true;
+  }
+
+  ptr->options.is_initialized= true;
+
+  ptr->root= memc;
+  memcached_string_create(memc, &ptr->value, 0);
+  WATCHPOINT_ASSERT_INITIALIZED(&ptr->value);
+  WATCHPOINT_ASSERT(ptr->value.string == NULL);
+
+  return ptr;
+}
+
+void memcached_result_reset(memcached_result_st *ptr)
+{
+  ptr->key_length= 0;
+  memcached_string_reset(&ptr->value);
+  ptr->flags= 0;
+  ptr->cas= 0;
+  ptr->expiration= 0;
+}
+
+/*
+  NOTE turn into macro
+*/
+memcached_return_t memcached_result_set_value(memcached_result_st *ptr, const char *value, size_t length)
+{
+  return memcached_string_append(&ptr->value, value, length);
+}
+
+void memcached_result_free(memcached_result_st *ptr)
+{
+  if (ptr == NULL)
+    return;
+
+  memcached_string_free(&ptr->value);
+
+  if (memcached_is_allocated(ptr))
+  {
+    free(ptr);
+  }
+  else
+  {
+    ptr->options.is_initialized= false;
+  }
+}
diff --git a/libmemcached/result.h b/libmemcached/result.h
new file mode 100644 (file)
index 0000000..4b0c12e
--- /dev/null
@@ -0,0 +1,65 @@
+/* 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: Functions to manipulate the result structure.
+ *
+ */
+
+#ifndef __MEMCACHED_RESULT_H__
+#define __MEMCACHED_RESULT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct memcached_result_st {
+  struct {
+    bool is_allocated:1;
+    bool is_initialized:1;
+  } options;
+  uint32_t flags;
+  time_t expiration;
+  memcached_st *root;
+  size_t key_length;
+  uint64_t cas;
+  memcached_string_st value;
+  char key[MEMCACHED_MAX_KEY];
+  /* Add result callback function */
+};
+
+/* Result Struct */
+LIBMEMCACHED_API
+void memcached_result_free(memcached_result_st *result);
+LIBMEMCACHED_API
+void memcached_result_reset(memcached_result_st *ptr);
+LIBMEMCACHED_API
+memcached_result_st *memcached_result_create(memcached_st *ptr, 
+                                             memcached_result_st *result);
+#define memcached_result_key_value(A) (A)->key
+#define memcached_result_key_length(A) (A)->key_length
+#define memcached_result_string_st(A) ((A)->value)
+#ifdef FIX
+#define memcached_result_value(A) memcached_string_value((A)->value)
+#define memcached_result_length(A) memcached_string_length((A)->value)
+#else
+LIBMEMCACHED_API
+char *memcached_result_value(memcached_result_st *ptr);
+LIBMEMCACHED_API
+size_t memcached_result_length(memcached_result_st *ptr);
+#endif
+#define memcached_result_flags(A) (A)->flags
+#define memcached_result_cas(A) (A)->cas
+LIBMEMCACHED_API
+memcached_return_t memcached_result_set_value(memcached_result_st *ptr, const char *value, size_t length);
+#define memcached_result_set_flags(A,B) (A)->flags=(B)
+#define memcached_result_set_expiration(A,B) (A)->expiration=(B)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MEMCACHED_RESULT_H__ */
diff --git a/libmemcached/server.c b/libmemcached/server.c
new file mode 100644 (file)
index 0000000..2cff36d
--- /dev/null
@@ -0,0 +1,179 @@
+/* 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: String structure used for libmemcached.
+ *
+ */
+
+/*
+  This is a partial implementation for fetching/creating memcached_server_st objects.
+*/
+#include "common.h"
+
+memcached_server_st *memcached_server_create(memcached_st *memc, memcached_server_st *ptr)
+{
+  if (ptr == NULL)
+  {
+    ptr= (memcached_server_st *)calloc(1, sizeof(memcached_server_st));
+
+    if (!ptr)
+      return NULL; /*  MEMCACHED_MEMORY_ALLOCATION_FAILURE */
+
+    ptr->options.is_allocated= true;
+  }
+  else
+  {
+    memset(ptr, 0, sizeof(memcached_server_st));
+  }
+
+  ptr->root= memc;
+
+  return ptr;
+}
+
+memcached_server_st *memcached_server_create_with(memcached_st *memc, memcached_server_st *host,
+                                                  const char *hostname, in_port_t port,
+                                                  uint32_t weight, memcached_connection_t type)
+{
+  host= memcached_server_create(memc, host);
+
+  if (host == NULL)
+    return NULL;
+
+  strncpy(host->hostname, hostname, MEMCACHED_MAX_HOST_LENGTH - 1);
+  host->root= memc ? memc : NULL;
+  host->port= port;
+  host->weight= weight;
+  host->fd= -1;
+  host->type= type;
+  host->read_ptr= host->read_buffer;
+  if (memc)
+    host->next_retry= memc->retry_timeout;
+  if (type == MEMCACHED_CONNECTION_UDP)
+  {
+    host->write_buffer_offset= UDP_DATAGRAM_HEADER_LENGTH;
+    memcached_io_init_udp_header(host, 0);
+  }
+
+  return host;
+}
+
+void memcached_server_free(memcached_server_st *ptr)
+{
+  memcached_quit_server(ptr, 0);
+
+  if (ptr->cached_server_error)
+    free(ptr->cached_server_error);
+
+  if (ptr->address_info)
+    freeaddrinfo(ptr->address_info);
+
+
+  if (memcached_is_allocated(ptr))
+  {
+    ptr->root->call_free(ptr->root, ptr);
+  }
+  else
+  {
+    memset(ptr, 0, sizeof(memcached_server_st));
+  }
+}
+
+/*
+  If we do not have a valid object to clone from, we toss an error.
+*/
+memcached_server_st *memcached_server_clone(memcached_server_st *clone, memcached_server_st *ptr)
+{
+  memcached_server_st *rv= NULL;
+
+  /* We just do a normal create if ptr is missing */
+  if (ptr == NULL)
+    return NULL;
+
+  rv = memcached_server_create_with(ptr->root, clone,
+                                    ptr->hostname, ptr->port, ptr->weight,
+                                    ptr->type);
+  if (rv != NULL)
+  {
+    rv->cached_errno= ptr->cached_errno;
+    if (ptr->cached_server_error)
+      rv->cached_server_error= strdup(ptr->cached_server_error);
+  }
+
+  return rv;
+
+}
+
+memcached_return_t memcached_server_cursor(memcached_st *ptr,
+                                           memcached_server_fn *callback,
+                                           void *context,
+                                           uint32_t number_of_callbacks)
+{
+  unsigned int y;
+
+  for (y= 0; y < ptr->number_of_hosts; y++)
+  {
+    unsigned int x;
+
+    for (x= 0; x < number_of_callbacks; x++)
+    {
+      unsigned int iferror;
+
+      iferror= (*callback[x])(ptr, &ptr->hosts[y], context);
+
+      if (iferror)
+        continue;
+    }
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_server_st *memcached_server_by_key(memcached_st *ptr,  const char *key, size_t key_length, memcached_return_t *error)
+{
+  uint32_t server_key;
+
+  *error= memcached_validate_key_length(key_length,
+                                        ptr->flags.binary_protocol);
+  unlikely (*error != MEMCACHED_SUCCESS)
+    return NULL;
+
+  unlikely (ptr->number_of_hosts == 0)
+  {
+    *error= MEMCACHED_NO_SERVERS;
+    return NULL;
+  }
+
+  if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
+  {
+    *error= MEMCACHED_BAD_KEY_PROVIDED;
+    return NULL;
+  }
+
+  server_key= memcached_generate_hash(ptr, key, key_length);
+
+  return memcached_server_clone(NULL, &ptr->hosts[server_key]);
+
+}
+
+const char *memcached_server_error(memcached_server_st *ptr)
+{
+  if (ptr)
+    return ptr->cached_server_error;
+  else
+    return NULL;
+}
+
+void memcached_server_error_reset(memcached_server_st *ptr)
+{
+  ptr->cached_server_error[0]= 0;
+}
+
+memcached_server_st *memcached_server_get_last_disconnect(memcached_st *ptr)
+{
+  return ptr->last_disconnected_server;
+}
diff --git a/libmemcached/server.h b/libmemcached/server.h
new file mode 100644 (file)
index 0000000..f2d92dc
--- /dev/null
@@ -0,0 +1,101 @@
+/* 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: String structure used for libmemcached.
+ *
+ */
+
+#ifndef __MEMCACHED_SERVER_H__
+#define __MEMCACHED_SERVER_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct memcached_server_st {
+  struct {
+    bool is_allocated:1;
+  } options;
+  bool sockaddr_inited;
+  uint16_t count;
+  uint32_t cursor_active;
+  in_port_t port;
+  int cached_errno;
+  int fd;
+  uint32_t io_bytes_sent; /* # bytes sent since last read */
+  uint32_t server_failure_counter;
+  uint32_t weight;
+  uint8_t major_version;
+  uint8_t micro_version;
+  uint8_t minor_version;
+  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;
+  struct addrinfo *address_info;
+  time_t next_retry;
+  memcached_st *root;
+  uint64_t limit_maxbytes;
+  char read_buffer[MEMCACHED_MAX_BUFFER];
+  char write_buffer[MEMCACHED_MAX_BUFFER];
+  char hostname[MEMCACHED_MAX_HOST_LENGTH];
+};
+
+#define memcached_server_count(A) (A)->number_of_hosts
+#define memcached_server_name(A,B) (B).hostname
+#define memcached_server_port(A,B) (B).port
+#define memcached_server_list(A) (A)->hosts
+#define memcached_server_response_count(A) (A)->cursor_active
+
+LIBMEMCACHED_API
+memcached_return_t memcached_server_cursor(memcached_st *ptr,
+                                           memcached_server_fn *callback,
+                                           void *context,
+                                           uint32_t number_of_callbacks);
+
+LIBMEMCACHED_API
+memcached_server_st *memcached_server_by_key(memcached_st *ptr,  const char *key,
+                                             size_t key_length, memcached_return_t *error);
+
+LIBMEMCACHED_API
+const char *memcached_server_error(memcached_server_st *ptr);
+
+LIBMEMCACHED_API
+void memcached_server_error_reset(memcached_server_st *ptr);
+
+/* These should not currently be used by end users */
+/* TODO: Is the above comment valid? If so, how can we unit test these if they
+ * aren't exported. If not, we should remove the comment */
+LIBMEMCACHED_API
+memcached_server_st *memcached_server_create(memcached_st *memc, memcached_server_st *ptr);
+
+LIBMEMCACHED_API
+memcached_server_st *memcached_server_create_with(memcached_st *memc, memcached_server_st *host,
+                                                  const char *hostname, in_port_t port,
+                                                  uint32_t weight, memcached_connection_t type);
+
+LIBMEMCACHED_API
+void memcached_server_free(memcached_server_st *ptr);
+LIBMEMCACHED_API
+memcached_server_st *memcached_server_clone(memcached_server_st *clone, memcached_server_st *ptr);
+LIBMEMCACHED_API
+memcached_analysis_st *memcached_analyze(memcached_st *memc, memcached_stat_st *memc_stat,
+                                         memcached_return_t *error);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_server_remove(memcached_server_st *st_ptr);
+
+LIBMEMCACHED_API
+memcached_server_st *memcached_server_get_last_disconnect(memcached_st *ptr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MEMCACHED_SERVER_H__ */
diff --git a/libmemcached/stats.c b/libmemcached/stats.c
new file mode 100644 (file)
index 0000000..e5f9a20
--- /dev/null
@@ -0,0 +1,456 @@
+/*
+*/
+
+#include "common.h"
+
+static const char *memcached_stat_keys[] = {
+  "pid",
+  "uptime",
+  "time",
+  "version",
+  "pointer_size",
+  "rusage_user",
+  "rusage_system",
+  "curr_items",
+  "total_items",
+  "bytes",
+  "curr_connections",
+  "total_connections",
+  "connection_structures",
+  "cmd_get",
+  "cmd_set",
+  "get_hits",
+  "get_misses",
+  "evictions",
+  "bytes_read",
+  "bytes_written",
+  "limit_maxbytes",
+  "threads",
+  NULL
+};
+
+
+static memcached_return_t set_data(memcached_stat_st *memc_stat, char *key, char *value)
+{
+
+  if (strlen(key) < 1) 
+  {
+    WATCHPOINT_STRING(key);
+    return MEMCACHED_UNKNOWN_STAT_KEY;
+  }
+  else if (!strcmp("pid", key))
+  {
+    memc_stat->pid= (uint32_t) strtol(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("uptime", key))
+  {
+    memc_stat->uptime= (uint32_t) strtol(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("time", key))
+  {
+    memc_stat->time= (uint32_t) strtol(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("version", key))
+  {
+    memcpy(memc_stat->version, value, strlen(value));
+    memc_stat->version[strlen(value)]= 0;
+  }
+  else if (!strcmp("pointer_size", key))
+  {
+    memc_stat->pointer_size= (uint32_t) strtol(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("rusage_user", key))
+  {
+    char *walk_ptr;
+    for (walk_ptr= value; (!ispunct(*walk_ptr)); walk_ptr++);
+    *walk_ptr= 0;
+    walk_ptr++;
+    memc_stat->rusage_user_seconds= (uint32_t) strtol(value, (char **)NULL, 10);
+    memc_stat->rusage_user_microseconds= (uint32_t) strtol(walk_ptr, (char **)NULL, 10);
+  }
+  else if (!strcmp("rusage_system", key))
+  {
+    char *walk_ptr;
+    for (walk_ptr= value; (!ispunct(*walk_ptr)); walk_ptr++);
+    *walk_ptr= 0;
+    walk_ptr++;
+    memc_stat->rusage_system_seconds= (uint32_t) strtol(value, (char **)NULL, 10);
+    memc_stat->rusage_system_microseconds= (uint32_t) strtol(walk_ptr, (char **)NULL, 10);
+  }
+  else if (!strcmp("curr_items", key))
+  {
+    memc_stat->curr_items= (uint32_t) strtol(value, (char **)NULL, 10); 
+  }
+  else if (!strcmp("total_items", key))
+  {
+    memc_stat->total_items= (uint32_t) strtol(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("bytes_read", key))
+  {
+    memc_stat->bytes_read= (uint32_t) strtoll(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("bytes_written", key))
+  {
+    memc_stat->bytes_written= (uint32_t) strtoll(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("bytes", key))
+  {
+    memc_stat->bytes= (uint32_t) strtoll(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("curr_connections", key))
+  {
+    memc_stat->curr_connections= (uint32_t) strtoll(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("total_connections", key))
+  {
+    memc_stat->total_connections= (uint32_t) strtoll(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("connection_structures", key))
+  {
+    memc_stat->connection_structures= (uint32_t) strtol(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("cmd_get", key))
+  {
+    memc_stat->cmd_get= (uint64_t) strtoll(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("cmd_set", key))
+  {
+    memc_stat->cmd_set= (uint64_t) strtoll(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("get_hits", key))
+  {
+    memc_stat->get_hits= (uint64_t) strtoll(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("get_misses", key))
+  {
+    memc_stat->get_misses= (uint64_t)strtoll(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("evictions", key))
+  {
+    memc_stat->evictions= (uint64_t)strtoll(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("limit_maxbytes", key))
+  {
+    memc_stat->limit_maxbytes= (uint64_t) strtoll(value, (char **)NULL, 10);
+  }
+  else if (!strcmp("threads", key))
+  {
+    memc_stat->threads= (uint32_t) strtol(value, (char **)NULL, 10);
+  }
+  else if (!(strcmp("delete_misses", key) == 0 ||/* New stats in the 1.3 beta */
+             strcmp("delete_hits", key) == 0 ||/* Just swallow them for now.. */
+             strcmp("incr_misses", key) == 0 ||
+             strcmp("incr_hits", key) == 0 ||
+             strcmp("decr_misses", key) == 0 ||
+             strcmp("decr_hits", key) == 0 ||
+             strcmp("cas_misses", key) == 0 ||
+             strcmp("cas_hits", key) == 0 ||
+             strcmp("cas_badval", key) == 0 ||
+             strcmp("cmd_flush", key) == 0 ||
+             strcmp("accepting_conns", key) == 0 ||
+             strcmp("listen_disabled_num", key) == 0 ||
+             strcmp("conn_yields", key) == 0))
+  {
+    WATCHPOINT_STRING(key);
+    return MEMCACHED_UNKNOWN_STAT_KEY;
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+char *memcached_stat_get_value(memcached_st *ptr, memcached_stat_st *memc_stat, 
+                               const char *key, memcached_return_t *error)
+{
+  char buffer[SMALL_STRING_LEN];
+  int length;
+  char *ret;
+
+  *error= MEMCACHED_SUCCESS;
+
+  if (!memcmp("pid", key, strlen("pid")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->pid);
+  else if (!memcmp("uptime", key, strlen("uptime")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->uptime);
+  else if (!memcmp("time", key, strlen("time")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->time);
+  else if (!memcmp("version", key, strlen("version")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%s", memc_stat->version);
+  else if (!memcmp("pointer_size", key, strlen("pointer_size")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->pointer_size);
+  else if (!memcmp("rusage_user", key, strlen("rusage_user")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%u.%u", memc_stat->rusage_user_seconds, memc_stat->rusage_user_microseconds);
+  else if (!memcmp("rusage_system", key, strlen("rusage_system")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%u.%u", memc_stat->rusage_system_seconds, memc_stat->rusage_system_microseconds);
+  else if (!memcmp("curr_items", key, strlen("curr_items")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->curr_items);
+  else if (!memcmp("total_items", key, strlen("total_items")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->total_items);
+  else if (!memcmp("curr_connections", key, strlen("curr_connections")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->curr_connections);
+  else if (!memcmp("total_connections", key, strlen("total_connections")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->total_connections);
+  else if (!memcmp("connection_structures", key, strlen("connection_structures")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->connection_structures);
+  else if (!memcmp("cmd_get", key, strlen("cmd_get")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->cmd_get);
+  else if (!memcmp("cmd_set", key, strlen("cmd_set")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->cmd_set);
+  else if (!memcmp("get_hits", key, strlen("get_hits")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->get_hits);
+  else if (!memcmp("get_misses", key, strlen("get_misses")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->get_misses);
+  else if (!memcmp("evictions", key, strlen("evictions")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->evictions);
+  else if (!memcmp("bytes_read", key, strlen("bytes_read")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes_read);
+  else if (!memcmp("bytes_written", key, strlen("bytes_written")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes_written);
+  else if (!memcmp("bytes", key, strlen("bytes")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->bytes);
+  else if (!memcmp("limit_maxbytes", key, strlen("limit_maxbytes")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%llu", (unsigned long long)memc_stat->limit_maxbytes);
+  else if (!memcmp("threads", key, strlen("threads")))
+    length= snprintf(buffer, SMALL_STRING_LEN,"%u", memc_stat->threads);
+  else
+  {
+    *error= MEMCACHED_NOTFOUND;
+    return NULL;
+  }
+
+  ret= ptr->call_malloc(ptr, (size_t) (length + 1));
+  memcpy(ret, buffer, (size_t) length);
+  ret[length]= '\0';
+
+  return ret;
+}
+
+static memcached_return_t binary_stats_fetch(memcached_st *ptr,
+                                             memcached_stat_st *memc_stat,
+                                             char *args,
+                                             unsigned int server_key)
+{
+  memcached_return_t rc;
+
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+  protocol_binary_request_stats request= {.bytes= {0}};
+  request.message.header.request.magic= PROTOCOL_BINARY_REQ;
+  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_STAT;
+  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+
+  if (args != NULL) 
+  {
+    size_t len= strlen(args);
+
+    rc= memcached_validate_key_length(len, true);
+    unlikely (rc != MEMCACHED_SUCCESS)
+      return rc;
+
+    request.message.header.request.keylen= htons((uint16_t)len);
+    request.message.header.request.bodylen= htonl((uint32_t) len);
+
+    if ((memcached_do(&ptr->hosts[server_key], request.bytes, 
+                      sizeof(request.bytes), 0) != MEMCACHED_SUCCESS) ||
+        (memcached_io_write(&ptr->hosts[server_key], args, len, 1) == -1)) 
+    {
+      memcached_io_reset(&ptr->hosts[server_key]);
+      return MEMCACHED_WRITE_FAILURE;
+    }
+  }
+  else
+  {
+    if (memcached_do(&ptr->hosts[server_key], request.bytes, 
+                     sizeof(request.bytes), 1) != MEMCACHED_SUCCESS) 
+    {
+      memcached_io_reset(&ptr->hosts[server_key]);
+      return MEMCACHED_WRITE_FAILURE;
+    }
+  }
+
+  memcached_server_response_decrement(&ptr->hosts[server_key]);  
+  do 
+  {
+    rc= memcached_response(&ptr->hosts[server_key], buffer, 
+                           sizeof(buffer), NULL);
+    if (rc == MEMCACHED_END)
+      break;
+
+    unlikely (rc != MEMCACHED_SUCCESS) 
+    {
+      memcached_io_reset(&ptr->hosts[server_key]);
+      return rc;
+    }
+
+    unlikely((set_data(memc_stat, buffer, buffer + strlen(buffer) + 1)) == MEMCACHED_UNKNOWN_STAT_KEY)
+    {
+      WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
+      WATCHPOINT_ASSERT(0);
+    }
+  } while (1);
+
+  /* shit... memcached_response will decrement the counter, so I need to
+   ** reset it.. todo: look at this and try to find a better solution.
+ */
+  ptr->hosts[server_key].cursor_active= 0;
+
+  return MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t ascii_stats_fetch(memcached_st *ptr,
+                                            memcached_stat_st *memc_stat,
+                                            char *args,
+                                            unsigned int server_key)
+{
+  memcached_return_t rc;
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+  size_t send_length;
+
+  if (args)
+    send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
+                                   "stats %s\r\n", args);
+  else
+    send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
+                                   "stats\r\n");
+
+  if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
+    return MEMCACHED_WRITE_FAILURE;
+
+  rc= memcached_do(&ptr->hosts[server_key], buffer, send_length, 1);
+  if (rc != MEMCACHED_SUCCESS)
+    goto error;
+
+  while (1)
+  {
+    rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+
+    if (rc == MEMCACHED_STAT)
+    {
+      char *string_ptr, *end_ptr;
+      char *key, *value;
+
+      string_ptr= buffer;
+      string_ptr+= 5; /* Move past STAT */
+      for (end_ptr= string_ptr; isgraph(*end_ptr); end_ptr++);
+      key= string_ptr;
+      key[(size_t)(end_ptr-string_ptr)]= 0;
+
+      string_ptr= end_ptr + 1;
+      for (end_ptr= string_ptr; !(isspace(*end_ptr)); end_ptr++);
+      value= string_ptr;
+      value[(size_t)(end_ptr-string_ptr)]= 0;
+      string_ptr= end_ptr + 2;
+      unlikely((set_data(memc_stat, key, value)) == MEMCACHED_UNKNOWN_STAT_KEY)
+      {
+        WATCHPOINT_ERROR(MEMCACHED_UNKNOWN_STAT_KEY);
+        WATCHPOINT_ASSERT(0);
+      }
+    }
+    else
+      break;
+  }
+
+error:
+  if (rc == MEMCACHED_END)
+    return MEMCACHED_SUCCESS;
+  else
+    return rc;
+}
+
+memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_return_t *error)
+{
+  unsigned int x;
+  memcached_return_t rc;
+  memcached_stat_st *stats;
+
+  unlikely (ptr->flags.use_udp)
+  {
+    *error= MEMCACHED_NOT_SUPPORTED;
+    return NULL;
+  }
+
+  stats= ptr->call_calloc(ptr, ptr->number_of_hosts, sizeof(memcached_stat_st));
+
+  if (!stats)
+  {
+    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return NULL;
+  }
+
+  rc= MEMCACHED_SUCCESS;
+  for (x= 0; x < ptr->number_of_hosts; x++)
+  {
+    memcached_return_t temp_return;
+
+    if (ptr->flags.binary_protocol)
+      temp_return= binary_stats_fetch(ptr, stats + x, args, x);
+    else
+      temp_return= ascii_stats_fetch(ptr, stats + x, args, x);
+
+    if (temp_return != MEMCACHED_SUCCESS)
+      rc= MEMCACHED_SOME_ERRORS;
+  }
+
+  *error= rc;
+  return stats;
+}
+
+memcached_return_t memcached_stat_servername(memcached_stat_st *memc_stat, char *args, 
+                                             const char *hostname, in_port_t port)
+{
+  memcached_return_t rc;
+  memcached_st memc;
+  memcached_st *memc_ptr;
+
+  memc_ptr= memcached_create(&memc);
+  WATCHPOINT_ASSERT(memc_ptr);
+
+  memcached_server_add(&memc, hostname, port);
+
+  if (memc.flags.binary_protocol)
+    rc= binary_stats_fetch(&memc, memc_stat, args, 0);
+  else
+    rc= ascii_stats_fetch(&memc, memc_stat, args, 0);
+
+  memcached_free(&memc);
+
+  return rc;
+}
+
+/* 
+  We make a copy of the keys since at some point in the not so distant future
+  we will add support for "found" keys.
+*/
+char ** memcached_stat_get_keys(memcached_st *ptr, memcached_stat_st *memc_stat, 
+                                memcached_return_t *error)
+{
+  (void) memc_stat;
+  char **list;
+  size_t length= sizeof(memcached_stat_keys);
+
+  list= ptr->call_malloc(ptr, length);
+
+  if (!list)
+  {
+    *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+    return NULL;
+  }
+
+  memcpy(list, memcached_stat_keys, sizeof(memcached_stat_keys));
+
+  *error= MEMCACHED_SUCCESS;
+
+  return list;
+}
+
+void memcached_stat_free(memcached_st *ptr, memcached_stat_st *memc_stat)
+{
+  if (memc_stat == NULL)
+  {
+    WATCHPOINT_ASSERT(0); /* Be polite, but when debugging catch this as an error */
+    return;
+  }
+
+  if (ptr)
+    ptr->call_free(ptr, memc_stat);
+  else
+    free(memc_stat);
+}
diff --git a/libmemcached/storage.c b/libmemcached/storage.c
new file mode 100644 (file)
index 0000000..5aa1d77
--- /dev/null
@@ -0,0 +1,519 @@
+/* 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: Storage related functions, aka set, replace,..
+ *
+ */
+
+#include "common.h"
+
+typedef enum {
+  SET_OP,
+  REPLACE_OP,
+  ADD_OP,
+  PREPEND_OP,
+  APPEND_OP,
+  CAS_OP,
+} memcached_storage_action_t;
+
+/* Inline this */
+static inline const char *storage_op_string(memcached_storage_action_t verb)
+{
+  switch (verb)
+  {
+  case SET_OP:
+    return "set ";
+  case REPLACE_OP:
+    return "replace ";
+  case ADD_OP:
+    return "add ";
+  case PREPEND_OP:
+    return "prepend ";
+  case APPEND_OP:
+    return "append ";
+  case CAS_OP:
+    return "cas ";
+  default:
+    return "tosserror"; /* This is impossible, fixes issue for compiler warning in VisualStudio */
+  }
+
+  /* NOTREACHED */
+}
+
+static memcached_return_t 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, 
+                                                time_t expiration,
+                                                uint32_t flags,
+                                                uint64_t cas,
+                                                memcached_storage_action_t verb);
+
+static inline memcached_return_t memcached_send(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, 
+                                                time_t expiration,
+                                                uint32_t flags,
+                                                uint64_t cas,
+                                                memcached_storage_action_t verb)
+{
+  char to_write;
+  size_t write_length;
+  ssize_t sent_length;
+  memcached_return_t rc;
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+  unsigned int server_key;
+
+  WATCHPOINT_ASSERT(!(value == NULL && value_length > 0));
+
+  rc= memcached_validate_key_length(key_length, ptr->flags.binary_protocol);
+  unlikely (rc != MEMCACHED_SUCCESS)
+    return rc;
+
+  unlikely (ptr->number_of_hosts == 0)
+    return MEMCACHED_NO_SERVERS;
+
+  if (ptr->flags.verify_key && (memcached_key_test((const char **)&key, &key_length, 1) == MEMCACHED_BAD_KEY_PROVIDED))
+    return MEMCACHED_BAD_KEY_PROVIDED;
+
+  if (ptr->flags.binary_protocol)
+  {
+    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= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
+                                    "%s %s%.*s %u %llu %zu %llu%s\r\n", 
+                                    storage_op_string(verb),
+                                    ptr->prefix_key,
+                                    (int)key_length, key, flags, 
+                                    (unsigned long long)expiration, value_length, 
+                                    (unsigned long long)cas,
+                                    (ptr->flags.no_reply) ? " noreply" : "");
+  }
+  else
+  {
+    char *buffer_ptr= buffer;
+    const char *command= storage_op_string(verb);
+
+    /* Copy in the command, no space needed, we handle that in the command function*/
+    memcpy(buffer_ptr, command, strlen(command));
+
+    /* Copy in the key prefix, switch to the buffer_ptr */
+    buffer_ptr= memcpy(buffer_ptr + strlen(command) , ptr->prefix_key, strlen(ptr->prefix_key));
+
+    /* Copy in the key, adjust point if a key prefix was used. */
+    buffer_ptr= memcpy(buffer_ptr + (ptr->prefix_key ? strlen(ptr->prefix_key) : 0), 
+                       key, key_length);
+    buffer_ptr+= key_length;
+    buffer_ptr[0]=  ' '; 
+    buffer_ptr++;
+
+    write_length= (size_t)(buffer_ptr - buffer);
+    write_length+= (size_t) snprintf(buffer_ptr, MEMCACHED_DEFAULT_COMMAND_SIZE, 
+                                     "%u %llu %zu%s\r\n", 
+                                     flags, 
+                                     (unsigned long long)expiration, value_length,
+                                     ptr->flags.no_reply ? " noreply" : "");
+  }
+
+  if (ptr->flags.use_udp && ptr->flags.buffer_requests)
+  {
+    size_t cmd_size= write_length + value_length + 2;
+    if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
+      return MEMCACHED_WRITE_FAILURE;
+    if (cmd_size + ptr->hosts[server_key].write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
+      memcached_io_write(&ptr->hosts[server_key], NULL, 0, 1);
+  }
+
+  if (write_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
+  {
+    rc= MEMCACHED_WRITE_FAILURE;
+    goto error;
+  }
+
+  /* Send command header */
+  rc=  memcached_do(&ptr->hosts[server_key], buffer, write_length, 0);
+  if (rc != MEMCACHED_SUCCESS)
+    goto error;
+
+  /* Send command body */
+  if ((sent_length= memcached_io_write(&ptr->hosts[server_key], value, value_length, 0)) == -1)
+  {
+    rc= MEMCACHED_WRITE_FAILURE;
+    goto error;
+  }
+
+  if (ptr->flags.buffer_requests && verb == SET_OP)
+  {
+    to_write= 0;
+  }
+  else
+  {
+    to_write= 1;
+  }
+
+  if ((sent_length= memcached_io_write(&ptr->hosts[server_key], "\r\n", 2, to_write)) == -1)
+  {
+    rc= MEMCACHED_WRITE_FAILURE;
+    goto error;
+  }
+
+  if (ptr->flags.no_reply)
+    return (to_write == 0) ? MEMCACHED_BUFFERED : MEMCACHED_SUCCESS;
+
+  if (to_write == 0)
+    return MEMCACHED_BUFFERED;
+
+  rc= memcached_response(&ptr->hosts[server_key], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+
+  if (rc == MEMCACHED_STORED)
+    return MEMCACHED_SUCCESS;
+  else 
+    return rc;
+
+error:
+  memcached_io_reset(&ptr->hosts[server_key]);
+
+  return rc;
+}
+
+
+memcached_return_t memcached_set(memcached_st *ptr, const char *key, size_t key_length, 
+                                 const char *value, size_t value_length, 
+                                 time_t expiration,
+                                 uint32_t flags)
+{
+  memcached_return_t rc;
+  LIBMEMCACHED_MEMCACHED_SET_START();
+  rc= memcached_send(ptr, key, key_length, 
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, SET_OP);
+  LIBMEMCACHED_MEMCACHED_SET_END();
+  return rc;
+}
+
+memcached_return_t memcached_add(memcached_st *ptr, 
+                                 const char *key, size_t key_length,
+                                 const char *value, size_t value_length, 
+                                 time_t expiration,
+                                 uint32_t flags)
+{
+  memcached_return_t rc;
+  LIBMEMCACHED_MEMCACHED_ADD_START();
+  rc= memcached_send(ptr, key, key_length, 
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, ADD_OP);
+  LIBMEMCACHED_MEMCACHED_ADD_END();
+  return rc;
+}
+
+memcached_return_t memcached_replace(memcached_st *ptr, 
+                                     const char *key, size_t key_length,
+                                     const char *value, size_t value_length, 
+                                     time_t expiration,
+                                     uint32_t flags)
+{
+  memcached_return_t rc;
+  LIBMEMCACHED_MEMCACHED_REPLACE_START();
+  rc= memcached_send(ptr, key, key_length, 
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, REPLACE_OP);
+  LIBMEMCACHED_MEMCACHED_REPLACE_END();
+  return rc;
+}
+
+memcached_return_t memcached_prepend(memcached_st *ptr, 
+                                     const char *key, size_t key_length,
+                                     const char *value, size_t value_length, 
+                                     time_t expiration,
+                                     uint32_t flags)
+{
+  memcached_return_t rc;
+  rc= memcached_send(ptr, key, key_length, 
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, PREPEND_OP);
+  return rc;
+}
+
+memcached_return_t memcached_append(memcached_st *ptr, 
+                                    const char *key, size_t key_length,
+                                    const char *value, size_t value_length, 
+                                    time_t expiration,
+                                    uint32_t flags)
+{
+  memcached_return_t rc;
+  rc= memcached_send(ptr, key, key_length, 
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, APPEND_OP);
+  return rc;
+}
+
+memcached_return_t memcached_cas(memcached_st *ptr, 
+                                 const char *key, size_t key_length,
+                                 const char *value, size_t value_length, 
+                                 time_t expiration,
+                                 uint32_t flags,
+                                 uint64_t cas)
+{
+  memcached_return_t rc;
+  rc= memcached_send(ptr, key, key_length, 
+                     key, key_length, value, value_length,
+                     expiration, flags, cas, CAS_OP);
+  return rc;
+}
+
+memcached_return_t memcached_set_by_key(memcached_st *ptr, 
+                                        const char *master_key __attribute__((unused)), 
+                                        size_t master_key_length __attribute__((unused)), 
+                                        const char *key, size_t key_length, 
+                                        const char *value, size_t value_length, 
+                                        time_t expiration,
+                                        uint32_t flags)
+{
+  memcached_return_t rc;
+  LIBMEMCACHED_MEMCACHED_SET_START();
+  rc= memcached_send(ptr, master_key, master_key_length, 
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, SET_OP);
+  LIBMEMCACHED_MEMCACHED_SET_END();
+  return rc;
+}
+
+memcached_return_t memcached_add_by_key(memcached_st *ptr, 
+                                        const char *master_key, size_t master_key_length,
+                                        const char *key, size_t key_length,
+                                        const char *value, size_t value_length, 
+                                        time_t expiration,
+                                        uint32_t flags)
+{
+  memcached_return_t rc;
+  LIBMEMCACHED_MEMCACHED_ADD_START();
+  rc= memcached_send(ptr, master_key, master_key_length, 
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, ADD_OP);
+  LIBMEMCACHED_MEMCACHED_ADD_END();
+  return rc;
+}
+
+memcached_return_t memcached_replace_by_key(memcached_st *ptr, 
+                                            const char *master_key, size_t master_key_length,
+                                            const char *key, size_t key_length,
+                                            const char *value, size_t value_length, 
+                                            time_t expiration,
+                                            uint32_t flags)
+{
+  memcached_return_t rc;
+  LIBMEMCACHED_MEMCACHED_REPLACE_START();
+  rc= memcached_send(ptr, master_key, master_key_length, 
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, REPLACE_OP);
+  LIBMEMCACHED_MEMCACHED_REPLACE_END();
+  return rc;
+}
+
+memcached_return_t memcached_prepend_by_key(memcached_st *ptr, 
+                                            const char *master_key, size_t master_key_length,
+                                            const char *key, size_t key_length,
+                                            const char *value, size_t value_length, 
+                                            time_t expiration,
+                                            uint32_t flags)
+{
+  memcached_return_t rc;
+  rc= memcached_send(ptr, master_key, master_key_length, 
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, PREPEND_OP);
+  return rc;
+}
+
+memcached_return_t memcached_append_by_key(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, 
+                                           time_t expiration,
+                                           uint32_t flags)
+{
+  memcached_return_t rc;
+  rc= memcached_send(ptr, master_key, master_key_length, 
+                     key, key_length, value, value_length,
+                     expiration, flags, 0, APPEND_OP);
+  return rc;
+}
+
+memcached_return_t memcached_cas_by_key(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, 
+                                        time_t expiration,
+                                        uint32_t flags,
+                                        uint64_t cas)
+{
+  memcached_return_t rc;
+  rc= memcached_send(ptr, master_key, master_key_length, 
+                     key, key_length, value, value_length,
+                     expiration, flags, cas, CAS_OP);
+  return rc;
+}
+
+static inline uint8_t get_com_code(memcached_storage_action_t verb, bool noreply)
+{
+  /* 0 isn't a value we want, but GCC 4.2 seems to think ret can otherwise
+   * be used uninitialized in this function. FAIL */
+  uint8_t ret= 0;
+
+  if (noreply)
+    switch (verb)
+    {
+    case SET_OP:
+      ret=PROTOCOL_BINARY_CMD_SETQ;
+      break;
+    case ADD_OP:
+      ret=PROTOCOL_BINARY_CMD_ADDQ;
+      break;
+    case CAS_OP: /* FALLTHROUGH */
+    case REPLACE_OP:
+      ret=PROTOCOL_BINARY_CMD_REPLACEQ;
+      break;
+    case APPEND_OP:
+      ret=PROTOCOL_BINARY_CMD_APPENDQ;
+      break;
+    case PREPEND_OP:
+      ret=PROTOCOL_BINARY_CMD_PREPENDQ;
+      break;
+    default:
+      WATCHPOINT_ASSERT(verb);
+      break;
+    }
+  else
+    switch (verb)
+    {
+    case SET_OP:
+      ret=PROTOCOL_BINARY_CMD_SET;
+      break;
+    case ADD_OP:
+      ret=PROTOCOL_BINARY_CMD_ADD;
+      break;
+    case CAS_OP: /* FALLTHROUGH */
+    case REPLACE_OP:
+      ret=PROTOCOL_BINARY_CMD_REPLACE;
+      break;
+    case APPEND_OP:
+      ret=PROTOCOL_BINARY_CMD_APPEND;
+      break;
+    case PREPEND_OP:
+      ret=PROTOCOL_BINARY_CMD_PREPEND;
+      break;
+    default:
+      WATCHPOINT_ASSERT(verb);
+      break;
+    }
+
+  return ret;
+}
+
+
+
+static memcached_return_t 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, 
+                                                time_t expiration,
+                                                uint32_t flags,
+                                                uint64_t cas,
+                                                memcached_storage_action_t verb)
+{
+  uint8_t 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.no_reply;
+
+  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);
+  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! */
+  else 
+  {
+    request.message.header.request.extlen= 8;
+    request.message.body.flags= htonl(flags);   
+    request.message.body.expiration= htonl((uint32_t)expiration);
+  }
+
+  request.message.header.request.bodylen= htonl((uint32_t) (key_length + value_length + 
+                                                            request.message.header.request.extlen));
+
+  if (cas)
+    request.message.header.request.cas= htonll(cas);
+
+  flush= (uint8_t) ((server->root->flags.buffer_requests && verb == SET_OP) ? 0 : 1);
+
+  if (server->root->flags.use_udp && !flush)
+  {
+    size_t cmd_size= send_length + key_length + value_length;
+
+    if (cmd_size > MAX_UDP_DATAGRAM_LENGTH - UDP_DATAGRAM_HEADER_LENGTH)
+      return MEMCACHED_WRITE_FAILURE;
+    if (cmd_size + server->write_buffer_offset > MAX_UDP_DATAGRAM_LENGTH)
+      memcached_io_write(server,NULL,0, 1);
+  }
+
+  /* write the header */
+  if ((memcached_do(server, (const char*)request.bytes, send_length, 0) != MEMCACHED_SUCCESS) ||
+      (memcached_io_write(server, key, key_length, 0) == -1) ||
+      (memcached_io_write(server, value, value_length, (char) flush) == -1)) 
+  {
+    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 (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, (char) flush) == -1))
+        memcached_io_reset(srv);
+      else
+        memcached_server_response_decrement(srv);
+    }
+  }
+
+  if (flush == 0)
+    return MEMCACHED_BUFFERED;
+
+  if (noreply)
+    return MEMCACHED_SUCCESS;
+
+  return memcached_response(server, NULL, 0, NULL);   
+}
+
diff --git a/libmemcached/storage.h b/libmemcached/storage.h
new file mode 100644 (file)
index 0000000..ec982ba
--- /dev/null
@@ -0,0 +1,110 @@
+/* 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: Storage related functions, aka set, replace,..
+ *
+ */
+
+#ifndef __MEMCACHED_STORAGE_H__
+#define __MEMCACHED_STORAGE_H__
+
+#include "libmemcached/memcached.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* All of the functions for adding data to the server */
+LIBMEMCACHED_API
+memcached_return_t memcached_set(memcached_st *ptr, const char *key, size_t key_length, 
+                                 const char *value, size_t value_length, 
+                                 time_t expiration,
+                                 uint32_t  flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_add(memcached_st *ptr, const char *key, size_t key_length,
+                                 const char *value, size_t value_length, 
+                                 time_t expiration,
+                                 uint32_t  flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_replace(memcached_st *ptr, const char *key, size_t key_length,
+                                     const char *value, size_t value_length, 
+                                     time_t expiration,
+                                     uint32_t  flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_append(memcached_st *ptr, 
+                                    const char *key, size_t key_length,
+                                    const char *value, size_t value_length, 
+                                    time_t expiration,
+                                    uint32_t flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_prepend(memcached_st *ptr, 
+                                     const char *key, size_t key_length,
+                                     const char *value, size_t value_length, 
+                                     time_t expiration,
+                                     uint32_t flags);
+LIBMEMCACHED_API
+memcached_return_t memcached_cas(memcached_st *ptr, 
+                                 const char *key, size_t key_length,
+                                 const char *value, size_t value_length, 
+                                 time_t expiration,
+                                 uint32_t flags,
+                                 uint64_t cas);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_set_by_key(memcached_st *ptr, 
+                                        const char *master_key, size_t master_key_length, 
+                                        const char *key, size_t key_length, 
+                                        const char *value, size_t value_length, 
+                                        time_t expiration,
+                                        uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_add_by_key(memcached_st *ptr, 
+                                        const char *master_key, size_t master_key_length,
+                                        const char *key, size_t key_length,
+                                        const char *value, size_t value_length, 
+                                        time_t expiration,
+                                        uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_replace_by_key(memcached_st *ptr, 
+                                            const char *master_key, size_t master_key_length,
+                                            const char *key, size_t key_length,
+                                            const char *value, size_t value_length, 
+                                            time_t expiration,
+                                            uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_prepend_by_key(memcached_st *ptr, 
+                                            const char *master_key, size_t master_key_length,
+                                            const char *key, size_t key_length,
+                                            const char *value, size_t value_length, 
+                                            time_t expiration,
+                                            uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_append_by_key(memcached_st *ptr, 
+                                           const char *master_key, size_t master_key_length,
+                                           const char *key, size_t key_length,
+                                           const char *value, size_t value_length, 
+                                           time_t expiration,
+                                           uint32_t flags);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_cas_by_key(memcached_st *ptr, 
+                                        const char *master_key, size_t master_key_length,
+                                        const char *key, size_t key_length,
+                                        const char *value, size_t value_length, 
+                                        time_t expiration,
+                                        uint32_t flags,
+                                        uint64_t cas);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MEMCACHED_STORAGE_H__ */
diff --git a/libmemcached/strerror.c b/libmemcached/strerror.c
new file mode 100644 (file)
index 0000000..f1d651c
--- /dev/null
@@ -0,0 +1,90 @@
+#include "common.h"
+
+const char *memcached_strerror(memcached_st *ptr __attribute__((unused)), memcached_return_t rc)
+{
+  switch (rc)
+  {
+  case MEMCACHED_SUCCESS:
+    return "SUCCESS";
+  case MEMCACHED_FAILURE:
+    return "FAILURE";
+  case MEMCACHED_HOST_LOOKUP_FAILURE:
+    return "HOSTNAME LOOKUP FAILURE";
+  case MEMCACHED_CONNECTION_FAILURE:
+    return "CONNECTION FAILURE";
+  case MEMCACHED_CONNECTION_BIND_FAILURE:
+    return "CONNECTION BIND FAILURE";
+  case MEMCACHED_READ_FAILURE:
+    return "READ FAILURE";
+  case MEMCACHED_UNKNOWN_READ_FAILURE:
+    return "UNKNOWN READ FAILURE";
+  case MEMCACHED_PROTOCOL_ERROR:
+    return "PROTOCOL ERROR";
+  case MEMCACHED_CLIENT_ERROR:
+    return "CLIENT ERROR";
+  case MEMCACHED_SERVER_ERROR:
+    return "SERVER ERROR";
+  case MEMCACHED_WRITE_FAILURE:
+    return "WRITE FAILURE";
+  case MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE:
+    return "CONNECTION SOCKET CREATE FAILURE";
+  case MEMCACHED_DATA_EXISTS:
+    return "CONNECTION DATA EXISTS";
+  case MEMCACHED_DATA_DOES_NOT_EXIST:
+    return "CONNECTION DATA DOES NOT EXIST";
+  case MEMCACHED_NOTSTORED:
+    return "NOT STORED";
+  case MEMCACHED_STORED:
+    return "STORED";
+  case MEMCACHED_NOTFOUND:
+    return "NOT FOUND";
+  case MEMCACHED_MEMORY_ALLOCATION_FAILURE:
+    return "MEMORY ALLOCATION FAILURE";
+  case MEMCACHED_PARTIAL_READ:
+    return "PARTIAL READ";
+  case MEMCACHED_SOME_ERRORS:
+    return "SOME ERRORS WERE REPORTED";
+  case MEMCACHED_NO_SERVERS:
+    return "NO SERVERS DEFINED";
+  case MEMCACHED_END:
+    return "SERVER END";
+  case MEMCACHED_DELETED:
+    return "SERVER DELETE";
+  case MEMCACHED_VALUE:
+    return "SERVER VALUE";
+  case MEMCACHED_STAT:
+    return "STAT VALUE";
+  case MEMCACHED_ITEM:
+    return "ITEM VALUE";
+  case MEMCACHED_ERRNO:
+    return "SYSTEM ERROR";
+  case MEMCACHED_FAIL_UNIX_SOCKET:
+    return "COULD NOT OPEN UNIX SOCKET";
+  case MEMCACHED_NOT_SUPPORTED:
+    return "ACTION NOT SUPPORTED";
+  case MEMCACHED_FETCH_NOTFINISHED:
+    return "FETCH WAS NOT COMPLETED";
+  case MEMCACHED_NO_KEY_PROVIDED:
+    return "A KEY LENGTH OF ZERO WAS PROVIDED";
+  case MEMCACHED_BUFFERED:
+    return "ACTION QUEUED";
+  case MEMCACHED_TIMEOUT:
+    return "A TIMEOUT OCCURRED";
+  case MEMCACHED_BAD_KEY_PROVIDED:
+    return "A BAD KEY WAS PROVIDED/CHARACTERS OUT OF RANGE";
+  case MEMCACHED_INVALID_HOST_PROTOCOL:
+    return "THE HOST TRANSPORT PROTOCOL DOES NOT MATCH THAT OF THE CLIENT";
+  case MEMCACHED_SERVER_MARKED_DEAD:
+    return "SERVER IS MARKED DEAD";
+  case MEMCACHED_UNKNOWN_STAT_KEY:
+    return "ENCOUNTERED AN UNKNOWN STAT KEY";
+  case MEMCACHED_E2BIG:
+    return "ITEM TOO BIG";
+  case MEMCACHED_INVALID_ARGUMENTS:
+     return "INVALID ARGUMENTS";
+  case MEMCACHED_MAXIMUM_RETURN:
+    return "Gibberish returned!";
+  default:
+    return "Gibberish returned!";
+  }
+}
diff --git a/libmemcached/string.c b/libmemcached/string.c
new file mode 100644 (file)
index 0000000..838ca41
--- /dev/null
@@ -0,0 +1,171 @@
+/* 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: String structure used for libmemcached.
+ *
+ */
+
+#include "common.h"
+
+inline static memcached_return_t _string_check(memcached_string_st *string, size_t need)
+{
+  if (need && need > (size_t)(string->current_size - (size_t)(string->end - string->string)))
+  {
+    size_t current_offset= (size_t) (string->end - string->string);
+    char *new_value;
+    size_t adjust;
+    size_t new_size;
+
+    /* This is the block multiplier. To keep it larger and surive division errors we must round it up */
+    adjust= (need - (size_t)(string->current_size - (size_t)(string->end - string->string))) / string->block_size;
+    adjust++;
+
+    new_size= sizeof(char) * (size_t)((adjust * string->block_size) + string->current_size);
+    /* Test for overflow */
+    if (new_size < need)
+      return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+
+    new_value= string->root->call_realloc(string->root, string->string, new_size);
+
+    if (new_value == NULL)
+      return MEMCACHED_MEMORY_ALLOCATION_FAILURE;
+
+    string->string= new_value;
+    string->end= string->string + current_offset;
+
+    string->current_size+= (string->block_size * adjust);
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_string_st *memcached_string_create(memcached_st *memc, memcached_string_st *string, size_t initial_size)
+{
+  memcached_return_t rc;
+
+  /* Saving malloc calls :) */
+  if (string)
+  {
+    WATCHPOINT_ASSERT(memc->options.is_safe && string->options.is_initialized == false);
+
+    memset(string, 0, sizeof(memcached_string_st));
+  }
+  else
+  {
+    string= memc->call_calloc(memc, 1, sizeof(memcached_string_st));
+
+    if (string == NULL)
+    {
+      return NULL;
+    }
+
+    string->options.is_allocated= true;
+  }
+  string->block_size= MEMCACHED_BLOCK_SIZE;
+  string->root= memc;
+
+  rc=  _string_check(string, initial_size);
+  if (rc != MEMCACHED_SUCCESS)
+  {
+    memc->call_free(memc, string);
+    return NULL;
+  }
+
+  string->options.is_initialized= true;
+
+  WATCHPOINT_ASSERT(string->string == string->end);
+
+  return string;
+}
+
+memcached_return_t memcached_string_append_character(memcached_string_st *string, 
+                                                   char character)
+{
+  memcached_return_t rc;
+
+  rc=  _string_check(string, 1);
+
+  if (rc != MEMCACHED_SUCCESS)
+    return rc;
+
+  *string->end= character;
+  string->end++;
+
+  return MEMCACHED_SUCCESS;
+}
+
+memcached_return_t memcached_string_append(memcached_string_st *string,
+                                         const char *value, size_t length)
+{
+  memcached_return_t rc;
+
+  rc= _string_check(string, length);
+
+  if (rc != MEMCACHED_SUCCESS)
+    return rc;
+
+  WATCHPOINT_ASSERT(length <= string->current_size);
+  WATCHPOINT_ASSERT(string->string);
+  WATCHPOINT_ASSERT(string->end >= string->string);
+
+  memcpy(string->end, value, length);
+  string->end+= length;
+
+  return MEMCACHED_SUCCESS;
+}
+
+char *memcached_string_c_copy(memcached_string_st *string)
+{
+  char *c_ptr;
+
+  if (memcached_string_length(string) == 0)
+    return NULL;
+
+  c_ptr= string->root->call_malloc(string->root, (memcached_string_length(string)+1) * sizeof(char));
+
+  if (c_ptr == NULL)
+    return NULL;
+
+  memcpy(c_ptr, memcached_string_value(string), memcached_string_length(string));
+  c_ptr[memcached_string_length(string)]= 0;
+
+  return c_ptr;
+}
+
+memcached_return_t memcached_string_reset(memcached_string_st *string)
+{
+  string->end= string->string;
+  
+  return MEMCACHED_SUCCESS;
+}
+
+void memcached_string_free(memcached_string_st *ptr)
+{
+  if (ptr == NULL)
+    return;
+
+  if (ptr->string)
+  {
+    ptr->root->call_free(ptr->root, ptr->string);
+  }
+
+  if (memcached_is_allocated(ptr))
+  {
+    ptr->root->call_free(ptr->root, ptr);
+  }
+  else
+  {
+    ptr->options.is_initialized= false;
+    memset(ptr, 0, sizeof(memcached_string_st));
+  }
+}
+
+memcached_return_t memcached_string_check(memcached_string_st *string, size_t need)
+{
+  return _string_check(string, need);
+}
+
diff --git a/libmemcached/string.h b/libmemcached/string.h
new file mode 100644 (file)
index 0000000..d93bc0d
--- /dev/null
@@ -0,0 +1,62 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: String structure used for libmemcached.
+ *
+ */
+
+#ifndef __MEMCACHED_STRING_H__
+#define __MEMCACHED_STRING_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct memcached_string_st {
+  memcached_st *root;
+  char *end;
+  char *string;
+  size_t current_size;
+  size_t block_size;
+  struct {
+    bool is_allocated:1;
+    bool is_initialized:1;
+  } options;
+};
+
+#define memcached_string_length(A) (size_t)((A)->end - (A)->string)
+#define memcached_string_set_length(A, B) (A)->end= (A)->string + B
+#define memcached_string_size(A) (A)->current_size
+#define memcached_string_value(A) (A)->string
+
+LIBMEMCACHED_API
+memcached_string_st *memcached_string_create(memcached_st *ptr,
+                                             memcached_string_st *string,
+                                             size_t initial_size);
+LIBMEMCACHED_API
+memcached_return_t memcached_string_check(memcached_string_st *string, size_t need);
+
+LIBMEMCACHED_API
+char *memcached_string_c_copy(memcached_string_st *string);
+
+LIBMEMCACHED_API
+memcached_return_t memcached_string_append_character(memcached_string_st *string,
+                                                     char character);
+LIBMEMCACHED_API
+memcached_return_t memcached_string_append(memcached_string_st *string,
+                                           const char *value, size_t length);
+LIBMEMCACHED_API
+memcached_return_t memcached_string_reset(memcached_string_st *string);
+
+LIBMEMCACHED_API
+void memcached_string_free(memcached_string_st *string);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MEMCACHED_STRING_H__ */
diff --git a/libmemcached/types.h b/libmemcached/types.h
new file mode 100644 (file)
index 0000000..58f0887
--- /dev/null
@@ -0,0 +1,76 @@
+/* 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: Types for libmemcached
+ *
+ */
+
+#ifndef LIBMEMCACHED_MEMCACHED_TYPES_H
+#define LIBMEMCACHED_MEMCACHED_TYPES_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct memcached_st memcached_st;
+typedef struct memcached_stat_st memcached_stat_st;
+typedef struct memcached_analysis_st memcached_analysis_st;
+typedef struct memcached_result_st memcached_result_st;
+typedef struct memcached_string_st memcached_string_st;
+typedef struct memcached_server_st memcached_server_st;
+typedef struct memcached_continuum_item_st memcached_continuum_item_st;
+typedef memcached_return_t (*memcached_clone_fn)(memcached_st *parent, memcached_st *clone);
+typedef memcached_return_t (*memcached_cleanup_fn)(memcached_st *ptr);
+typedef void (*memcached_free_fn)(memcached_st *ptr, void *mem);
+typedef void *(*memcached_malloc_fn)(memcached_st *ptr, const size_t size);
+typedef void *(*memcached_realloc_fn)(memcached_st *ptr, void *mem, const size_t size);
+typedef void *(*memcached_calloc_fn)(memcached_st *ptr, size_t nelem, const size_t elsize);
+typedef memcached_return_t (*memcached_execute_fn)(memcached_st *ptr, memcached_result_st *result, void *context);
+typedef memcached_return_t (*memcached_server_fn)(memcached_st *ptr, memcached_server_st *server, void *context);
+typedef memcached_return_t (*memcached_trigger_key_fn)(memcached_st *ptr,
+                                                       const char *key, size_t key_length,
+                                                       memcached_result_st *result);
+typedef memcached_return_t (*memcached_trigger_delete_key_fn)(memcached_st *ptr,
+                                                              const char *key, size_t key_length);
+
+typedef memcached_return_t (*memcached_dump_fn)(memcached_st *ptr,
+                                                  const char *key, size_t key_length, void *context);
+
+typedef struct {
+  memcached_execute_fn *callback;
+  void *context;
+  uint32_t number_of_callback;
+} memcached_callback_st;
+
+/**
+  @note The following definitions are just here for backwards compatibility.
+*/
+typedef memcached_return_t memcached_return;
+typedef memcached_server_distribution_t memcached_server_distribution;
+typedef memcached_behavior_t memcached_behavior;
+typedef memcached_callback_t memcached_callback;
+typedef memcached_hash_t memcached_hash;
+typedef memcached_connection_t memcached_connection;
+typedef memcached_clone_fn memcached_clone_func;
+typedef memcached_cleanup_fn memcached_cleanup_func;
+typedef memcached_free_fn memcached_free_function;
+typedef memcached_malloc_fn memcached_malloc_function;
+typedef memcached_realloc_fn memcached_realloc_function;
+typedef memcached_calloc_fn memcached_calloc_function;
+typedef memcached_execute_fn memcached_execute_function;
+typedef memcached_server_fn memcached_server_function;
+typedef memcached_trigger_key_fn memcached_trigger_key;
+typedef memcached_trigger_delete_key_fn memcached_trigger_delete_key;
+typedef memcached_dump_fn memcached_dump_func;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBMEMCACHED_MEMCACHED_TYPES_H */
diff --git a/libmemcached/util/memcached_pool.c b/libmemcached/util/memcached_pool.c
deleted file mode 100644 (file)
index fac7d2d..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
-#include "libmemcached/common.h"
-#include "libmemcached/memcached_pool.h"
-
-#include <errno.h>
-#include <pthread.h>
-
-struct memcached_pool_st 
-{
-  pthread_mutex_t mutex;
-  pthread_cond_t cond;
-  memcached_st *master;
-  memcached_st **mmc;
-  int firstfree;
-  uint32_t size;
-  uint32_t current_size;
-  char *version;
-};
-
-static memcached_return_t mutex_enter(pthread_mutex_t *mutex) 
-{
-  int ret;
-  do 
-    ret= pthread_mutex_lock(mutex);
-  while (ret == -1 && errno == EINTR);
-
-  return (ret == -1) ? MEMCACHED_ERRNO : MEMCACHED_SUCCESS;
-}
-
-static memcached_return_t mutex_exit(pthread_mutex_t *mutex) {
-  int ret;
-  do
-    ret= pthread_mutex_unlock(mutex);
-  while (ret == -1 && errno == EINTR);
-
-  return (ret == -1) ? MEMCACHED_ERRNO : MEMCACHED_SUCCESS;
-}
-
-/**
- * Grow the connection pool by creating a connection structure and clone the
- * original memcached handle.
- */
-static int grow_pool(memcached_pool_st* pool) {
-  memcached_st *obj= calloc(1, sizeof(*obj));
-  if (obj == NULL)
-    return -1;
-
-  if (memcached_clone(obj, pool->master) == NULL)
-  {
-    free(obj);
-    return -1;
-  }
-
-  pool->mmc[++pool->firstfree] = obj;
-  pool->current_size++;
-
-  return 0;
-}
-
-memcached_pool_st *memcached_pool_create(memcached_st* mmc, 
-                                         uint32_t initial, uint32_t max) 
-{
-  memcached_pool_st* ret = NULL;
-  memcached_pool_st object = { .mutex = PTHREAD_MUTEX_INITIALIZER, 
-    .cond = PTHREAD_COND_INITIALIZER,
-    .master = mmc,
-    .mmc = calloc(max, sizeof(memcached_st*)),
-    .firstfree = -1,
-    .size = max, 
-    .current_size = 0 };
-
-  if (object.mmc != NULL) 
-  {
-    ret= calloc(1, sizeof(*ret));
-    if (ret == NULL) 
-    {
-      free(object.mmc);
-      return NULL;
-    } 
-
-    *ret = object;
-
-    /* Try to create the initial size of the pool. An allocation failure at
-     * this time is not fatal..
-   */
-    for (unsigned int ii=0; ii < initial; ++ii)
-      if (grow_pool(ret) == -1)
-        break;
-  }
-
-  return ret;
-}
-
-memcached_st*  memcached_pool_destroy(memcached_pool_st* pool) 
-{
-  memcached_st *ret = pool->master;
-
-  for (int xx= 0; xx <= pool->firstfree; ++xx) 
-  {
-    memcached_free(pool->mmc[xx]);
-    free(pool->mmc[xx]);
-    pool->mmc[xx] = NULL;
-  }
-
-  pthread_mutex_destroy(&pool->mutex);
-  pthread_cond_destroy(&pool->cond);
-  free(pool->mmc);
-  free(pool);
-
-  return ret;
-}
-
-memcached_st* memcached_pool_pop(memcached_pool_st* pool,
-                                 bool block,
-                                 memcached_return_t *rc) 
-{
-  memcached_st *ret= NULL;
-  if ((*rc= mutex_enter(&pool->mutex)) != MEMCACHED_SUCCESS) 
-    return NULL;
-
-  do 
-  {
-    if (pool->firstfree > -1)
-      ret= pool->mmc[pool->firstfree--];
-    else if (pool->current_size == pool->size) 
-    {
-      if (!block) 
-      {
-        *rc= mutex_exit(&pool->mutex);
-        return NULL;
-      }
-
-      if (pthread_cond_wait(&pool->cond, &pool->mutex) == -1) 
-      {
-        int err = errno;
-        mutex_exit(&pool->mutex);
-        errno = err; 
-        *rc= MEMCACHED_ERRNO;
-        return NULL;
-      }
-    } 
-    else if (grow_pool(pool) == -1) 
-    {
-      *rc= mutex_exit(&pool->mutex);
-      return NULL;
-    }
-  } 
-  while (ret == NULL);
-
-  *rc= mutex_exit(&pool->mutex);
-
-  return ret;
-}
-
-memcached_return_t memcached_pool_push(memcached_pool_st* pool, 
-                                       memcached_st *mmc)
-{
-  memcached_return_t rc= mutex_enter(&pool->mutex);
-
-  if (rc != MEMCACHED_SUCCESS)
-    return rc;
-
-  char* version = memcached_get_user_data(mmc);
-  /* Someone updated the behavior on the object.. */
-  if (version != pool->version) 
-  {
-    memcached_free(mmc);
-    memset(mmc, 0, sizeof(*mmc));
-    if (memcached_clone(mmc, pool->master) == NULL)
-    {
-      rc= MEMCACHED_SOME_ERRORS;
-    }
-  }
-
-  pool->mmc[++pool->firstfree]= mmc;
-
-  if (pool->firstfree == 0 && pool->current_size == pool->size) 
-  {
-    /* we might have people waiting for a connection.. wake them up :-) */
-    pthread_cond_broadcast(&pool->cond);
-  }
-
-  memcached_return_t rval= mutex_exit(&pool->mutex);
-  if (rc == MEMCACHED_SOME_ERRORS)
-    return rc;
-
-  return rval;
-}
-
-
-memcached_return_t memcached_pool_behavior_set(memcached_pool_st *pool, 
-                                               memcached_behavior_t flag, 
-                                               uint64_t data)
-{
-
-  memcached_return_t rc= mutex_enter(&pool->mutex);
-  if (rc != MEMCACHED_SUCCESS)
-    return rc;
-
-  /* update the master */
-  rc= memcached_behavior_set(pool->master, flag, data);
-  if (rc != MEMCACHED_SUCCESS)
-  {
-    mutex_exit(&pool->mutex);
-    return rc;
-  }
-
-  ++pool->version;
-  memcached_set_user_data(pool->master, pool->version);
-  /* update the clones */
-  for (int xx= 0; xx <= pool->firstfree; ++xx) 
-  {
-    rc= memcached_behavior_set(pool->mmc[xx], flag, data);
-    if (rc == MEMCACHED_SUCCESS)
-      memcached_set_user_data(pool->mmc[xx], pool->version);
-    else
-    {
-      memcached_free(pool->mmc[xx]);
-      memset(pool->mmc[xx], 0, sizeof(*pool->mmc[xx]));
-      if (memcached_clone(pool->mmc[xx], pool->master) == NULL)
-      {
-        /* I'm not sure what to do in this case.. this would happen
-          if we fail to push the server list inside the client..
-          I should add a testcase for this, but I believe the following
-          would work, except that you would add a hole in the pool list..
-          in theory you could end up with an empty pool....
-        */
-        free(pool->mmc[xx]);
-        pool->mmc[xx]= NULL;
-      }
-    }
-  }
-
-  return mutex_exit(&pool->mutex);
-}
-
-memcached_return_t memcached_pool_behavior_get(memcached_pool_st *pool, 
-                                               memcached_behavior_t flag,
-                                               uint64_t *value)
-{
-  memcached_return_t rc= mutex_enter(&pool->mutex);
-  if (rc != MEMCACHED_SUCCESS)
-    return rc;
-  *value= memcached_behavior_get(pool->master, flag);
-  return mutex_exit(&pool->mutex);
-}
diff --git a/libmemcached/util/pool.c b/libmemcached/util/pool.c
new file mode 100644 (file)
index 0000000..7cb2517
--- /dev/null
@@ -0,0 +1,257 @@
+/* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
+#include "libmemcached/common.h"
+#include "libmemcached/pool.h"
+
+#include <errno.h>
+#include <pthread.h>
+
+struct memcached_pool_st
+{
+  pthread_mutex_t mutex;
+  pthread_cond_t cond;
+  memcached_st *master;
+  memcached_st **mmc;
+  int firstfree;
+  uint32_t size;
+  uint32_t current_size;
+  char *version;
+};
+
+static memcached_return_t mutex_enter(pthread_mutex_t *mutex)
+{
+  int ret;
+  do
+    ret= pthread_mutex_lock(mutex);
+  while (ret == -1 && errno == EINTR);
+
+  return (ret == -1) ? MEMCACHED_ERRNO : MEMCACHED_SUCCESS;
+}
+
+static memcached_return_t mutex_exit(pthread_mutex_t *mutex)
+{
+  int ret;
+  do
+    ret= pthread_mutex_unlock(mutex);
+  while (ret == -1 && errno == EINTR);
+
+  return (ret == -1) ? MEMCACHED_ERRNO : MEMCACHED_SUCCESS;
+}
+
+/**
+ * Grow the connection pool by creating a connection structure and clone the
+ * original memcached handle.
+ */
+static int grow_pool(memcached_pool_st* pool)
+{
+  memcached_st *obj= calloc(1, sizeof(*obj));
+
+  if (obj == NULL)
+    return -1;
+
+  if (memcached_clone(obj, pool->master) == NULL)
+  {
+    free(obj);
+    return -1;
+  }
+
+  pool->mmc[++pool->firstfree] = obj;
+  pool->current_size++;
+
+  return 0;
+}
+
+memcached_pool_st *memcached_pool_create(memcached_st* mmc,
+                                         uint32_t initial, uint32_t max)
+{
+  memcached_pool_st* ret = NULL;
+  memcached_pool_st object = { .mutex = PTHREAD_MUTEX_INITIALIZER,
+    .cond = PTHREAD_COND_INITIALIZER,
+    .master = mmc,
+    .mmc = calloc(max, sizeof(memcached_st*)),
+    .firstfree = -1,
+    .size = max,
+    .current_size = 0 };
+
+  if (object.mmc != NULL)
+  {
+    ret= calloc(1, sizeof(*ret));
+    if (ret == NULL)
+    {
+      free(object.mmc);
+      return NULL;
+    }
+
+    *ret = object;
+
+    /*
+      Try to create the initial size of the pool. An allocation failure at
+      this time is not fatal..
+    */
+    for (unsigned int ii= 0; ii < initial; ++ii)
+    {
+      if (grow_pool(ret) == -1)
+        break;
+    }
+  }
+
+  return ret;
+}
+
+memcached_st*  memcached_pool_destroy(memcached_pool_st* pool)
+{
+  memcached_st *ret = pool->master;
+
+  for (int xx= 0; xx <= pool->firstfree; ++xx)
+  {
+    memcached_free(pool->mmc[xx]);
+    free(pool->mmc[xx]);
+    pool->mmc[xx] = NULL;
+  }
+
+  pthread_mutex_destroy(&pool->mutex);
+  pthread_cond_destroy(&pool->cond);
+  free(pool->mmc);
+  free(pool);
+
+  return ret;
+}
+
+memcached_st* memcached_pool_pop(memcached_pool_st* pool,
+                                 bool block,
+                                 memcached_return_t *rc)
+{
+  memcached_st *ret= NULL;
+  if ((*rc= mutex_enter(&pool->mutex)) != MEMCACHED_SUCCESS)
+    return NULL;
+
+  do
+  {
+    if (pool->firstfree > -1)
+      ret= pool->mmc[pool->firstfree--];
+    else if (pool->current_size == pool->size)
+    {
+      if (!block)
+      {
+        *rc= mutex_exit(&pool->mutex);
+        return NULL;
+      }
+
+      if (pthread_cond_wait(&pool->cond, &pool->mutex) == -1)
+      {
+        int err = errno;
+        mutex_exit(&pool->mutex);
+        errno = err;
+        *rc= MEMCACHED_ERRNO;
+        return NULL;
+      }
+    }
+    else if (grow_pool(pool) == -1)
+    {
+      *rc= mutex_exit(&pool->mutex);
+      return NULL;
+    }
+  }
+  while (ret == NULL);
+
+  *rc= mutex_exit(&pool->mutex);
+
+  return ret;
+}
+
+memcached_return_t memcached_pool_push(memcached_pool_st* pool,
+                                       memcached_st *mmc)
+{
+  memcached_return_t rc= mutex_enter(&pool->mutex);
+
+  if (rc != MEMCACHED_SUCCESS)
+    return rc;
+
+  char* version= memcached_get_user_data(mmc);
+  /* Someone updated the behavior on the object.. */
+  if (version != pool->version)
+  {
+    memcached_free(mmc);
+    memset(mmc, 0, sizeof(*mmc));
+    if (memcached_clone(mmc, pool->master) == NULL)
+    {
+      rc= MEMCACHED_SOME_ERRORS;
+    }
+  }
+
+  pool->mmc[++pool->firstfree]= mmc;
+
+  if (pool->firstfree == 0 && pool->current_size == pool->size)
+  {
+    /* we might have people waiting for a connection.. wake them up :-) */
+    pthread_cond_broadcast(&pool->cond);
+  }
+
+  memcached_return_t rval= mutex_exit(&pool->mutex);
+  if (rc == MEMCACHED_SOME_ERRORS)
+    return rc;
+
+  return rval;
+}
+
+
+memcached_return_t memcached_pool_behavior_set(memcached_pool_st *pool,
+                                               memcached_behavior_t flag,
+                                               uint64_t data)
+{
+
+  memcached_return_t rc= mutex_enter(&pool->mutex);
+  if (rc != MEMCACHED_SUCCESS)
+    return rc;
+
+  /* update the master */
+  rc= memcached_behavior_set(pool->master, flag, data);
+  if (rc != MEMCACHED_SUCCESS)
+  {
+    mutex_exit(&pool->mutex);
+    return rc;
+  }
+
+  ++pool->version;
+  memcached_set_user_data(pool->master, pool->version);
+  /* update the clones */
+  for (int xx= 0; xx <= pool->firstfree; ++xx)
+  {
+    rc= memcached_behavior_set(pool->mmc[xx], flag, data);
+    if (rc == MEMCACHED_SUCCESS)
+      memcached_set_user_data(pool->mmc[xx], pool->version);
+    else
+    {
+      memcached_free(pool->mmc[xx]);
+      memset(pool->mmc[xx], 0, sizeof(*pool->mmc[xx]));
+      if (memcached_clone(pool->mmc[xx], pool->master) == NULL)
+      {
+        /* I'm not sure what to do in this case.. this would happen
+          if we fail to push the server list inside the client..
+          I should add a testcase for this, but I believe the following
+          would work, except that you would add a hole in the pool list..
+          in theory you could end up with an empty pool....
+        */
+        free(pool->mmc[xx]);
+        pool->mmc[xx]= NULL;
+      }
+    }
+  }
+
+  return mutex_exit(&pool->mutex);
+}
+
+memcached_return_t memcached_pool_behavior_get(memcached_pool_st *pool,
+                                               memcached_behavior_t flag,
+                                               uint64_t *value)
+{
+  memcached_return_t rc= mutex_enter(&pool->mutex);
+
+  if (rc != MEMCACHED_SUCCESS)
+  {
+    return rc;
+  }
+
+  *value= memcached_behavior_get(pool->master, flag);
+
+  return mutex_exit(&pool->mutex);
+}
diff --git a/libmemcached/verbosity.c b/libmemcached/verbosity.c
new file mode 100644 (file)
index 0000000..3d34880
--- /dev/null
@@ -0,0 +1,36 @@
+#include "common.h"
+
+memcached_return_t memcached_verbosity(memcached_st *ptr, unsigned int verbosity)
+{
+  unsigned int x;
+  size_t send_length;
+  memcached_return_t rc;
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+
+  send_length= (size_t) snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
+                                 "verbosity %u\r\n", verbosity);
+  unlikely (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE)
+    return MEMCACHED_WRITE_FAILURE;
+
+  rc= MEMCACHED_SUCCESS;
+  for (x= 0; x < ptr->number_of_hosts; x++)
+  {
+    memcached_return_t rrc;
+
+    rrc= memcached_do(&ptr->hosts[x], buffer, send_length, 1);
+    if (rrc != MEMCACHED_SUCCESS)
+    {
+      rc= MEMCACHED_SOME_ERRORS;
+      continue;
+    }
+
+    unlikely (ptr->flags.use_udp)
+      continue;
+
+    rrc= memcached_response(&ptr->hosts[x], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+    if (rrc != MEMCACHED_SUCCESS)
+      rc= MEMCACHED_SOME_ERRORS;
+  }
+
+  return rc;
+}
diff --git a/libmemcached/version.c b/libmemcached/version.c
new file mode 100644 (file)
index 0000000..db2419c
--- /dev/null
@@ -0,0 +1,112 @@
+#include "common.h"
+
+const char * memcached_lib_version(void) 
+{
+  return LIBMEMCACHED_VERSION_STRING;
+}
+
+static inline memcached_return_t memcached_version_binary(memcached_st *ptr);
+static inline memcached_return_t memcached_version_textual(memcached_st *ptr);
+
+memcached_return_t memcached_version(memcached_st *ptr)
+{
+  if (ptr->flags.use_udp)
+    return MEMCACHED_NOT_SUPPORTED;
+
+  if (ptr->flags.binary_protocol)
+    return memcached_version_binary(ptr);
+  else
+    return memcached_version_textual(ptr);      
+}
+
+static inline memcached_return_t memcached_version_textual(memcached_st *ptr)
+{
+  unsigned int x;
+  size_t send_length;
+  memcached_return_t rc;
+  char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
+  char *response_ptr;
+  const char *command= "version\r\n";
+
+  send_length= strlen(command);
+
+  rc= MEMCACHED_SUCCESS;
+  for (x= 0; x < ptr->number_of_hosts; x++)
+  {
+    memcached_return_t rrc;
+
+    rrc= memcached_do(&ptr->hosts[x], command, send_length, 1);
+    if (rrc != MEMCACHED_SUCCESS)
+    {
+      rc= MEMCACHED_SOME_ERRORS;
+      continue;
+    }
+
+    rrc= memcached_response(&ptr->hosts[x], buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
+    if (rrc != MEMCACHED_SUCCESS)
+    {
+      rc= MEMCACHED_SOME_ERRORS;
+      continue;
+    }
+
+    /* Find the space, and then move one past it to copy version */
+    response_ptr= index(buffer, ' ');
+    response_ptr++;
+
+    ptr->hosts[x].major_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
+    response_ptr= index(response_ptr, '.');
+    response_ptr++;
+    ptr->hosts[x].minor_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
+    response_ptr= index(response_ptr, '.');
+    response_ptr++;
+    ptr->hosts[x].micro_version= (uint8_t)strtol(response_ptr, (char **)NULL, 10);
+  }
+
+  return rc;
+}
+
+static inline memcached_return_t memcached_version_binary(memcached_st *ptr)
+{
+  memcached_return_t rc;
+  unsigned int x;
+  protocol_binary_request_version request= { .bytes= {0}};
+  request.message.header.request.magic= PROTOCOL_BINARY_REQ;
+  request.message.header.request.opcode= PROTOCOL_BINARY_CMD_VERSION;
+  request.message.header.request.datatype= PROTOCOL_BINARY_RAW_BYTES;
+
+  rc= MEMCACHED_SUCCESS;
+  for (x= 0; x < ptr->number_of_hosts; x++) 
+  {
+    memcached_return_t rrc;
+
+    rrc= memcached_do(&ptr->hosts[x], request.bytes, sizeof(request.bytes), 1);
+    if (rrc != MEMCACHED_SUCCESS) 
+    {
+      memcached_io_reset(&ptr->hosts[x]);
+      rc= MEMCACHED_SOME_ERRORS;
+      continue;
+    }
+  }
+
+  for (x= 0; x < ptr->number_of_hosts; x++) 
+    if (memcached_server_response_count(&ptr->hosts[x]) > 0) 
+    {
+      memcached_return_t rrc;
+      char buffer[32];
+      char *p;
+
+      rrc= memcached_response(&ptr->hosts[x], buffer, sizeof(buffer), NULL);
+      if (rrc != MEMCACHED_SUCCESS) 
+      {
+        memcached_io_reset(&ptr->hosts[x]);
+        rc= MEMCACHED_SOME_ERRORS;
+        continue;
+      }
+
+      ptr->hosts[x].major_version= (uint8_t)strtol(buffer, &p, 10);
+      ptr->hosts[x].minor_version= (uint8_t)strtol(p + 1, &p, 10);
+      ptr->hosts[x].micro_version= (uint8_t)strtol(p + 1, NULL, 10);
+    }
+
+  return rc;
+}
diff --git a/libmemcached/watchpoint.h b/libmemcached/watchpoint.h
new file mode 100644 (file)
index 0000000..d8c593e
--- /dev/null
@@ -0,0 +1,45 @@
+/* LibMemcached
+ * Copyright (C) 2006-2009 Brian Aker 
+ * All rights reserved.
+ *
+ * Use and distribution licensed under the BSD license.  See
+ * the COPYING file in the parent directory for full text.
+ *
+ * Summary: Localized copy of WATCHPOINT debug symbols
+ *
+ */
+
+#ifndef LIBMEMCACHED_MEMCACHED_WATCHPOINT_H
+#define LIBMEMCACHED_MEMCACHED_WATCHPOINT_H
+
+/* Some personal debugging functions */
+#if defined(DEBUG)
+
+#include <assert.h>
+
+#define WATCHPOINT fprintf(stderr, "\nWATCHPOINT %s:%d (%s)\n", __FILE__, __LINE__,__func__);fflush(stdout);
+#define WATCHPOINT_ERROR(A) fprintf(stderr, "\nWATCHPOINT %s:%d %s\n", __FILE__, __LINE__, memcached_strerror(NULL, A));fflush(stdout);
+#define WATCHPOINT_IFERROR(A) if(A != MEMCACHED_SUCCESS)fprintf(stderr, "\nWATCHPOINT %s:%d %s\n", __FILE__, __LINE__, memcached_strerror(NULL, A));fflush(stdout);
+#define WATCHPOINT_STRING(A) fprintf(stderr, "\nWATCHPOINT %s:%d (%s) %s\n", __FILE__, __LINE__,__func__,A);fflush(stdout);
+#define WATCHPOINT_STRING_LENGTH(A,B) fprintf(stderr, "\nWATCHPOINT %s:%d (%s) %.*s\n", __FILE__, __LINE__,__func__,(int)B,A);fflush(stdout);
+#define WATCHPOINT_NUMBER(A) fprintf(stderr, "\nWATCHPOINT %s:%d (%s) %zu\n", __FILE__, __LINE__,__func__,(size_t)(A));fflush(stdout);
+#define WATCHPOINT_ERRNO(A) fprintf(stderr, "\nWATCHPOINT %s:%d (%s) %s\n", __FILE__, __LINE__,__func__, strerror(A));fflush(stdout);
+#define WATCHPOINT_ASSERT_PRINT(A,B,C) if(!(A)){fprintf(stderr, "\nWATCHPOINT ASSERT %s:%d (%s) ", __FILE__, __LINE__,__func__);fprintf(stderr, (B),(C));fprintf(stderr,"\n");fflush(stdout);}assert((A));
+#define WATCHPOINT_ASSERT(A) assert((A));
+#define WATCHPOINT_ASSERT_INITIALIZED(A) (memcached_is_initialized((A));
+
+#else
+
+#define WATCHPOINT
+#define WATCHPOINT_ERROR(A)
+#define WATCHPOINT_IFERROR(A)
+#define WATCHPOINT_STRING(A)
+#define WATCHPOINT_NUMBER(A)
+#define WATCHPOINT_ERRNO(A)
+#define WATCHPOINT_ASSERT_PRINT(A,B,C)
+#define WATCHPOINT_ASSERT(A)
+#define WATCHPOINT_ASSERT_INITIALIZED(A)
+
+#endif /* DEBUG */
+
+#endif /* LIBMEMCACHED_MEMCACHED_WATCHPOINT_H */