diff options
author | rbb <rbb@13f79535-47bb-0310-9956-ffa450edef68> | 2000-07-15 16:00:50 +0000 |
---|---|---|
committer | rbb <rbb@13f79535-47bb-0310-9956-ffa450edef68> | 2000-07-15 16:00:50 +0000 |
commit | c563fb4d10b93228ae491221adda128486c586f0 (patch) | |
tree | 09b8b0874c4f0bfcf7d98829e228543399a8ac3e /network_io | |
parent | 9ca200cea8141aa0f1fa2288cf09f5c40adc7f8b (diff) | |
download | libapr-c563fb4d10b93228ae491221adda128486c586f0.tar.gz |
Add ap_sendfile for Tru64 Unix. This needs to be tested better, but it
is a start. Also, add an error message for machines where sendfile is
detected, but nobody has written ap_sendfile.
Submitted by: Dave Hill <ddhill@laurel.zk3.dec.com>
Reviewed by: Ryan Bloom
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@60380 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'network_io')
-rw-r--r-- | network_io/unix/sendrecv.c | 144 |
1 files changed, 143 insertions, 1 deletions
diff --git a/network_io/unix/sendrecv.c b/network_io/unix/sendrecv.c index 159359591..369dc0b22 100644 --- a/network_io/unix/sendrecv.c +++ b/network_io/unix/sendrecv.c @@ -633,6 +633,148 @@ ap_status_t ap_sendfile(ap_socket_t * sock, ap_file_t * file, } 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 */ +#error APR has detected sendfile on your system, but nobody has written a +#error version of it for APR yet. To get past this, either write ap_sendfile +#error or change APR_HAS_SENDFILE in apr.h to 0. +#endif /* __linux__, __FreeBSD__, __HPUX__, _AIX, Tru64/OSF1 */ #endif /* APR_HAS_SENDFILE */ |