]> granicus.if.org Git - apache/commitdiff
First cut at a file bucket. Modify the core_filter to handle use
authorBill Stoddard <stoddard@apache.org>
Thu, 21 Sep 2000 16:22:13 +0000 (16:22 +0000)
committerBill Stoddard <stoddard@apache.org>
Thu, 21 Sep 2000 16:22:13 +0000 (16:22 +0000)
of apr_sendfile(). Modify ap_send_fd() to use the new file bucket.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@86278 13f79535-47bb-0310-9956-ffa450edef68

ApacheCore.dsp
httpd.dsp
modules/http/http_core.c
modules/http/http_protocol.c

index c26b7c42e7dcdca86363c57f78bdc76b8dabc4e3..7528d2544dad07628611a630bde4f132c311a0b3 100644 (file)
@@ -98,6 +98,10 @@ SOURCE=.\ap\ap_buckets_eos.c
 # End Source File
 # Begin Source File
 
+SOURCE=.\ap\ap_buckets_file.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\ap\ap_buckets_heap.c
 # End Source File
 # Begin Source File
index c26b7c42e7dcdca86363c57f78bdc76b8dabc4e3..7528d2544dad07628611a630bde4f132c311a0b3 100644 (file)
--- a/httpd.dsp
+++ b/httpd.dsp
@@ -98,6 +98,10 @@ SOURCE=.\ap\ap_buckets_eos.c
 # End Source File
 # Begin Source File
 
+SOURCE=.\ap\ap_buckets_file.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\ap\ap_buckets_heap.c
 # End Source File
 # Begin Source File
index d676b02924c49ff8e8f38d7a8a39eeda7f1a8e26..f855e0a6c5aba6e698ad792fcc44b6c3f3224244 100644 (file)
@@ -2525,6 +2525,61 @@ static const char *set_limit_nproc(cmd_parms *cmd, void *conf_,
 }
 #endif
 
+#if APR_HAS_SENDFILE
+static apr_status_t send_the_file(apr_file_t *fd, apr_off_t offset, apr_size_t length,  
+                                  request_rec *r, apr_size_t *nbytes) 
+{
+    apr_int32_t flags = 0;
+    apr_status_t rv;
+    struct iovec iov;
+    apr_hdtr_t hdtr;
+
+#if 0
+    ap_bsetopt(r->connection->client, BO_TIMEOUT,
+               r->connection->keptalive
+               ? &r->server->keep_alive_timeout
+               : &r->server->timeout);
+#endif
+    /*
+     * We want to send any data held in the client buffer on the
+     * call to apr_sendfile. So hijack it then set outcnt to 0
+     * to prevent the data from being sent to the client again
+     * when the buffer is flushed to the client at the end of the
+     * request.
+     */
+    iov.iov_base = r->connection->client->outbase;
+    iov.iov_len =  r->connection->client->outcnt;
+    r->connection->client->outcnt = 0;
+
+    /* initialize the apr_hdtr_t struct */
+    hdtr.headers = &iov;
+    hdtr.numheaders = 1;
+    hdtr.trailers = NULL;
+    hdtr.numtrailers = 0;
+
+    if (!r->connection->keepalive) {
+        /* Prepare the socket to be reused */
+        /* XXX fix me - byteranges? */
+        flags |= APR_SENDFILE_DISCONNECT_SOCKET;
+    }
+
+    rv = apr_sendfile(r->connection->client->bsock, 
+                      fd,      /* The file to send */
+                      &hdtr,   /* Header and trailer iovecs */
+                      &offset, /* Offset in file to begin sending from */
+                      &length,
+                      flags);
+#if 0
+    if (r->connection->keptalive) {
+        ap_bsetopt(r->connection->client, BO_TIMEOUT, 
+                   &r->server->timeout);
+    }
+#endif
+    *nbytes = length;
+
+    return rv;
+}
+#endif
 /* Note --- ErrorDocument will now work from .htaccess files.  
  * The AllowOverride of Fileinfo allows webmasters to turn it off
  */
