Mercurial > hg > nginx
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; |