httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Dave Hill <ddh...@laurel.zk3.dec.com>
Subject ap_sendfile() impementation for Tru64 UNIX
Date Thu, 13 Jul 2000 00:59:33 GMT


I mentioned ap_sendfile was not available for Tru64 earlier and
said I would take a crack at it. Well, it got me interested,
and so here it is :-)

Attached is a diff for a proposed ap_sendfile for Tru64 unix. sendfile()
is only available on v5.0(a?) and later. I tested this outside of
Apache by building a wrapper program that sent a single file to a
listener program. Although this works, I did not really get to test the
error paths. Although I based this on the __linux__ flavor I am not
sure I really,truely understand some of the partial write/ error
cases/blocking cases. Code review by someone who understands better how
ap_sendfile fits into the whole would be a very good idea.


*** sendrecv.c.orig	Wed Jul 12 15:35:10 2000
--- sendrecv.c	Wed Jul 12 20:47:16 2000
***************
*** 633,638 ****
      }
      return APR_SUCCESS;
  }
  #else
! #endif /* __linux__, __FreeBSD__, __HPUX__, _AIX */
  #endif /* APR_HAS_SENDFILE */
--- 633,777 ----
      }
      return APR_SUCCESS;
  }
+ #elif defined(__osf__) && defined (__alpha)
+ /*
+  * ap_sendfile for Tru64 Unix. 
+  */
+ ap_status_t ap_sendfile(ap_socket_t * sock, ap_file_t * file,
+ 		    ap_hdtr_t * hdtr, ap_off_t * offset, ap_size_t * len,
+ 		    ap_int32_t flags)
+ {
+     off_t nbytes = 0;
+     int rv, i;
+     ap_status_t arv;
+     struct iovec headerstruct[2];
+     size_t bytes_to_send = *len;
+ 
+     /* Ignore flags for now. */
+     flags = 0;
+ 
+     /*
+      Tru64 can send 1 header and 1 trailer per sendfile().
+      with > 1, we have the choice to build 1 header/trailer or
+      to send them before/after the sendfile. I did the later.
+ 
+      headerstruct is a 2 iovec array with the first pointing
+      to the header, the second pointing to the trailer.
+      iov_len must be set to zero on any not being used.
+      */
+ 
+     if(hdtr->numheaders == 0) {
+ 	headerstruct[0].iov_len = 0;
+     } else if (hdtr->numheaders == 1) {
+ 	headerstruct[0].iov_base = hdtr->headers[0].iov_base;
+ 	headerstruct[0].iov_len = hdtr->headers[0].iov_len;
+     } else {
+ 	ap_size_t hdrbytes = 0;
+ 	/* sending them in bits.. if more than one header/trailer */
+ 	headerstruct[0].iov_len = 0;
+ 
+ 	arv = ap_sendv(sock, hdtr->headers, hdtr->numheaders, &hdrbytes);
+ 	if (arv != APR_SUCCESS) {
+ 	    *len = 0;
+ 	    return errno;
+ 	}
+ 
+ 	nbytes += hdrbytes;
+ 
+ 	/* If this was a partial write and we aren't doing timeouts, 
+ 	 * return now with the partial byte count; this is a non-blocking 
+ 	 * socket.
+ 	 */
+ 	if (sock->timeout <= 0) {
+ 	    ap_size_t total_hdrbytes = 0;
+ 	    for (i = 0; i < hdtr->numheaders; i++) {
+ 		total_hdrbytes += hdtr->headers[i].iov_len;
+ 	    }
+ 	    if (hdrbytes < total_hdrbytes) {
+ 		*len = hdrbytes;
+ 		return APR_SUCCESS;
+ 	    }
+ 	}
+     }
+ 
+     if(hdtr->numtrailers == 0) {
+ 	headerstruct[1].iov_len = 0;
+     } else if (hdtr->numtrailers == 1) {
+ 	headerstruct[1].iov_base = hdtr->trailers[0].iov_base;
+ 	headerstruct[1].iov_len = hdtr->trailers[0].iov_len;
+     } else {
+ 	/* we will send them after the file as more than one */
+ 	headerstruct[1].iov_len = 0;
+     }
+ 
+     if (bytes_to_send) {
+ 	/* We won't dare call sendfile() if we don't have
+ 	 * header or file bytes to send because bytes_to_send == 0
+ 	 * means send the whole file.
+ 	 */
+ 	do {
+ 	    rv = sendfile(
+ 		  sock->socketdes, /* socket */
+ 		  file->filedes,   /* file to be sent */
+ 		  *offset,         /* where in the file to start */
+ 		  bytes_to_send,   /* number of bytes to send */
+ 		  headerstruct,    /* Headers/footers */
+ 		  flags);          /* currently unused */
+ 	} while (rv == -1 && errno == EINTR);
+     } else 
+ 	rv = 0;
+ 
+     if (rv == -1 && 
+ 	(errno == EAGAIN || errno == EWOULDBLOCK) && 
+ 	sock->timeout > 0) {
+ 	ap_status_t arv = wait_for_io_or_timeout(sock, 0);
+ 
+ 	if (arv != APR_SUCCESS) {
+ 	    *len = 0;
+ 	    return arv;
+ 	}
+ 	else {
+ 	    do {
+ 		rv = sendfile(
+ 		  sock->socketdes, /* socket */
+ 		  file->filedes, /* file to be sent */
+ 		  *offset,       /* where in the file to start */
+ 		  bytes_to_send, /* number of bytes to send */
+ 		  headerstruct, /* Headers/footers */
+ 		  flags        /* undefined, set to 0 */
+ 		    );
+ 	    } while (rv == -1 && errno == EINTR);
+ 	}
+     }
+ 
+     if(rv != -1) {
+ 	nbytes += rv;
+     }
+ 
+     if((rv != -1) && (hdtr->numtrailers > 1)) {
+ 	ap_size_t trlbytes = 0;
+ 
+ 	/* send the trailers now */
+ 	arv = ap_sendv(sock, hdtr->trailers, hdtr->numtrailers, &trlbytes);
+ 	if (arv != APR_SUCCESS) {
+ 	    *len = 0;
+ 	    return errno;
+ 	}
+ 
+ 	nbytes += trlbytes;
+     }
+ 
+     /* 
+        question:
+        should this be the sum of all of them ?
+        sendfile returns a total byte count incl headers/trailers
+        but when headers/trailers is > 1 hdrbytes and trlbytes
+        will be non-zero
+     */
+     (*len) = nbytes;
+ 
+     return (rv < 0) ? errno : APR_SUCCESS;
+ }
  #else
! #endif /* __linux__, __FreeBSD__, __HPUX__, _AIX, Tru64/OSF1 */
  #endif /* APR_HAS_SENDFILE */


+-------------------------------------------------------------+
Dave Hill                             Unix Software Group
Mailstop: ZKO3-3/Y15                  
Digital Equipment Corp.               (603) 884-2985
110 Spit Brook Road         /\_/\     enet: ddhill@zk3.dec.com
Nashua, NH 03062-2698       (0_0)     
+-----------------------oOO--(_)--OOo-------------------------+


Mime
View raw message