You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Dave Hill <dd...@laurel.zk3.dec.com> on 2000/07/13 02:59:33 UTC
ap_sendfile() impementation for Tru64 UNIX
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-------------------------+
Re: ap_sendfile() impementation for Tru64 UNIX
Posted by Jeff Trawick <tr...@ibm.net>.
> Date: Wed, 12 Jul 2000 20:59:33 -0400 (EDT)
> From: Dave Hill <dd...@laurel.zk3.dec.com>
>
> 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 :-)
I've been playing in ap_sendfile() a bit lately (at least before a
recent vacation from which I just returned), so I'll look at applying
your patch.
A couple of requests first:
1. how does it work with the existing test driver?
Try out src/lib/apr/test/testsf (the test-ap_sendfile program) in both
blocking and non-blocking modes.
terminal 1: run "testsf server"
terminal 2: run "testsf client blocking"
repeat again, but in terminal 2 run "testsf client nonblocking"
2. source formatting
Can you try to format the source according to Apache conventions, or
at least a bit closer? From http://dev.apache.org there is a link to
a very brief documentation showing the desired indentation.
Other comments:
1. timeout mode
Note that timeout mode is broken with all existing ap_sendfile()
implementations (and yours too). Don't worry about it. When timeout
mode is working for the other implementations, testsf will hopefully
have been modified (if required; maybe not) to drive it properly.
2. your question
> + /*
> + 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;
*len on output should include a count of all bytes sent (header bytes
sent + file bytes sent + trailer bytes sent).
testsf will help you out on this matter.
Thanks,
Jeff
--
Jeff Trawick | trawick@ibm.net | PGP public key at web site:
http://www.geocities.com/SiliconValley/Park/9289/
Born in Roswell... married an alien...