Fix for looping through multi-interfaces (in case one is busted)
authorBrian Aker <brian@tangent.org>
Mon, 18 Feb 2008 07:49:31 +0000 (23:49 -0800)
committerBrian Aker <brian@tangent.org>
Mon, 18 Feb 2008 07:49:31 +0000 (23:49 -0800)
ChangeLog
lib/memcached_connect.c
tests/function.c

index 21fb30c64500f6207acd32117bb5a05e46412b77..4510c19bd98707e932e44512492974292193a766 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,6 +11,7 @@
     MEMCACHED_BEHAVIOR_VERIFY_KEY was added to enable this feature.
   * More error messages on command line tools.
   * Fixed bugs in memcached_cas() operator.
+  * Fix to loop through interfaces
   
 0.15 Tue Jan 29 14:55:44 PST 2008
   * More work on the C++ API.
index d1b2dcabf1244ff51dd37117ab0bfa1f716f3c28..b4642c7630fb542ece0935e0f9312ebf31b7ab60 100644 (file)
@@ -38,6 +38,78 @@ static memcached_return set_hostinfo(memcached_server_st *server)
   return MEMCACHED_SUCCESS;
 }
 
+static memcached_return set_socket_options(memcached_server_st *ptr)
+{
+  if (ptr->type == MEMCACHED_CONNECTION_UDP)
+    return MEMCACHED_SUCCESS;
+
+  if (ptr->root->flags & MEM_NO_BLOCK)
+  {
+    int error;
+    struct linger linger;
+    struct timeval waittime;
+
+    waittime.tv_sec= 10;
+    waittime.tv_usec= 0;
+
+    linger.l_onoff= 1; 
+    linger.l_linger= MEMCACHED_DEFAULT_TIMEOUT; 
+    error= setsockopt(ptr->fd, SOL_SOCKET, SO_LINGER, 
+                      &linger, (socklen_t)sizeof(struct linger));
+    WATCHPOINT_ASSERT(error == 0);
+
+    error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDTIMEO, 
+                      &waittime, (socklen_t)sizeof(struct timeval));
+    WATCHPOINT_ASSERT(error == 0);
+
+    error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVTIMEO, 
+                      &waittime, (socklen_t)sizeof(struct timeval));
+    WATCHPOINT_ASSERT(error == 0);
+  }
+
+  if (ptr->root->flags & MEM_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_SNDBUF, 
+                      &ptr->root->recv_size, (socklen_t)sizeof(int));
+    WATCHPOINT_ASSERT(error == 0);
+  }
+
+  /* For the moment, not getting a nonblocking mode will not be fatal */
+  if (ptr->root->flags & MEM_NO_BLOCK)
+  {
+    int flags;
+
+    flags= fcntl(ptr->fd, F_GETFL, 0);
+    if (flags != -1)
+    {
+      (void)fcntl(ptr->fd, F_SETFL, flags | O_NONBLOCK);
+    }
+  }
+
+  return MEMCACHED_SUCCESS;
+}
+
 static memcached_return unix_socket_connect(memcached_server_st *ptr)
 {
   struct sockaddr_un servAddr;
@@ -99,113 +171,56 @@ static memcached_return network_connect(memcached_server_st *ptr)
         return rc;
       ptr->sockaddr_inited= MEMCACHED_ALLOCATED;
     }
-    use= ptr->address_info;
 
+    use= ptr->address_info;
     /* Create the socket */
