Add support for AUTO_EJECT_HOST
[awesomized/libmemcached] / libmemcached / memcached_connect.c
index 8e0e4208e864f11556ed8aaa9927aa8b15400c11..fb79c80ad5d7296d900878a6e81406c80aa77a35 100644 (file)
@@ -121,7 +121,7 @@ static memcached_return set_socket_options(memcached_server_st *ptr)
   }
 
   /* For the moment, not getting a nonblocking mode will not be fatal */
-  if (ptr->root->flags & MEM_NO_BLOCK)
+  if ((ptr->root->flags & MEM_NO_BLOCK) || ptr->root->connect_timeout)
   {
     int flags;
 
@@ -185,15 +185,6 @@ static memcached_return network_connect(memcached_server_st *ptr)
   {
     struct addrinfo *use;
 
-    if (ptr->root->server_failure_limit != 0) 
-    {
-      if (ptr->server_failure_counter >= ptr->root->server_failure_limit) 
-      {
-          memcached_server_remove(ptr);
-          return MEMCACHED_FAILURE;
-      }
-    }
-
     if (!ptr->sockaddr_inited ||
         (!(ptr->root->flags & MEM_USE_CACHE_LOOKUPS)))
     {
@@ -253,7 +244,7 @@ static memcached_return network_connect(memcached_server_st *ptr)
               int err;
               int len = sizeof (err);
               (void)getsockopt(ptr->fd, SOL_SOCKET, SO_ERROR, &err, &len);
-              ptr->cached_errno= errno;
+              ptr->cached_errno= (err == 0) ? errno : err;
             }
 
             (void)close(ptr->fd);
@@ -275,7 +266,7 @@ static memcached_return network_connect(memcached_server_st *ptr)
       if (ptr->fd != -1)
       {
         /* restore flags */ 
-        if (ptr->root->connect_timeout && (flags & O_NONBLOCK) == 0) 
+        if (ptr->root->connect_timeout && (ptr->root->flags & MEM_NO_BLOCK) == 0) 
           (void)fcntl(ptr->fd, F_SETFL, flags & ~O_NONBLOCK);
 
         WATCHPOINT_ASSERT(ptr->cursor_active == 0);
@@ -297,6 +288,8 @@ static memcached_return network_connect(memcached_server_st *ptr)
         ptr->next_retry= next_time.tv_sec + ptr->root->retry_timeout;
     }
     ptr->server_failure_counter+= 1;
+    if (ptr->cached_errno == 0)
+      return MEMCACHED_TIMEOUT;
     return MEMCACHED_ERRNO; /* The last error should be from connect() */
   }
 
@@ -310,14 +303,29 @@ memcached_return memcached_connect(memcached_server_st *ptr)
   memcached_return rc= MEMCACHED_NO_SERVERS;
   LIBMEMCACHED_MEMCACHED_CONNECT_START();
 
-  if (ptr->root->retry_timeout)
+  /* both retry_timeout and server_failure_limit must be set in order to delay retrying a server on error. */
+  if (ptr->root->retry_timeout && ptr->root->server_failure_limit)
   {
     struct timeval next_time;
 
     gettimeofday(&next_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= next_time.tv_sec + ptr->root->retry_timeout;
+      ptr->server_failure_counter= 0;
+    }
+
     if (next_time.tv_sec < ptr->next_retry)
-      return MEMCACHED_TIMEOUT;
+    {
+      if (memcached_behavior_get(ptr->root, MEMCACHED_BEHAVIOR_AUTO_EJECT_HOSTS))
+        run_distribution(ptr->root);
+
+      return MEMCACHED_SERVER_MARKED_DEAD;
+    }
   }
+
   /* We need to clean up the multi startup piece */
   switch (ptr->type)
   {