Mercurial > hg > nginx
comparison src/http/ngx_http_output_filter.c @ 60:50186b49f2ad
nginx-0.0.1-2003-02-11-10:14:40 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 11 Feb 2003 07:14:40 +0000 |
parents | e8cdc2989cee |
children | 4f3e2abcc2c4 |
comparison
equal
deleted
inserted
replaced
59:e8cdc2989cee | 60:50186b49f2ad |
---|---|
53 &ngx_http_output_filter_module_ctx, /* module context */ | 53 &ngx_http_output_filter_module_ctx, /* module context */ |
54 ngx_http_output_filter_commands, /* module directives */ | 54 ngx_http_output_filter_commands, /* module directives */ |
55 NGX_HTTP_MODULE_TYPE, /* module type */ | 55 NGX_HTTP_MODULE_TYPE, /* module type */ |
56 NULL /* init module */ | 56 NULL /* init module */ |
57 }; | 57 }; |
58 | |
59 | |
60 #if 1 | |
61 | |
62 #define next_filter ngx_http_output_filter_module_ctx.next_output_body_filter | |
63 | |
64 #define need_to_copy(r, hunk) \ | |
65 (((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) \ | |
66 && (hunk->type & NGX_HUNK_FILE)) \ | |
67 || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP) \ | |
68 && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP)))) | |
69 | |
70 int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) | |
71 { | |
72 int rc; | |
73 size_t size; | |
74 ngx_chain_t *ce, *pe; | |
75 ngx_http_output_filter_ctx_t *ctx; | |
76 ngx_http_output_filter_conf_t *conf; | |
77 | |
78 ctx = (ngx_http_output_filter_ctx_t *) | |
79 ngx_http_get_module_ctx(r->main ? r->main : r, | |
80 ngx_http_output_filter_module); | |
81 | |
82 if (ctx == NULL) { | |
83 ngx_http_create_ctx(r, ctx, ngx_http_output_filter_module, | |
84 sizeof(ngx_http_output_filter_ctx_t)); | |
85 } | |
86 | |
87 /* the incoming chain ctx->in is empty */ | |
88 if (ctx->in == NULL) { | |
89 | |
90 if (hunk == NULL) { | |
91 return next_filter(r, NULL); | |
92 } | |
93 | |
94 /* we do not need to copy the incoming hunk to our hunk */ | |
95 if (!need_to_copy(r, hunk)) { | |
96 ctx->out.hunk = hunk; | |
97 ctx->out.next = NULL; | |
98 | |
99 return next_filter(r, &ctx->out); | |
100 } | |
101 | |
102 /* we need to copy the incoming hunk to our hunk */ | |
103 | |
104 /* allocate ctx->hunk if it's needed */ | |
105 if (ctx->hunk == NULL) { | |
106 | |
107 conf = (ngx_http_output_filter_conf_t *) | |
108 ngx_http_get_module_loc_conf(r->main ? r->main : r, | |
109 ngx_http_output_filter_module); | |
110 | |
111 if (hunk->type & NGX_HUNK_LAST) { | |
112 size = hunk->last.mem - hunk->pos.mem; | |
113 if (size > conf->hunk_size) { | |
114 size = conf->hunk_size; | |
115 } | |
116 | |
117 } else { | |
118 size = conf->hunk_size; | |
119 } | |
120 | |
121 ngx_test_null(ctx->hunk, | |
122 ngx_create_temp_hunk(r->pool, size, 50, 50), | |
123 NGX_ERROR); | |
124 | |
125 ctx->hunk->type |= NGX_HUNK_RECYCLED; | |
126 } | |
127 | |
128 /* copy the incoming hunk or its part to our hunk | |
129 and pass it to the next filter */ | |
130 | |
131 do { | |
132 rc = ngx_http_output_filter_copy_hunk(ctx->hunk, hunk); | |
133 | |
134 if (rc == NGX_ERROR) { | |
135 return rc; | |
136 } | |
137 | |
138 #if (NGX_FILE_AIO_READ) | |
139 | |
140 if (rc == NGX_AGAIN) { | |
141 /* add the incoming hunk to the incoming chain */ | |
142 ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, NGX_ERROR); | |
143 return rc; | |
144 } | |
145 | |
146 #endif | |
147 ctx->out.hunk = ctx->hunk; | |
148 ctx->out.next = NULL; | |
149 | |
150 rc = next_filter(r, &ctx->out); | |
151 | |
152 if (rc == NGX_ERROR) { | |
153 return rc; | |
154 } | |
155 | |
156 if (rc == NGX_AGAIN) { | |
157 /* add the incoming hunk to the incoming chain */ | |
158 ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, NGX_ERROR); | |
159 return rc; | |
160 } | |
161 | |
162 /* NGX_OK */ | |
163 | |
164 /* set our hunk free */ | |
165 ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; | |
166 | |
167 /* repeat until we will have copied the whole incoming hunk */ | |
168 } while (hunk->pos.mem < hunk->last.mem); | |
169 | |
170 return NGX_OK; | |
171 } | |
172 | |
173 /* the incoming chain ctx->in is not empty */ | |
174 | |
175 /* add the incoming hunk to the incoming chain */ | |
176 if (hunk) { | |
177 for (ce = ctx->in; ce->next; ce = ce->next) { | |
178 /* void */ ; | |
179 } | |
180 | |
181 ngx_add_hunk_to_chain(ce->next, hunk, r->pool, NGX_ERROR); | |
182 } | |
183 | |
184 /* our hunk is still busy */ | |
185 if (ctx->hunk->pos.mem < ctx->hunk->last.mem) { | |
186 rc = next_filter(r, NULL); | |
187 | |
188 if (rc == NGX_ERROR || rc == NGX_AGAIN) { | |
189 return rc; | |
190 } | |
191 | |
192 /* NGX_OK */ | |
193 ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; | |
194 } | |
195 | |
196 #if (NGX_SUPPRESS_WARN) | |
197 pe = NULL; | |
198 #endif | |
199 | |
200 /* process the incoming chain ctx->in */ | |
201 do { | |
202 /* find the hunks that do not need to be copied ... */ | |
203 for (ce = ctx->in; ce; ce = ce->next) { | |
204 if (need_to_copy(r, ce->hunk)) { | |
205 break; | |
206 } | |
207 pe = ce; | |
208 } | |
209 | |
210 /* ... and pass them to the next filter */ | |
211 if (ctx->in != ce) { | |
212 | |
213 ctx->out.hunk = ctx->in->hunk; | |
214 ctx->out.next = ctx->in->next; | |
215 ctx->in = ce; | |
216 pe->next = NULL; | |
217 | |
218 rc = next_filter(r, &ctx->out); | |
219 | |
220 if (rc == NGX_ERROR || rc == NGX_AGAIN) { | |
221 return rc; | |
222 } | |
223 | |
224 /* NGX_OK */ | |
225 if (ctx->in == NULL) { | |
226 return rc; | |
227 } | |
228 } | |
229 | |
230 | |
231 /* copy the first hunk or its part from the incoming chain ctx->in | |
232 to our hunk and pass it to the next filter */ | |
233 do { | |
234 rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk); | |
235 | |
236 if (rc == NGX_ERROR) { | |
237 return rc; | |
238 } | |
239 | |
240 #if (NGX_FILE_AIO_READ) | |
241 | |
242 if (rc == NGX_AGAIN) { | |
243 return rc; | |
244 } | |
245 | |
246 #endif | |
247 ctx->out.hunk = ctx->hunk; | |
248 ctx->out.next = NULL; | |
249 | |
250 rc = next_filter(r, &ctx->out); | |
251 | |
252 if (rc == NGX_ERROR || rc == NGX_AGAIN) { | |
253 return rc; | |
254 } | |
255 | |
256 /* NGX_OK */ | |
257 | |
258 /* set our hunk free */ | |
259 ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; | |
260 | |
261 /* repeat until we will have copied the whole first hunk from | |
262 the incoming chain ctx->in */ | |
263 } while (ctx->in->hunk->pos.mem < ctx->in->hunk->last.mem); | |
264 | |
265 /* delete the completed hunk from the incoming chain */ | |
266 ctx->in = ctx->in->next; | |
267 | |
268 /* repeat until we will have processed the whole incoming chain ctx->in */ | |
269 } while (ctx->in); | |
270 | |
271 return NGX_OK; | |
272 } | |
273 | |
274 | |
275 #else | |
58 | 276 |
59 | 277 |
60 int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) | 278 int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) |
61 { | 279 { |
62 int rc, once; | 280 int rc, once; |
104 | 322 |
105 /* our hunk is free */ | 323 /* our hunk is free */ |
106 } else { | 324 } else { |
107 ctx->out.hunk = ctx->hunk; | 325 ctx->out.hunk = ctx->hunk; |
108 | 326 |
327 /* XXX: should we check hunk type before copy it ? */ | |
109 rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk); | 328 rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk); |
110 #if (NGX_FILE_AIO_READ) | 329 #if (NGX_FILE_AIO_READ) |
111 if (rc == NGX_AGAIN) { | 330 if (rc == NGX_AGAIN) { |
112 return rc; | 331 return rc; |
113 } | 332 } |
114 #endif | 333 #endif |
115 if (rc == NGX_ERROR) { | 334 if (rc == NGX_ERROR) { |
116 return rc; | 335 return rc; |
117 } | 336 } |
337 | |
338 /* NGX_OK */ | |
118 | 339 |
119 /* whole hunk is copied so we send to next filter chain part | 340 /* whole hunk is copied so we send to next filter chain part |
120 up to next hunk that need to be copied */ | 341 up to next hunk that need to be copied */ |
121 if (ctx->in->hunk->pos.mem == ctx->in->hunk->last.mem) { | 342 if (ctx->in->hunk->pos.mem == ctx->in->hunk->last.mem) { |
122 ctx->out.next = ctx->in->next; | 343 ctx->out.next = ctx->in->next; |
240 next_output_body_filter(r, &ctx->out); | 461 next_output_body_filter(r, &ctx->out); |
241 } | 462 } |
242 } | 463 } |
243 } | 464 } |
244 | 465 |
245 if (rc == NGX_OK && ctx->hunk) | 466 /* set free our hunk if operation has completed */ |
467 if (rc == NGX_OK && ctx->hunk) { | |
246 ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; | 468 ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; |
469 } | |
247 } | 470 } |
248 | 471 |
249 #if (NGX_SUPPRESS_WARN) | 472 #if (NGX_SUPPRESS_WARN) |
250 if (rc == NGX_ALERT) { | 473 if (rc == NGX_ALERT) { |
251 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | 474 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, |
257 if (rc == NGX_OK && ctx->last) { | 480 if (rc == NGX_OK && ctx->last) { |
258 return NGX_OK; | 481 return NGX_OK; |
259 } | 482 } |
260 | 483 |
261 if (rc == NGX_OK) { | 484 if (rc == NGX_OK) { |
262 if (ctx->hunk) { | 485 if (ctx->hunk) { /* XXX: double upper code ? */ |
263 ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; | 486 ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; |
264 } | 487 } |
265 #if (NGX_LEVEL_EVENT) | 488 #if (NGX_LEVEL_EVENT) |
266 ngx_del_event(r->connection->write, NGX_WRITE_EVENT); | 489 ngx_del_event(r->connection->write, NGX_WRITE_EVENT); |
267 #endif | 490 #endif |
268 } | 491 } |
269 | 492 |
270 return rc; | 493 return rc; |
271 } | 494 } |
495 | |
496 #endif | |
272 | 497 |
273 | 498 |
274 static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src) | 499 static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src) |
275 { | 500 { |
276 ssize_t n, size; | 501 ssize_t n, size; |