Rewrote internal connect function to do by demand (aka only open up
authorBrian Aker <brian@tangent.org>
Sun, 7 Oct 2007 23:09:57 +0000 (16:09 -0700)
committerBrian Aker <brian@tangent.org>
Sun, 7 Oct 2007 23:09:57 +0000 (16:09 -0700)
connections as we need them).

Found a bug in stats where we were hardcoding the serer key (which
ended up a a hang when requesting stats).

lib/common.h
lib/memcached_auto.c
lib/memcached_connect.c
lib/memcached_delete.c
lib/memcached_flush.c
lib/memcached_get.c
lib/memcached_stats.c
lib/memcached_storage.c
lib/memcached_verbosity.c

index baf75242bcd16f0fa2b9d32847e571eb777bf44b..bc428c0229d37322694662bfa1f31080c7e040b4 100644 (file)
@@ -26,7 +26,7 @@ typedef enum {
 } memcached_flags;
 
 void md5_signature(unsigned char *key, unsigned int length, unsigned char *result);
-memcached_return memcached_connect(memcached_st *ptr);
+memcached_return memcached_connect(memcached_st *ptr, unsigned int server_key);
 memcached_return memcached_response(memcached_st *ptr, 
                                     char *buffer, size_t buffer_length,
                                     unsigned int server_key);