@@ -3058,9 +3113,7 @@ static apr_status_t chunk_filter(ap_filter_t *f, ap_bucket_brigade *b)
  */
 static int core_filter(ap_filter_t *f, ap_bucket_brigade *b)
 {
-#if 0
     request_rec *r = f->r;
-#endif
     apr_status_t rv;
     apr_ssize_t bytes_sent = 0, len = 0, written;
     ap_bucket *e;
@@ -3087,25 +3140,51 @@ static int core_filter(ap_filter_t *f, ap_bucket_brigade *b)
     } 
     else {
 #endif
-    AP_BRIGADE_FOREACH(e, b) {
-       rv = e->read(e, &str, &len, 0);
-       if (rv != APR_SUCCESS) {
-            return rv;
-        }
-       if (len == AP_END_OF_BRIGADE) {
-           break;
-       }
-        rv = ap_bwrite(f->r->connection->client, str, len, &written);
-       if (rv != APR_SUCCESS) {
-            return rv;
-        }
-        bytes_sent += written;
-    }
+
+     AP_BRIGADE_FOREACH(e, b) {
+         if (e->type == AP_BUCKET_EOS) {
+             /* there shouldn't be anything after the eos */
+             break;
+         }
+         else if (e->type == AP_BUCKET_FILE) {
+#if APR_HAS_SENDFILE
+             /* If a file bucket gets all the way down to the core filter,
+              * the bucket by definition represents the unfiltered contents
+              * of a file. Thus it is acceptable to use apr_sendfile().
+              */
+             rv = send_the_file(e->data, e->offset, e->length, r, &bytes_sent);
+          
+             if (rv == APR_SUCCESS) {
+                 ap_brigade_destroy(b);
+                 return APR_SUCCESS;
+             }
+
+             /* If apr_sendfile is not implemented (e.g. Win95/98), then
+              * continue to the read/write loop.
+              */
+             if (rv != APR_ENOTIMPL) {
+                 /* check_first_conn_error(r, "send_fd", rv); */
+                 return rv;
+             }
+#endif
+         }
+         rv = e->read(e, &str, &len, 0);
+         if (rv != APR_SUCCESS) {
+             return rv;
+         }
+         rv = ap_bwrite(r->connection->client, str, len, &written);
+         if (rv != APR_SUCCESS) {
+             return rv;
+         }
+         bytes_sent += written;
+     }
+
     ap_brigade_destroy(b);
     /* This line will go away as soon as the BUFFs are removed */
     if (len == AP_END_OF_BRIGADE) {
-        ap_bflush(f->r->connection->client);
+        ap_bflush(r->connection->client);
     }
+
     return APR_SUCCESS;
 #if 0
     }
index 5d81855733c70dbe3b0115831fa56644278c33a4..e44fd5faf74e75246066fc3145e85c8ebc7fbcce 100644 (file)
@@ -2514,63 +2514,30 @@ API_EXPORT(int) ap_discard_request_body(request_rec *r)
     return OK;
 }
 
-#if APR_HAS_SENDFILE
-static apr_status_t static_send_file(apr_file_t *fd, request_rec *r, apr_off_t offset, 
-                                    apr_size_t length, apr_size_t *nbytes) 
+/*
+ * Send the body of a response to the client.
+ */
+API_EXPORT(apr_status_t) ap_send_fd(apr_file_t *fd, request_rec *r, apr_off_t offset, 
+                                    apr_size_t len, apr_size_t *nbytes) 
 {
-    apr_int32_t flags = 0;
-    apr_status_t rv;
-    struct iovec iov;
-    apr_hdtr_t hdtr;
-
-    ap_bsetopt(r->connection->client, BO_TIMEOUT,
-               r->connection->keptalive
-               ? &r->server->keep_alive_timeout
-               : &r->server->timeout);
-
-    /*
-     * We want to send any data held in the client buffer on the
-     * call to apr_sendfile. So hijack it then set outcnt to 0
-     * to prevent the data from being sent to the client again
-     * when the buffer is flushed to the client at the end of the
-     * request.
-     */
-    iov.iov_base = r->connection->client->outbase;
-    iov.iov_len =  r->connection->client->outcnt;
-    r->connection->client->outcnt = 0;
-
-    /* initialize the apr_hdtr_t struct */
-    hdtr.headers = &iov;
-    hdtr.numheaders = 1;
-    hdtr.trailers = NULL;
-    hdtr.numtrailers = 0;
-
-    if (!r->connection->keepalive) {
-        /* Prepare the socket to be reused */
-        /* XXX fix me - byteranges? */
-        flags |= APR_SENDFILE_DISCONNECT_SOCKET;
-    }
-
-    rv = apr_sendfile(r->connection->client->bsock, 
-                      fd,      /* The file to send */
-                      &hdtr,   /* Header and trailer iovecs */
-                      &offset, /* Offset in file to begin sending from */
-                      &length,
-                      flags);
+    ap_bucket_brigade *bb = NULL;
+    ap_bucket *b;
 
-    if (r->connection->keptalive) {
-        ap_bsetopt(r->connection->client, BO_TIMEOUT, 
-                   &r->server->timeout);
-    }
+    bb = ap_brigade_create(r->pool);
+    b = ap_bucket_create_file(fd, offset, len);
+    AP_BRIGADE_INSERT_TAIL(bb, b);
 
-    *nbytes = length;
+    /* Hummm, is this the right place to insert eos? */
+#if 0
+    b = ap_bucket_create_eos();
+    AP_BRIGADE_INSERT_TAIL(bb, b);
+#endif
+    ap_pass_brigade(r->output_filters, bb);
 
-    return rv;
+    return len;
 }
-#endif
-/*
- * Send the body of a response to the client.
- */
+#if 0
+/* Leave the old implementation around temporarily for reference purposes */
 API_EXPORT(apr_status_t) ap_send_fd(apr_file_t *fd, request_rec *r, apr_off_t offset, 
                                    apr_size_t length, apr_size_t *nbytes) 
 {
@@ -2642,7 +2609,8 @@ API_EXPORT(apr_status_t) ap_send_fd(apr_file_t *fd, request_rec *r, apr_off_t of
     SET_BYTES_SENT(r);
     *nbytes = total_bytes_sent;
     return rv;
-}
+} 
+#endif
 
 /*
  * Send the body of a response to the client.