Latest of libtest.
[m6w6/libmemcached] / libmemcached / connect.cc
index b81b25b992bf8fc57d5f7929cba9e2a4ff71b3cb..9d50e5c0dc05ecc1ad1f0ecd754077a1ff9eda15 100644 (file)
@@ -78,6 +78,7 @@ static memcached_return_t connect_poll(memcached_server_st *server)
       }
     case 0:
       {
+        server->io_wait_count.timeouts++;
         return memcached_set_error(*server, MEMCACHED_TIMEOUT, MEMCACHED_AT);
       }
 
@@ -129,8 +130,9 @@ static memcached_return_t connect_poll(memcached_server_st *server)
   return memcached_set_errno(*server, get_socket_errno(), MEMCACHED_AT);
 }
 
-memcached_return_t set_hostinfo(memcached_server_st *server)
+static memcached_return_t set_hostinfo(memcached_server_st *server)
 {
+  assert(server->type != MEMCACHED_CONNECTION_UNIX_SOCKET);
   if (server->address_info)
   {
     freeaddrinfo(server->address_info);
@@ -478,7 +480,10 @@ static memcached_return_t network_connect(memcached_server_st *server)
       timeout_error_occured= true;
       break;
 
+    case EAGAIN:
+#if EWOULDBLOCK != EAGAIN
     case EWOULDBLOCK:
+#endif
     case EINPROGRESS: // nonblocking mode - first return
     case EALREADY: // nonblocking mode - subsequent returns
       {
@@ -554,6 +559,9 @@ static memcached_return_t network_connect(memcached_server_st *server)
 */
 static memcached_return_t backoff_handling(memcached_server_write_instance_st server, bool& in_timeout)
 {
+  struct timeval curr_time;
+  bool _gettime_success= (gettimeofday(&curr_time, NULL) == 0);
+
   /* 
     If we hit server_failure_limit then something is completely wrong about the server.
 
@@ -568,7 +576,21 @@ static memcached_return_t backoff_handling(memcached_server_write_instance_st se
     if (_is_auto_eject_host(server->root))
     {
       set_last_disconnected_host(server);
-      run_distribution((memcached_st *)server->root);
+
+      // Retry dead servers if requested
+      if (_gettime_success and server->root->dead_timeout > 0)
+      {
+        server->next_retry= curr_time.tv_sec +server->root->dead_timeout;
+
+        // We only retry dead servers once before assuming failure again
+        server->server_failure_counter= server->root->server_failure_limit -1;
+      }
+
+      memcached_return_t rc;
+      if (memcached_failed(rc= run_distribution((memcached_st *)server->root)))
+      {
+        return memcached_set_error(*server, rc, MEMCACHED_AT, memcached_literal_param("Backoff handling failed during run_distribution"));
+      }
 
       return memcached_set_error(*server, MEMCACHED_SERVER_MARKED_DEAD, MEMCACHED_AT);
     }
@@ -584,9 +606,6 @@ static memcached_return_t backoff_handling(memcached_server_write_instance_st se
 
   if (server->state == MEMCACHED_SERVER_STATE_IN_TIMEOUT)
   {
-    struct timeval curr_time;
-    bool _gettime_success= (gettimeofday(&curr_time, NULL) == 0);
-
     /*
       If next_retry is less then our current time, then we reset and try everything again.
     */
@@ -605,7 +624,7 @@ static memcached_return_t backoff_handling(memcached_server_write_instance_st se
   return MEMCACHED_SUCCESS;
 }
 
-memcached_return_t memcached_connect(memcached_server_write_instance_st server)
+static memcached_return_t _memcached_connect(memcached_server_write_instance_st server, const bool set_last_disconnected)
 {
   if (server->fd != INVALID_SOCKET)
   {
@@ -627,6 +646,11 @@ memcached_return_t memcached_connect(memcached_server_write_instance_st server)
     return memcached_set_error(*server, MEMCACHED_INVALID_HOST_PROTOCOL, MEMCACHED_AT, memcached_literal_param("SASL is not supported for UDP connections"));
   }
 
+  if (server->hostname[0] == '/')
+  {
+    server->type= MEMCACHED_CONNECTION_UNIX_SOCKET;
+  }
+
   /* We need to clean up the multi startup piece */
   switch (server->type)
   {
@@ -659,25 +683,39 @@ memcached_return_t memcached_connect(memcached_server_write_instance_st server)
     memcached_mark_server_as_clean(server);
     return rc;
   }
-
-  set_last_disconnected_host(server);
-  if (memcached_has_current_error(*server))
-  {
-    memcached_mark_server_for_timeout(server);
-    assert(memcached_failed(memcached_server_error_return(server)));
-  }
-  else
+  else if (set_last_disconnected)
   {
-    memcached_set_error(*server, rc, MEMCACHED_AT);
-    memcached_mark_server_for_timeout(server);
-  }
+    set_last_disconnected_host(server);
+    if (memcached_has_current_error(*server))
+    {
+      memcached_mark_server_for_timeout(server);
+      assert(memcached_failed(memcached_server_error_return(server)));
+    }
+    else
+    {
+      memcached_set_error(*server, rc, MEMCACHED_AT);
+      memcached_mark_server_for_timeout(server);
+    }
 
-  LIBMEMCACHED_MEMCACHED_CONNECT_END();
+    LIBMEMCACHED_MEMCACHED_CONNECT_END();
 
-  if (in_timeout)
-  {
-    return memcached_set_error(*server, MEMCACHED_SERVER_TEMPORARILY_DISABLED, MEMCACHED_AT);
+    if (in_timeout)
+    {
+      char buffer[1024];
+      int snprintf_length= snprintf(buffer, sizeof(buffer), "%s:%d", server->hostname, int(server->port));
+      return memcached_set_error(*server, MEMCACHED_SERVER_TEMPORARILY_DISABLED, MEMCACHED_AT, buffer, snprintf_length);
+    }
   }
 
   return rc;
 }
+
+memcached_return_t memcached_connect_try(memcached_server_write_instance_st server)
+{
+  return _memcached_connect(server, false);
+}
+
+memcached_return_t memcached_connect(memcached_server_write_instance_st server)
+{
+  return _memcached_connect(server, true);
+}