summaryrefslogtreecommitdiff
path: root/network_io
diff options
context:
space:
mode:
authorrbb <rbb@13f79535-47bb-0310-9956-ffa450edef68>2000-07-15 16:00:50 +0000
committerrbb <rbb@13f79535-47bb-0310-9956-ffa450edef68>2000-07-15 16:00:50 +0000
commitc563fb4d10b93228ae491221adda128486c586f0 (patch)
tree09b8b0874c4f0bfcf7d98829e228543399a8ac3e /network_io
parent9ca200cea8141aa0f1fa2288cf09f5c40adc7f8b (diff)
downloadlibapr-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.c144
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 */