apr-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j..@apache.org
Subject svn commit: r656356 - /apr/apr/branches/1.3.x/network_io/unix/sendrecv.c
Date Wed, 14 May 2008 18:47:24 GMT
Author: jim
Date: Wed May 14 11:47:24 2008
New Revision: 656356

URL: http://svn.apache.org/viewvc?rev=656356&view=rev
Log:
Backport r654788 and r656355 for fully functional
Darwin sendfile impl.

Modified:
    apr/apr/branches/1.3.x/network_io/unix/sendrecv.c

Modified: apr/apr/branches/1.3.x/network_io/unix/sendrecv.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.3.x/network_io/unix/sendrecv.c?rev=656356&r1=656355&r2=656356&view=diff
==============================================================================
--- apr/apr/branches/1.3.x/network_io/unix/sendrecv.c (original)
+++ apr/apr/branches/1.3.x/network_io/unix/sendrecv.c Wed May 14 11:47:24 2008
@@ -406,15 +406,15 @@
 #elif defined(DARWIN)
 
 /* OS/X Release 10.5 or greater */
-apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file,
-                                 apr_hdtr_t * hdtr, apr_off_t * offset,
-                                 apr_size_t * len, apr_int32_t flags)
+apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file,
+                                 apr_hdtr_t *hdtr, apr_off_t *offset,
+                                 apr_size_t *len, apr_int32_t flags)
 {
     apr_off_t nbytes = 0;
     apr_off_t bytes_to_send = *len;
-    apr_size_t header_bytes_written = 0;
+    apr_off_t bytes_sent = 0;
+    apr_status_t arv;
     int rv = 0;
-    int sent_headers = 0;
 
     /* Ignore flags for now. */
     flags = 0;
@@ -425,9 +425,35 @@
 
     /* OS X can send the headers/footers as part of the system call, 
      * but how it counts bytes isn't documented properly. We use 
-     * writev() instead.
+     * apr_socket_sendv() instead.
      */
+     if (hdtr->numheaders > 0) {
+        apr_size_t hbytes;
+        int i;
+
+        /* Now write the headers */
+        arv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders,
+                               &hbytes);
+        if (arv != APR_SUCCESS) {
+            *len = 0;
+            return errno;
+        }
+        bytes_sent = hbytes;
+
+        hbytes = 0;
+        for (i = 0; i < hdtr->numheaders; i++) {
+            hbytes += hdtr->headers[i].iov_len;
+        }
+        if (bytes_sent < hbytes) {
+            *len = bytes_sent;
+            return APR_SUCCESS;
+        }
+    }
+
     do {
+        if (!bytes_to_send) {
+            break;
+        }
         if (sock->options & APR_INCOMPLETE_WRITE) {
             apr_status_t arv;
             sock->options &= ~APR_INCOMPLETE_WRITE;
@@ -438,72 +464,40 @@
             }
         }
 
-        if (!sent_headers) {
-            if (hdtr->numheaders) {
-                rv = writev(sock->socketdes,
-                            hdtr->headers,
-                            hdtr->numheaders);
-                if (rv > 0) {
-                    header_bytes_written = rv;
-                    sent_headers = 1;
-                    rv = 0;
-                }
-            }
-            else {
-                sent_headers = 1;
-            }
-        }
-
-        if (bytes_to_send && sent_headers) {
-            /* We won't dare call sendfile() if we don't have
-             * header or file bytes to send because nbytes == 0
-             * means send the remaining file to EOF.
-             */
-            nbytes = bytes_to_send;
-            rv = sendfile(file->filedes, /* file to be sent */
-                          sock->socketdes, /* socket */
-                          *offset,       /* where in the file to start */
-                          &nbytes,       /* number of bytes to write/written */
-                          NULL,          /* Headers/footers */
-                          flags);        /* undefined, set to 0 */
-
-            bytes_to_send -= nbytes;
-            if (rv == -1) {
-                if (errno == EAGAIN) {
-                    if (sock->timeout > 0) {
-                        sock->options |= APR_INCOMPLETE_WRITE;
-                    }
-                    /* BSD's sendfile can return -1/EAGAIN even if it
-                     * sent bytes.  Sanitize the result so we get normal EAGAIN
-                     * semantics w.r.t. bytes sent.
-                     */
-                    else if (nbytes) {
-                        /* normal exit for a big file & non-blocking io */
-                        (*len) = nbytes + header_bytes_written;
-                        return APR_SUCCESS;
-                    }
+        nbytes = bytes_to_send;
+        rv = sendfile(file->filedes, /* file to be sent */
+                      sock->socketdes, /* socket */
+                      *offset,       /* where in the file to start */
+                      &nbytes,       /* number of bytes to write/written */
+                      NULL,          /* Headers/footers */
+                      flags);        /* undefined, set to 0 */
+
+        bytes_sent += nbytes;
+        bytes_to_send -= nbytes;
+        (*offset) += nbytes;
+        if (rv == -1) {
+            if (errno == EAGAIN) {
+                if (sock->timeout > 0) {
+                    sock->options |= APR_INCOMPLETE_WRITE;
                 }
-            }
-            else {       /* rv == 0 (or the kernel is broken) */
-                if (nbytes == 0) {
-                    /* Most likely the file got smaller after the stat.
-                     * Return an error so the caller can do the Right Thing.
-                     */
-                    (*len) = nbytes + header_bytes_written;
-                    return APR_EOF;
+                /* BSD's sendfile can return -1/EAGAIN even if it
+                 * sent bytes.  Sanitize the result so we get normal EAGAIN
+                 * semantics w.r.t. bytes sent.
+                 */
+                else if (nbytes) {
+                    /* normal exit for a big file & non-blocking io */
+                    (*len) = bytes_sent;
+                    return APR_SUCCESS;
                 }
             }
         }
-
-        if (sent_headers && !bytes_to_send) {
-            /* just trailer bytes... use writev()
-             */
-            rv = writev(sock->socketdes,
-                        hdtr->trailers,
-                        hdtr->numtrailers);
-            if (rv > 0) {
-                nbytes += rv;
-                rv = 0;
+        else {       /* rv == 0 (or the kernel is broken) */
+            if (nbytes == 0) {
+                /* Most likely the file got smaller after the stat.
+                 * Return an error so the caller can do the Right Thing.
+                 */
+                (*len) = bytes_sent;
+                return APR_EOF;
             }
         }
 
@@ -512,7 +506,20 @@
         }
     } while (rv == -1 && (errno == EINTR || errno == EAGAIN));
 
-    (*len) = nbytes + header_bytes_written;
+    /* Now write the footers */
+    if (hdtr->numtrailers > 0) {
+        apr_size_t tbytes;
+        arv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers, 
+                               &tbytes);
+        bytes_sent += tbytes;
+        if (arv != APR_SUCCESS) {
+            *len = bytes_sent;
+            rv = errno;
+            return rv;
+        }
+    }
+
+    (*len) = bytes_sent;
     if (rv == -1) {
         return errno;
     }



Mime
View raw message