Annotation of embedaddon/nginx/src/http/ngx_http_copy_filter_module.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (C) Igor Sysoev
4: * Copyright (C) Nginx, Inc.
5: */
6:
7:
8: #include <ngx_config.h>
9: #include <ngx_core.h>
10: #include <ngx_http.h>
11:
12:
13: typedef struct {
14: ngx_bufs_t bufs;
15: } ngx_http_copy_filter_conf_t;
16:
17:
18: #if (NGX_HAVE_FILE_AIO)
19: static void ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx,
20: ngx_file_t *file);
21: static void ngx_http_copy_aio_event_handler(ngx_event_t *ev);
22: #if (NGX_HAVE_AIO_SENDFILE)
23: static void ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev);
24: #endif
25: #endif
26:
27: static void *ngx_http_copy_filter_create_conf(ngx_conf_t *cf);
28: static char *ngx_http_copy_filter_merge_conf(ngx_conf_t *cf,
29: void *parent, void *child);
30: static ngx_int_t ngx_http_copy_filter_init(ngx_conf_t *cf);
31:
32:
33: static ngx_command_t ngx_http_copy_filter_commands[] = {
34:
35: { ngx_string("output_buffers"),
36: NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
37: ngx_conf_set_bufs_slot,
38: NGX_HTTP_LOC_CONF_OFFSET,
39: offsetof(ngx_http_copy_filter_conf_t, bufs),
40: NULL },
41:
42: ngx_null_command
43: };
44:
45:
46: static ngx_http_module_t ngx_http_copy_filter_module_ctx = {
47: NULL, /* preconfiguration */
48: ngx_http_copy_filter_init, /* postconfiguration */
49:
50: NULL, /* create main configuration */
51: NULL, /* init main configuration */
52:
53: NULL, /* create server configuration */
54: NULL, /* merge server configuration */
55:
56: ngx_http_copy_filter_create_conf, /* create location configuration */
57: ngx_http_copy_filter_merge_conf /* merge location configuration */
58: };
59:
60:
61: ngx_module_t ngx_http_copy_filter_module = {
62: NGX_MODULE_V1,
63: &ngx_http_copy_filter_module_ctx, /* module context */
64: ngx_http_copy_filter_commands, /* module directives */
65: NGX_HTTP_MODULE, /* module type */
66: NULL, /* init master */
67: NULL, /* init module */
68: NULL, /* init process */
69: NULL, /* init thread */
70: NULL, /* exit thread */
71: NULL, /* exit process */
72: NULL, /* exit master */
73: NGX_MODULE_V1_PADDING
74: };
75:
76:
77: static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
78:
79:
80: static ngx_int_t
81: ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in)
82: {
83: ngx_int_t rc;
84: ngx_connection_t *c;
85: ngx_output_chain_ctx_t *ctx;
86: ngx_http_core_loc_conf_t *clcf;
87: ngx_http_copy_filter_conf_t *conf;
88:
89: c = r->connection;
90:
91: ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
92: "http copy filter: \"%V?%V\"", &r->uri, &r->args);
93:
94: ctx = ngx_http_get_module_ctx(r, ngx_http_copy_filter_module);
95:
96: if (ctx == NULL) {
97: ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t));
98: if (ctx == NULL) {
99: return NGX_ERROR;
100: }
101:
102: ngx_http_set_ctx(r, ctx, ngx_http_copy_filter_module);
103:
104: conf = ngx_http_get_module_loc_conf(r, ngx_http_copy_filter_module);
105: clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
106:
107: ctx->sendfile = c->sendfile;
108: ctx->need_in_memory = r->main_filter_need_in_memory
109: || r->filter_need_in_memory;
110: ctx->need_in_temp = r->filter_need_temporary;
111:
112: ctx->alignment = clcf->directio_alignment;
113:
114: ctx->pool = r->pool;
115: ctx->bufs = conf->bufs;
116: ctx->tag = (ngx_buf_tag_t) &ngx_http_copy_filter_module;
117:
118: ctx->output_filter = (ngx_output_chain_filter_pt)
119: ngx_http_next_body_filter;
120: ctx->filter_ctx = r;
121:
122: #if (NGX_HAVE_FILE_AIO)
123: if (ngx_file_aio) {
124: if (clcf->aio) {
125: ctx->aio_handler = ngx_http_copy_aio_handler;
126: }
127: #if (NGX_HAVE_AIO_SENDFILE)
128: c->aio_sendfile = (clcf->aio == NGX_HTTP_AIO_SENDFILE);
129: #endif
130: }
131: #endif
132:
133: if (in && in->buf && ngx_buf_size(in->buf)) {
134: r->request_output = 1;
135: }
136: }
137:
138: #if (NGX_HAVE_FILE_AIO)
139: ctx->aio = r->aio;
140: #endif
141:
142: for ( ;; ) {
143: rc = ngx_output_chain(ctx, in);
144:
145: if (ctx->in == NULL) {
146: r->buffered &= ~NGX_HTTP_COPY_BUFFERED;
147:
148: } else {
149: r->buffered |= NGX_HTTP_COPY_BUFFERED;
150: }
151:
152: ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
153: "http copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args);
154:
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->aio_sendfile = (offset != file->aio->last_offset);
173: file->aio->last_offset = offset;
174:
175: if (c->aio_sendfile == 0) {
176: ngx_log_error(NGX_LOG_ALERT, c->log, 0,
177: "sendfile(%V) returned busy again",
178: &file->name);
179: }
180: }
181:
182: c->busy_sendfile = NULL;
183: e = (ngx_http_ephemeral_t *) &r->uri_start;
184:
185: n = ngx_file_aio_read(file, &e->aio_preload, 1, offset, r->pool);
186:
187: if (n > 0) {
188: in = NULL;
189: continue;
190: }
191:
192: rc = n;
193:
194: if (rc == NGX_AGAIN) {
195: file->aio->data = r;
196: file->aio->handler = ngx_http_copy_aio_sendfile_event_handler;
197:
198: r->main->blocked++;
199: r->aio = 1;
200: }
201: }
202: #endif
203:
204: return rc;
205: }
206: }
207:
208:
209: #if (NGX_HAVE_FILE_AIO)
210:
211: static void
212: ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx, ngx_file_t *file)
213: {
214: ngx_http_request_t *r;
215:
216: r = ctx->filter_ctx;
217:
218: file->aio->data = r;
219: file->aio->handler = ngx_http_copy_aio_event_handler;
220:
221: r->main->blocked++;
222: r->aio = 1;
223: ctx->aio = 1;
224: }
225:
226:
227: static void
228: ngx_http_copy_aio_event_handler(ngx_event_t *ev)
229: {
230: ngx_event_aio_t *aio;
231: ngx_http_request_t *r;
232:
233: aio = ev->data;
234: r = aio->data;
235:
236: r->main->blocked--;
237: r->aio = 0;
238:
239: r->connection->write->handler(r->connection->write);
240: }
241:
242:
243: #if (NGX_HAVE_AIO_SENDFILE)
244:
245: static void
246: ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev)
247: {
248: ngx_event_aio_t *aio;
249: ngx_http_request_t *r;
250:
251: aio = ev->data;
252: r = aio->data;
253:
254: r->main->blocked--;
255: r->aio = 0;
256: ev->complete = 0;
257:
258: r->connection->write->handler(r->connection->write);
259: }
260:
261: #endif
262: #endif
263:
264:
265: static void *
266: ngx_http_copy_filter_create_conf(ngx_conf_t *cf)
267: {
268: ngx_http_copy_filter_conf_t *conf;
269:
270: conf = ngx_palloc(cf->pool, sizeof(ngx_http_copy_filter_conf_t));
271: if (conf == NULL) {
272: return NULL;
273: }
274:
275: conf->bufs.num = 0;
276:
277: return conf;
278: }
279:
280:
281: static char *
282: ngx_http_copy_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
283: {
284: ngx_http_copy_filter_conf_t *prev = parent;
285: ngx_http_copy_filter_conf_t *conf = child;
286:
287: ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 1, 32768);
288:
289: return NULL;
290: }
291:
292:
293: static ngx_int_t
294: ngx_http_copy_filter_init(ngx_conf_t *cf)
295: {
296: ngx_http_next_body_filter = ngx_http_top_body_filter;
297: ngx_http_top_body_filter = ngx_http_copy_filter;
298:
299: return NGX_OK;
300: }
301:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>