index 653764ab981a51a2ef61b86f63b68eb3338b1177..69b975c1603598296c8618bba6b532eb981e4ecc 100644 (file)
@@ -11,13 +11,11 @@ static memcached_return memcached_auto(memcached_st *ptr,
   char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
   unsigned int server_key;
 
-  rc= memcached_connect(ptr);
+  server_key= memcached_generate_hash(ptr, key, key_length);
 
-  if (rc != MEMCACHED_SUCCESS)
+  if ((rc= memcached_connect(ptr, server_key)) != MEMCACHED_SUCCESS)
     return rc;
 
-  server_key= memcached_generate_hash(ptr, key, key_length);
-
   send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
                         "%s %.*s %u\r\n", verb, 
                         (int)key_length, key,
index 78a7d70337aa560773e50e41c5307f0eb2001689..f95b8e7d752f3115298cf85310b63c1d93a9bb69 100644 (file)
@@ -5,83 +5,96 @@
 #include <sys/socket.h>
 #include <netinet/tcp.h>
 
-memcached_return memcached_connect(memcached_st *ptr)
+memcached_return memcached_real_connect(memcached_st *ptr, unsigned int server_key)
 {
-  unsigned int x;
   struct sockaddr_in localAddr, servAddr;
   struct hostent *h;
 
-  LIBMEMCACHED_MEMCACHED_CONNECT_START();
-
-  if (ptr->connected == ptr->number_of_hosts)
-    return MEMCACHED_SUCCESS;
+  if (ptr->hosts[server_key].fd == -1)
+  {
+    if ((h= gethostbyname(ptr->hosts[server_key].hostname)) == NULL)
+      return MEMCACHED_HOST_LOCKUP_FAILURE;
 
-  if (!ptr->hosts)
-    return MEMCACHED_NO_SERVERS;
+    servAddr.sin_family= h->h_addrtype;
+    memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
+    servAddr.sin_port = htons(ptr->hosts[server_key].port);
 
-  for (x= 0; x < ptr->number_of_hosts; x++)
-  {
-    if (ptr->hosts[x].fd == -1)
+    /* Create the socket */
+    if ((ptr->hosts[server_key].fd= socket(AF_INET, SOCK_STREAM, 0)) < 0)
     {
-      if ((h= gethostbyname(ptr->hosts[x].hostname)) == NULL)
-        return MEMCACHED_HOST_LOCKUP_FAILURE;
-
-      servAddr.sin_family= h->h_addrtype;
-      memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
-      servAddr.sin_port = htons(ptr->hosts[x].port);
+      ptr->my_errno= errno;
+      return MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE;
+    }
 
-      /* Create the socket */
-      if ((ptr->hosts[x].fd= socket(AF_INET, SOCK_STREAM, 0)) < 0)
-      {
-        ptr->my_errno= errno;
-        return MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE;
-      }
 
+    /* bind any port number */
+    localAddr.sin_family = AF_INET;
+    localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+    localAddr.sin_port = htons(0);
 
-      /* bind any port number */
-      localAddr.sin_family = AF_INET;
-      localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
-      localAddr.sin_port = htons(0);
+    /* For the moment, not getting a nonblocking mode will note be fatal */
+    if (ptr->flags & MEM_NO_BLOCK)
+    {
+      int flags;
 
-      /* For the moment, not getting a nonblocking mode will note be fatal */
-      if (ptr->flags & MEM_NO_BLOCK)
-      {
-        int flags;
-      
-        flags= fcntl(ptr->hosts[x].fd, F_GETFL, 0);
-        if (flags != -1)
-          (void)fcntl(ptr->hosts[x].fd, F_SETFL, flags | O_NONBLOCK);
-      }
+      flags= fcntl(ptr->hosts[server_key].fd, F_GETFL, 0);
+      if (flags != -1)
+        (void)fcntl(ptr->hosts[server_key].fd, F_SETFL, flags | O_NONBLOCK);
+    }
 
-      if (ptr->flags & MEM_TCP_NODELAY)
-      {
-        int flag= 1;
+    if (ptr->flags & MEM_TCP_NODELAY)
+    {
+      int flag= 1;
 
-        setsockopt(ptr->hosts[x].fd, IPPROTO_TCP, TCP_NODELAY, 
-                   &flag, (socklen_t)sizeof(int));
-      }
+      setsockopt(ptr->hosts[server_key].fd, IPPROTO_TCP, TCP_NODELAY, 
+                 &flag, (socklen_t)sizeof(int));
+    }
 
-      /* connect to server */
+    /* connect to server */
 test_connect:
-      if (connect(ptr->hosts[x].fd, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
-      {
-        switch (errno) {
-          /* We are spinning waiting on connect */
-        case EINPROGRESS:
-        case EINTR:
-          goto test_connect;
-        case EISCONN: /* We were spinning waiting on connect */
-          break;
-        default:
+    if (connect(ptr->hosts[server_key].fd, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
+    {
+      switch (errno) {
+        /* We are spinning waiting on connect */
+      case EINPROGRESS:
+      case EINTR:
+        goto test_connect;
+      case EISCONN: /* We were spinning waiting on connect */
+        break;
+      default:
         ptr->my_errno= errno;
         return MEMCACHED_HOST_LOCKUP_FAILURE;
       }
-
       ptr->connected++;
-      }
     }
   }
-  LIBMEMCACHED_MEMCACHED_CONNECT_END();
 
   return MEMCACHED_SUCCESS;
 }
+
+
+memcached_return memcached_connect(memcached_st *ptr, unsigned int server_key)
+{
+  memcached_return rc;
+  LIBMEMCACHED_MEMCACHED_CONNECT_START();
+
+  if (ptr->connected == ptr->number_of_hosts)
+    return MEMCACHED_SUCCESS;
+
+  if (!ptr->hosts)
+    return MEMCACHED_NO_SERVERS;
+
+  /* We need to clean up the multi startup piece */
+  if (server_key)
+    rc= memcached_real_connect(ptr, server_key);
+  else
+  {
+    unsigned int x;
+
+    for (x= 0; x < ptr->number_of_hosts; x++)
+      rc= memcached_real_connect(ptr, x);
+  }
+  LIBMEMCACHED_MEMCACHED_CONNECT_END();
+
+  return rc;
+}
index 6fa2d4a8ff6833a3527f38ef57a31921439e1e7e..ff085453ab63a0fc602df81205b3348c59ddd118 100644 (file)
@@ -10,12 +10,11 @@ memcached_return memcached_delete(memcached_st *ptr, char *key, size_t key_lengt
 
   LIBMEMCACHED_MEMCACHED_DELETE_START();
 
-  rc= memcached_connect(ptr);
+  server_key= memcached_generate_hash(ptr, key, key_length);
 
-  if (rc != MEMCACHED_SUCCESS)
+  if ((rc= memcached_connect(ptr, server_key)) != MEMCACHED_SUCCESS)
     return rc;
 
-  server_key= memcached_generate_hash(ptr, key, key_length);
 
   if (expiration)
     send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
index 41b193fc3f9ac6a3ff4c8196aa00bd86fd03bc51..8538aaa0cc753f7e6c963d542d140b1f8cb32a2a 100644 (file)
@@ -8,7 +8,7 @@ memcached_return memcached_flush(memcached_st *ptr, time_t expiration)
   char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
   LIBMEMCACHED_MEMCACHED_FLUSH_START();
 
-  rc= memcached_connect(ptr);
+  rc= memcached_connect(ptr, 0);
 
   if (rc != MEMCACHED_SUCCESS)
     rc= MEMCACHED_SOME_ERRORS;
index 8ea1fabc964c59888be79358d167304fc65f0fb0..c7c21d1ee43ad7518700d1c6f026ca1323dcd62a 100644 (file)
@@ -130,14 +130,14 @@ char *memcached_get(memcached_st *ptr, char *key, size_t key_length,
   char *value;
   LIBMEMCACHED_MEMCACHED_GET_START();
 
+  server_key= memcached_generate_hash(ptr, key, key_length);
+
   *value_length= 0;
-  *error= memcached_connect(ptr);
+  *error= memcached_connect(ptr, server_key);
 
   if (*error != MEMCACHED_SUCCESS)
     goto error;
 
-  server_key= memcached_generate_hash(ptr, key, key_length);
-
   send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, "get %.*s\r\n", 
                         (int)key_length, key);
 
@@ -195,11 +195,6 @@ memcached_return memcached_mget(memcached_st *ptr,
   ptr->cursor_server= 0;
   memset(buffer, 0, HUGE_STRING_LEN);
 
-  rc= memcached_connect(ptr);
-
-  if (rc != MEMCACHED_SUCCESS)
-    return rc;
-
   cursor_key_exec= (memcached_string_st **)malloc(sizeof(memcached_string_st *) * ptr->number_of_hosts);
   memset(cursor_key_exec, 0, sizeof(memcached_string_st *) * ptr->number_of_hosts);
 
@@ -240,6 +235,9 @@ memcached_return memcached_mget(memcached_st *ptr,
   {
     if (cursor_key_exec[x])
     {
+      /* We need to doo something about non-connnected hosts in the future */
+      rc= memcached_connect(ptr, x);
+
       memcached_string_st *string= cursor_key_exec[x];
       memcached_string_append(ptr, string, "\r\n", 2);
 
index b3a5781213e8f9f05368ed23f2ee085a431e0ee0..f71deb46c4d713a3acc7ee297c0d8edfc0a7f6e4 100644 (file)
@@ -225,7 +225,7 @@ static memcached_return memcached_stats_fetch(memcached_st *ptr,
   char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
   size_t send_length, sent_length;
 
-  rc= memcached_connect(ptr);
+  rc= memcached_connect(ptr, server_key);
 
   if (rc != MEMCACHED_SUCCESS)
     return rc;
@@ -247,7 +247,7 @@ static memcached_return memcached_stats_fetch(memcached_st *ptr,
 
   while (1)
   {
-    rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 0);
+    rc= memcached_response(ptr, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, server_key);
 
     if (rc == MEMCACHED_STAT)
     {
@@ -283,13 +283,6 @@ memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_retur
   memcached_return rc;
   memcached_stat_st *stats;
 
-  rc= memcached_connect(ptr);
-  if (rc != MEMCACHED_SUCCESS)
-  {
-    *error= rc;
-    return NULL;
-  }
-
   stats= (memcached_stat_st *)malloc(sizeof(memcached_st)*(ptr->number_of_hosts+1));
   if (!stats)
   {
@@ -299,10 +292,12 @@ memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_retur
   }
   memset(stats, 0, sizeof(memcached_st)*(ptr->number_of_hosts+1));
 
+  rc= MEMCACHED_SUCCESS;
   for (x= 0; x < ptr->number_of_hosts; x++)
   {
-    rc= memcached_stats_fetch(ptr, stats+x, args, x);
-    if (rc != MEMCACHED_SUCCESS)
+    memcached_return temp_return;
+    temp_return= memcached_stats_fetch(ptr, stats+x, args, x);
+    if (temp_return != MEMCACHED_SUCCESS)
       rc= MEMCACHED_SOME_ERRORS;
   }
 
@@ -320,11 +315,6 @@ memcached_return memcached_stat_servername(memcached_stat_st *stat, char *args,
 
   memcached_server_add(&memc, hostname, port);
 
-  rc= memcached_connect(&memc);
-
-  if (rc != MEMCACHED_SUCCESS)
-    return rc;
-
   rc= memcached_stats_fetch(&memc, stat, args, 0);
 
   memcached_free(&memc);
index eabe6ce981bd6ea61bb16b3b4253010c9dbab750..6b76375cdb20bd62505f9ee5e5fcec5061af048e 100644 (file)
@@ -37,15 +37,15 @@ static memcached_return memcached_send(memcached_st *ptr,
 
   memset(buffer, 0, MEMCACHED_DEFAULT_COMMAND_SIZE);
 
-  rc= memcached_connect(ptr);
-  if (rc != MEMCACHED_SUCCESS)
-    return rc;
-
   /* Leaveing this assert in since only a library fubar could blow this */
   assert(ptr->write_buffer_offset == 0);
 
   server_key= memcached_generate_hash(ptr, key, key_length);
 
+  rc= memcached_connect(ptr, server_key);
+  if (rc != MEMCACHED_SUCCESS)
+    return rc;
+
   write_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 
                         "%s %.*s %x %llu %zu\r\n", storage_op_string(verb),
                         (int)key_length, key, flags, 
index 5d308aa2380399ff0da0e15553e3604fa37d8af7..6d35664232cc80ac1cad96bb87fc119c684c78c9 100644 (file)
@@ -7,7 +7,7 @@ memcached_return memcached_verbosity(memcached_st *ptr, unsigned int verbosity)
   memcached_return rc;
   char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
 
-  rc= memcached_connect(ptr);
+  rc= memcached_connect(ptr, 0);
 
   if (rc != MEMCACHED_SUCCESS)
     rc= MEMCACHED_SOME_ERRORS;