comparison 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
comparison
equal deleted inserted replaced
5979:b2920b517490 5980:ccad84a174e0
18 #if (NGX_HAVE_FILE_AIO) 18 #if (NGX_HAVE_FILE_AIO)
19 static void ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx, 19 static void ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx,
20 ngx_file_t *file); 20 ngx_file_t *file);
21 static void ngx_http_copy_aio_event_handler(ngx_event_t *ev); 21 static void ngx_http_copy_aio_event_handler(ngx_event_t *ev);
22 #if (NGX_HAVE_AIO_SENDFILE) 22 #if (NGX_HAVE_AIO_SENDFILE)
23 static ssize_t ngx_http_copy_aio_sendfile_preload(ngx_buf_t *file);
23 static void ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev); 24 static void ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev);
24 #endif 25 #endif
25 #endif 26 #endif
26 27
27 static void *ngx_http_copy_filter_create_conf(ngx_conf_t *cf); 28 static void *ngx_http_copy_filter_create_conf(ngx_conf_t *cf);
123 if (ngx_file_aio) { 124 if (ngx_file_aio) {
124 if (clcf->aio) { 125 if (clcf->aio) {
125 ctx->aio_handler = ngx_http_copy_aio_handler; 126 ctx->aio_handler = ngx_http_copy_aio_handler;
126 } 127 }
127 #if (NGX_HAVE_AIO_SENDFILE) 128 #if (NGX_HAVE_AIO_SENDFILE)
128 c->aio_sendfile = (clcf->aio == NGX_HTTP_AIO_SENDFILE); 129 if (clcf->aio == NGX_HTTP_AIO_SENDFILE) {
130 ctx->aio_preload = ngx_http_copy_aio_sendfile_preload;
131 }
129 #endif 132 #endif
130 } 133 }
131 #endif 134 #endif
132 135
133 if (in && in->buf && ngx_buf_size(in->buf)) { 136 if (in && in->buf && ngx_buf_size(in->buf)) {
137 140
138 #if (NGX_HAVE_FILE_AIO) 141 #if (NGX_HAVE_FILE_AIO)
139 ctx->aio = r->aio; 142 ctx->aio = r->aio;
140 #endif 143 #endif
141 144
142 for ( ;; ) { 145 rc = ngx_output_chain(ctx, in);
143 rc = ngx_output_chain(ctx, in); 146
144 147 if (ctx->in == NULL) {
145 if (ctx->in == NULL) { 148 r->buffered &= ~NGX_HTTP_COPY_BUFFERED;
146 r->buffered &= ~NGX_HTTP_COPY_BUFFERED; 149
147 150 } else {
148 } else { 151 r->buffered |= NGX_HTTP_COPY_BUFFERED;
149 r->buffered |= NGX_HTTP_COPY_BUFFERED; 152 }
150 } 153
151 154 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
152 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0, 155 "http copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args);
153 "http copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args); 156
154 157 return rc;
155 #if (NGX_HAVE_FILE_AIO && NGX_HAVE_AIO_SENDFILE)
156
157 if (c->busy_sendfile) {
158 ssize_t n;
159 off_t offset;
160 ngx_file_t *file;
161 ngx_http_ephemeral_t *e;
162
163 if (r->aio) {
164 c->busy_sendfile = NULL;
165 return rc;
166 }
167
168 file = c->busy_sendfile->file;
169 offset = c->busy_sendfile->file_pos;
170
171 if (file->aio) {
172 c->busy_count = (offset == file->aio->last_offset) ?
173 c->busy_count + 1 : 0;
174 file->aio->last_offset = offset;
175
176 if (c->busy_count > 2) {
177 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
178 "sendfile(%V) returned busy again",
179 &file->name);
180 c->aio_sendfile = 0;
181 }
182 }
183
184 c->busy_sendfile = NULL;
185 e = (ngx_http_ephemeral_t *) &r->uri_start;
186
187 n = ngx_file_aio_read(file, &e->aio_preload, 1, offset, r->pool);
188
189 if (n > 0) {
190 in = NULL;
191 continue;
192 }
193
194 rc = n;
195
196 if (rc == NGX_AGAIN) {
197 file->aio->data = r;
198 file->aio->handler = ngx_http_copy_aio_sendfile_event_handler;
199
200 r->main->blocked++;
201 r->aio = 1;
202 }
203 }
204 #endif
205
206 return rc;
207 }
208 } 158 }
209 159
210 160
211 #if (NGX_HAVE_FILE_AIO) 161 #if (NGX_HAVE_FILE_AIO)
212 162
242 } 192 }
243 193
244 194
245 #if (NGX_HAVE_AIO_SENDFILE) 195 #if (NGX_HAVE_AIO_SENDFILE)
246 196
197 static ssize_t
198 ngx_http_copy_aio_sendfile_preload(ngx_buf_t *file)
199 {
200 ssize_t n;
201 static u_char buf[1];
202 ngx_event_aio_t *aio;
203 ngx_http_request_t *r;
204
205 n = ngx_file_aio_read(file->file, buf, 1, file->file_pos, NULL);
206
207 if (n == NGX_AGAIN) {
208 aio = file->file->aio;
209 aio->handler = ngx_http_copy_aio_sendfile_event_handler;
210
211 r = aio->data;
212 r->main->blocked++;
213 r->aio = 1;
214 }
215
216 return n;
217 }
218
219
247 static void 220 static void
248 ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev) 221 ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev)
249 { 222 {
250 ngx_event_aio_t *aio; 223 ngx_event_aio_t *aio;
251 ngx_http_request_t *r; 224 ngx_http_request_t *r;