-    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;
-    }
-
-    if (ptr->type == MEMCACHED_CONNECTION_UDP)
-      return MEMCACHED_SUCCESS;
-
-    if (ptr->root->flags & MEM_NO_BLOCK)
-    {
-      int error;
-      struct linger linger;
-      struct timeval waittime;
-
-      waittime.tv_sec= 10;
-      waittime.tv_usec= 0;
-
-      linger.l_onoff= 1; 
-      linger.l_linger= MEMCACHED_DEFAULT_TIMEOUT; 
-      error= setsockopt(ptr->fd, SOL_SOCKET, SO_LINGER, 
-                        &linger, (socklen_t)sizeof(struct linger));
-      WATCHPOINT_ASSERT(error == 0);
-
-      error= setsockopt(ptr->fd, SOL_SOCKET, SO_SNDTIMEO, 
-                        &waittime, (socklen_t)sizeof(struct timeval));
-      WATCHPOINT_ASSERT(error == 0);
-
-      error= setsockopt(ptr->fd, SOL_SOCKET, SO_RCVTIMEO, 
-                        &waittime, (socklen_t)sizeof(struct timeval));
-      WATCHPOINT_ASSERT(error == 0);
-    }
-
-    if (ptr->root->flags & MEM_TCP_NODELAY)
+    while (use != NULL)
     {
-      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_SNDBUF, 
-                        &ptr->root->recv_size, (socklen_t)sizeof(int));
-      WATCHPOINT_ASSERT(error == 0);
-    }
-
-    /* For the moment, not getting a nonblocking mode will not be fatal */
-    if (ptr->root->flags & MEM_NO_BLOCK)
-    {
-      int flags;
-
-      flags= fcntl(ptr->fd, F_GETFL, 0);
-      if (flags != -1)
+      if ((ptr->fd= socket(use->ai_family, 
+                           use->ai_socktype, 
+                           use->ai_protocol)) < 0)
       {
-        (void)fcntl(ptr->fd, F_SETFL, flags | O_NONBLOCK);
+        ptr->cached_errno= errno;
+        WATCHPOINT_ERRNO(errno);
+        return MEMCACHED_CONNECTION_SOCKET_CREATE_FAILURE;
       }
-    }
 
+      (void)set_socket_options(ptr);
 
-    /* connect to server */
+      /* connect to server */
 test_connect:
-    if (connect(ptr->fd, 
-                use->ai_addr, 
-                use->ai_addrlen) < 0)
-    {
-      switch (errno) {
-        /* We are spinning waiting on connect */
-      case EALREADY:
-      case EINPROGRESS:
-      case EINTR:
-        goto test_connect;
-      case EISCONN: /* We were spinning waiting on connect */
-        break;
-      default:
-        ptr->cached_errno= errno;
-        WATCHPOINT_ERRNO(ptr->cached_errno);
-        close(ptr->fd);
-        ptr->fd= -1;
-        return MEMCACHED_ERRNO;
+      if (connect(ptr->fd, 
+                  use->ai_addr, 
+                  use->ai_addrlen) < 0)
+      {
+        switch (errno) {
+          /* We are spinning waiting on connect */
+        case EALREADY:
+        case EINPROGRESS:
+        case EINTR:
+          goto test_connect;
+        case EISCONN: /* We were spinning waiting on connect */
+          break;
+        default:
+          ptr->cached_errno= errno;
+          WATCHPOINT_ERRNO(ptr->cached_errno);
+          close(ptr->fd);
+          ptr->fd= -1;
+        }
       }
+      else
+      {
+        WATCHPOINT_ASSERT(ptr->cursor_active == 0);
+        return MEMCACHED_SUCCESS;
+      }
+      use = use->ai_next;
     }
-
-    WATCHPOINT_ASSERT(ptr->cursor_active == 0);
   }
 
-  return MEMCACHED_SUCCESS;
+  if (ptr->fd == -1)
+    return MEMCACHED_ERRNO; /* The last error should be from connect() */
+
+  return MEMCACHED_SUCCESS; /* The last error should be from connect() */
 }
 
 
index 2a17a9ccfd4e3ad72eb7e9e75024300fa0982d94..d79e956c28701e6b7ce7a4a8dd183fa18f97dc94 100644 (file)
@@ -569,6 +569,7 @@ uint8_t set_test2(memcached_st *memc)
     rc= memcached_set(memc, key, strlen(key), 
                       value, value_length,
                       (time_t)0, (uint32_t)0);
+    WATCHPOINT_ERROR(rc);
     assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_BUFFERED);
   }