Fix for interface issues (Bug 571909 <571909@bugs.launchpad.net>)
[m6w6/libmemcached] / libmemcached / io.c
index c72aaa277e933584e4c570a3bf422b017c3f4899..30a2a1a4921396a967b71bd92bda79ec57ce3bb6 100644 (file)
@@ -32,8 +32,15 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr,
   };
   int error;
 
-  unlikely (read_or_write == MEM_WRITE) /* write */
+  if (read_or_write == MEM_WRITE) /* write */
+  {
     fds.events= POLLOUT;
+    WATCHPOINT_SET(ptr->io_wait_count.write++);
+  }
+  else
+  {
+    WATCHPOINT_SET(ptr->io_wait_count.read++);
+  }
 
   /*
    ** We are going to block on write, but at least on Solaris we might block
@@ -55,32 +62,50 @@ static memcached_return_t io_wait(memcached_server_write_instance_st ptr,
     timeout= -1;
 
   size_t loop_max= 5;
-  while (--loop_max)
+  while (--loop_max) // While loop is for ERESTART or EINTR
   {
     error= poll(&fds, 1, timeout);
 
     switch (error)
     {
-    case 1:
+    case 1: // Success!
+      WATCHPOINT_IF_LABELED_NUMBER(read_or_write && loop_max < 4, "read() times we had to loop, decremented down from 5", loop_max);
+      WATCHPOINT_IF_LABELED_NUMBER(!read_or_write && loop_max < 4, "write() times we had to loop, decremented down from 5", loop_max);
+
       return MEMCACHED_SUCCESS;
-    case 0:
+    case 0: // Timeout occured, we let the while() loop do its thing.
       return MEMCACHED_TIMEOUT;
+    default:
+      WATCHPOINT_ERRNO(errno);
+      switch (errno)
+      {
 #ifdef TARGET_OS_LINUX
-    case ERESTART:
+      case ERESTART:
 #endif
-    case EINTR:
-      continue;
-    default:
-      ptr->cached_errno= error;
-      memcached_quit_server(ptr, true);
+      case EINTR:
+        break;
+      default:
+        if (fds.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;
+        }
+        else
+        {
+          ptr->cached_errno= errno;
+        }
+        memcached_quit_server(ptr, true);
 
-      return MEMCACHED_FAILURE;
+        return MEMCACHED_FAILURE;
+      }
     }
   }
 
   /* Imposssible for anything other then -1 */
   WATCHPOINT_ASSERT(error == -1);
-  ptr->cached_errno= error;
+  ptr->cached_errno= errno;
   memcached_quit_server(ptr, true);
 
   return MEMCACHED_FAILURE;
@@ -252,11 +277,13 @@ memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
       {
         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;
+          memcached_return_t rc= MEMCACHED_ERRNO;
           switch (errno)
           {
           case EAGAIN:
@@ -287,6 +314,7 @@ memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
             for blocking I/O we do not return 0 and for non-blocking case
             it will return EGAIN if data is not immediatly available.
           */
+          WATCHPOINT_STRING("We had a zero length read()");
           memcached_quit_server(ptr, true);
           *nread= -1;
           return MEMCACHED_UNKNOWN_READ_FAILURE;
@@ -326,36 +354,8 @@ memcached_return_t memcached_io_read(memcached_server_write_instance_st ptr,
   return MEMCACHED_SUCCESS;
 }
 
-ssize_t memcached_io_writev(memcached_server_write_instance_st ptr,
-                            struct __write_vector_st *vector,
-                            size_t number_of, bool with_flush)
-{
-  ssize_t total= 0;
-
-  for (size_t x= 0; x < number_of; x++, vector++)
-  {
-    ssize_t returnable;
-
-    if ((returnable= memcached_io_write(ptr, vector->buffer, vector->length, false)) == -1)
-    {
-      return -1;
-    }
-    total+= returnable;
-  }
-
-  if (with_flush)
-  {
-    if (memcached_io_write(ptr, NULL, 0, true) == -1)
-    {
-      return -1;
-    }
-  }
-
-  return total;
-}
-
-ssize_t memcached_io_write(memcached_server_write_instance_st ptr,
-                           const void *buffer, size_t length, bool with_flush)
+static ssize_t _io_write(memcached_server_write_instance_st ptr,
+                         const void *buffer, size_t length, bool with_flush)
 {
   size_t original_length;
   const char* buffer_ptr;
@@ -431,6 +431,41 @@ ssize_t memcached_io_write(memcached_server_write_instance_st ptr,
   return (ssize_t) original_length;
 }
 
+ssize_t memcached_io_write(memcached_server_write_instance_st ptr,
+                           const void *buffer, size_t length, bool with_flush)
+{
+  return _io_write(ptr, buffer, length, with_flush);
+}
+
+ssize_t memcached_io_writev(memcached_server_write_instance_st ptr,
+                            const struct __write_vector_st *vector,
+                            size_t number_of, bool with_flush)
+{
+  ssize_t total= 0;
+
+  for (size_t x= 0; x < number_of; x++, vector++)
+  {
+    ssize_t returnable;
+
+    if ((returnable= _io_write(ptr, vector->buffer, vector->length, false)) == -1)
+    {
+      return -1;
+    }
+    total+= returnable;
+  }
+
+  if (with_flush)
+  {
+    if (memcached_io_write(ptr, NULL, 0, true) == -1)
+    {
+      return -1;
+    }
+  }
+
+  return total;
+}
+
+
 memcached_return_t memcached_io_close(memcached_server_write_instance_st ptr)
 {
   if (ptr->fd == -1)
@@ -576,6 +611,8 @@ static ssize_t io_flush(memcached_server_write_instance_st ptr,
     if (sent_length == -1)
     {
       ptr->cached_errno= errno;
+      WATCHPOINT_ERRNO(errno);
+      WATCHPOINT_NUMBER(errno);
       switch (errno)
       {
       case ENOBUFS: