diff src/http/ngx_http_copy_filter_module.c @ 5980:ccad84a174e0

Refactored sendfile() AIO preload. This reduces layering violation and simplifies the logic of AIO preread, since it's now triggered by the send chain function itself without falling back to the copy filter. The context of AIO operation is now stored per file buffer, which makes it possible to properly handle cases when multiple buffers come from different locations, each with its own configuration.
author Valentin Bartenev <vbart@nginx.com>
date Wed, 11 Feb 2015 17:52:15 +0300
parents d39a69427056
children 2dac6ae6d703
line wrap: on
line diff
--- a/src/http/ngx_http_copy_filter_module.c
+++ b/src/http/ngx_http_copy_filter_module.c
@@ -20,6 +20,7 @@ static void ngx_http_copy_aio_handler(ng
     ngx_file_t *file);
 static void ngx_http_copy_aio_event_handler(ngx_event_t *ev);
 #if (NGX_HAVE_AIO_SENDFILE)
+static ssize_t ngx_http_copy_aio_sendfile_preload(ngx_buf_t *file);
 static void ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev);
 #endif
 #endif
@@ -125,7 +126,9 @@ ngx_http_copy_filter(ngx_http_request_t 
                 ctx->aio_handler = ngx_http_copy_aio_handler;
             }
 #if (NGX_HAVE_AIO_SENDFILE)
-            c->aio_sendfile = (clcf->aio == NGX_HTTP_AIO_SENDFILE);
+            if (clcf->aio == NGX_HTTP_AIO_SENDFILE) {
+                ctx->aio_preload = ngx_http_copy_aio_sendfile_preload;
+            }
 #endif
         }
 #endif
@@ -139,72 +142,19 @@ ngx_http_copy_filter(ngx_http_request_t 
     ctx->aio = r->aio;
 #endif
 
-    for ( ;; ) {
-        rc = ngx_output_chain(ctx, in);
-
-        if (ctx->in == NULL) {
-            r->buffered &= ~NGX_HTTP_COPY_BUFFERED;
-
-        } else {
-            r->buffered |= NGX_HTTP_COPY_BUFFERED;
-        }
-
-        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                       "http copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args);
+    rc = ngx_output_chain(ctx, in);
 
-#if (NGX_HAVE_FILE_AIO && NGX_HAVE_AIO_SENDFILE)
-
-        if (c->busy_sendfile) {
-            ssize_t                n;
-            off_t                  offset;
-            ngx_file_t            *file;
-            ngx_http_ephemeral_t  *e;
-
-            if (r->aio) {
-                c->busy_sendfile = NULL;
-                return rc;
-            }
-
-            file = c->busy_sendfile->file;
-            offset = c->busy_sendfile->file_pos;
+    if (ctx->in == NULL) {
+        r->buffered &= ~NGX_HTTP_COPY_BUFFERED;
 
-            if (file->aio) {
-                c->busy_count = (offset == file->aio->last_offset) ?
-                                c->busy_count + 1 : 0;
-                file->aio->last_offset = offset;
-
-                if (c->busy_count > 2) {
-                    ngx_log_error(NGX_LOG_ALERT, c->log, 0,
-                                  "sendfile(%V) returned busy again",
-                                  &file->name);
-                    c->aio_sendfile = 0;
-                }
-            }
-
-            c->busy_sendfile = NULL;
-            e = (ngx_http_ephemeral_t *) &r->uri_start;
-
-            n = ngx_file_aio_read(file, &e->aio_preload, 1, offset, r->pool);
+    } else {
+        r->buffered |= NGX_HTTP_COPY_BUFFERED;
+    }
 
-            if (n > 0) {
-                in = NULL;
-                continue;
-            }
-
-            rc = n;
+    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                   "http copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args);
 
-            if (rc == NGX_AGAIN) {
-                file->aio->data = r;
-                file->aio->handler = ngx_http_copy_aio_sendfile_event_handler;
-
-                r->main->blocked++;
-                r->aio = 1;
-            }
-        }
-#endif
-
-        return rc;
-    }
+    return rc;
 }
 
 
@@ -244,6 +194,29 @@ ngx_http_copy_aio_event_handler(ngx_even
 
 #if (NGX_HAVE_AIO_SENDFILE)
 
+static ssize_t
+ngx_http_copy_aio_sendfile_preload(ngx_buf_t *file)
+{
+    ssize_t              n;
+    static u_char        buf[1];
+    ngx_event_aio_t     *aio;
+    ngx_http_request_t  *r;
+
+    n = ngx_file_aio_read(file->file, buf, 1, file->file_pos, NULL);
+
+    if (n == NGX_AGAIN) {
+        aio = file->file->aio;
+        aio->handler = ngx_http_copy_aio_sendfile_event_handler;
+
+        r = aio->data;
+        r->main->blocked++;
+        r->aio = 1;
+    }
+
+    return n;
+}
+
+
 static void
 ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev)
 {