blob: 423a650d30c8bdbe25c30597c2c8973027472ce6 [file] [log] [blame]
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00001
Igor Sysoevd90282d2004-09-28 08:34:51 +00002/*
Igor Sysoevff8da912004-09-29 16:00:49 +00003 * Copyright (C) Igor Sysoev
Igor Sysoevd90282d2004-09-28 08:34:51 +00004 */
5
6
Igor Sysoev10fc9ef2003-10-27 08:53:49 +00007#include <ngx_config.h>
8#include <ngx_core.h>
Igor Sysoev2b0c76c2003-10-27 21:01:00 +00009#include <ngx_event.h>
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000010
11
Igor Sysoevf6906042004-11-25 16:17:31 +000012#if 0
13#define NGX_SENDFILE_LIMIT 4096
14#endif
15
16
17#define NGX_NONE 1
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000018
19
Igor Sysoevd43bee82004-11-20 19:52:20 +000020static ngx_inline ngx_int_t
Igor Sysoev2f657222004-06-16 15:32:11 +000021 ngx_output_chain_need_to_copy(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf);
Igor Sysoevf6906042004-11-25 16:17:31 +000022static ngx_int_t ngx_output_chain_add_copy(ngx_pool_t *pool,
Igor Sysoev8184d1b2005-03-04 14:06:57 +000023 ngx_chain_t **chain, ngx_chain_t *in);
Igor Sysoev369145c2004-05-28 15:49:23 +000024static ngx_int_t ngx_output_chain_copy_buf(ngx_buf_t *dst, ngx_buf_t *src,
Igor Sysoev8184d1b2005-03-04 14:06:57 +000025 ngx_uint_t sendfile);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000026
27
Igor Sysoev8184d1b2005-03-04 14:06:57 +000028ngx_int_t
29ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in)
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000030{
Igor Sysoev42b12b32004-12-02 18:40:46 +000031 off_t bsize;
32 size_t size;
Igor Sysoevdf3254a2006-01-11 15:26:57 +000033 ngx_int_t rc, last;
34 ngx_uint_t recycled;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000035 ngx_chain_t *cl, *out, **last_out;
36
Igor Sysoevc0edbcc2004-10-21 15:34:38 +000037 if (ctx->in == NULL && ctx->busy == NULL) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000038
Igor Sysoevf6906042004-11-25 16:17:31 +000039 /*
40 * the short path for the case when the ctx->in and ctx->busy chains
41 * are empty, the incoming chain is empty too or has the single buf
42 * that does not require the copy
43 */
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000044
45 if (in == NULL) {
Igor Sysoev89690bf2004-03-23 06:01:52 +000046 return ctx->output_filter(ctx->filter_ctx, in);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000047 }
48
Igor Sysoev2b0c76c2003-10-27 21:01:00 +000049 if (in->next == NULL
Igor Sysoevf6906042004-11-25 16:17:31 +000050#if (NGX_SENDFILE_LIMIT)
51 && !(in->buf->in_file && in->buf->file_last > NGX_SENDFILE_LIMIT)
52#endif
Igor Sysoev899b44e2005-05-12 14:58:06 +000053 && !ngx_output_chain_need_to_copy(ctx, in->buf))
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000054 {
Igor Sysoev89690bf2004-03-23 06:01:52 +000055 return ctx->output_filter(ctx->filter_ctx, in);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000056 }
57 }
58
Igor Sysoev67f450d2004-06-01 06:04:46 +000059 /* add the incoming buf to the chain ctx->in */
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000060
61 if (in) {
Igor Sysoevf6906042004-11-25 16:17:31 +000062 if (ngx_output_chain_add_copy(ctx->pool, &ctx->in, in) == NGX_ERROR) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000063 return NGX_ERROR;
64 }
65 }
66
Igor Sysoevb5faed22003-10-29 08:30:44 +000067 out = NULL;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000068 last_out = &out;
Igor Sysoev8184d1b2005-03-04 14:06:57 +000069 last = NGX_NONE;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +000070
71 for ( ;; ) {
72
73 while (ctx->in) {
74
Igor Sysoev9bfb4342004-04-18 19:06:02 +000075 /*
Igor Sysoev369145c2004-05-28 15:49:23 +000076 * cycle while there are the ctx->in bufs
77 * or there are the free output bufs to copy in
Igor Sysoev9bfb4342004-04-18 19:06:02 +000078 */
79
Igor Sysoev00d433f2004-07-28 19:21:26 +000080 bsize = ngx_buf_size(ctx->in->buf);
81
82 if (bsize == 0 && !ngx_buf_special(ctx->in->buf)) {
83
84 ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, 0,
Igor Sysoeve5a222c2005-01-25 12:27:35 +000085 "zero size buf in output "
86 "t:%d r:%d f:%d %p %p-%p %p %O-%O",
87 ctx->in->buf->temporary,
88 ctx->in->buf->recycled,
89 ctx->in->buf->in_file,
90 ctx->in->buf->start,
91 ctx->in->buf->pos,
92 ctx->in->buf->last,
93 ctx->in->buf->file,
94 ctx->in->buf->file_pos,
95 ctx->in->buf->file_last);
Igor Sysoev00d433f2004-07-28 19:21:26 +000096
Igor Sysoev42b12b32004-12-02 18:40:46 +000097 ngx_debug_point();
98
Igor Sysoev00d433f2004-07-28 19:21:26 +000099 ctx->in = ctx->in->next;
Igor Sysoeva2c81192004-09-19 18:27:00 +0000100
Igor Sysoev00d433f2004-07-28 19:21:26 +0000101 continue;
102 }
103
Igor Sysoev369145c2004-05-28 15:49:23 +0000104 if (!ngx_output_chain_need_to_copy(ctx, ctx->in->buf)) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000105
Igor Sysoev9bfb4342004-04-18 19:06:02 +0000106 /* move the chain link to the output chain */
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000107
108 cl = ctx->in;
109 ctx->in = cl->next;
110
111 *last_out = cl;
112 last_out = &cl->next;
113 cl->next = NULL;
114
115 continue;
116 }
117
Igor Sysoev369145c2004-05-28 15:49:23 +0000118 if (ctx->buf == NULL) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000119
Igor Sysoev369145c2004-05-28 15:49:23 +0000120 /* get the free buf */
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000121
122 if (ctx->free) {
Igor Sysoev02f742b2005-04-08 15:18:55 +0000123 cl = ctx->free;
124 ctx->buf = cl->buf;
125 ctx->free = cl->next;
126 ngx_free_chain(ctx->pool, cl);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000127
Igor Sysoev369145c2004-05-28 15:49:23 +0000128 } else if (out || ctx->allocated == ctx->bufs.num) {
Igor Sysoev31f7f6a2004-05-12 05:37:55 +0000129
130 break;
131
132 } else {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000133
134 size = ctx->bufs.size;
Igor Sysoevdf3254a2006-01-11 15:26:57 +0000135 recycled = 1;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000136
Igor Sysoev899b44e2005-05-12 14:58:06 +0000137 if (ctx->in->buf->last_in_chain) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000138
Igor Sysoev42b12b32004-12-02 18:40:46 +0000139 if (bsize < (off_t) ctx->bufs.size) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000140
141 /*
Igor Sysoev369145c2004-05-28 15:49:23 +0000142 * allocate small temp buf for the small last buf
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000143 * or its small last part
144 */
145
Igor Sysoev42b12b32004-12-02 18:40:46 +0000146 size = (size_t) bsize;
Igor Sysoevdf3254a2006-01-11 15:26:57 +0000147 recycled = 0;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000148
149 } else if (ctx->bufs.num == 1
Igor Sysoev42b12b32004-12-02 18:40:46 +0000150 && (bsize < (off_t) (ctx->bufs.size
151 + (ctx->bufs.size >> 2))))
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000152 {
153 /*
Igor Sysoev369145c2004-05-28 15:49:23 +0000154 * allocate a temp buf that equals
155 * to the last buf if the last buf size is lesser
156 * than 1.25 of bufs.size and a temp buf is single
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000157 */
158
Igor Sysoev42b12b32004-12-02 18:40:46 +0000159 size = (size_t) bsize;
Igor Sysoevdf3254a2006-01-11 15:26:57 +0000160 recycled = 0;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000161 }
162 }
163
Igor Sysoevc1571722005-03-19 12:38:37 +0000164 ctx->buf = ngx_create_temp_buf(ctx->pool, size);
165 if (ctx->buf == NULL) {
Igor Sysoev369145c2004-05-28 15:49:23 +0000166 return NGX_ERROR;
167 }
168
169 ctx->buf->tag = ctx->tag;
Igor Sysoevdf3254a2006-01-11 15:26:57 +0000170 ctx->buf->recycled = recycled;
Igor Sysoev369145c2004-05-28 15:49:23 +0000171 ctx->allocated++;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000172 }
173 }
174
Igor Sysoev369145c2004-05-28 15:49:23 +0000175 rc = ngx_output_chain_copy_buf(ctx->buf, ctx->in->buf,
176 ctx->sendfile);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000177
178 if (rc == NGX_ERROR) {
179 return rc;
180 }
181
182 if (rc == NGX_AGAIN) {
183 if (out) {
184 break;
185 }
Igor Sysoeva2c81192004-09-19 18:27:00 +0000186
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000187 return rc;
188 }
189
Igor Sysoev369145c2004-05-28 15:49:23 +0000190 /* delete the completed buf from the ctx->in chain */
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000191
Igor Sysoev369145c2004-05-28 15:49:23 +0000192 if (ngx_buf_size(ctx->in->buf) == 0) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000193 ctx->in = ctx->in->next;
194 }
195
Igor Sysoevc1571722005-03-19 12:38:37 +0000196 cl = ngx_alloc_chain_link(ctx->pool);
197 if (cl == NULL) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000198 return NGX_ERROR;
199 }
Igor Sysoevc1571722005-03-19 12:38:37 +0000200
Igor Sysoev1b735832004-11-11 14:07:14 +0000201 cl->buf = ctx->buf;
202 cl->next = NULL;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000203 *last_out = cl;
204 last_out = &cl->next;
Igor Sysoev369145c2004-05-28 15:49:23 +0000205 ctx->buf = NULL;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000206 }
207
208 if (out == NULL && last != NGX_NONE) {
Igor Sysoev899b44e2005-05-12 14:58:06 +0000209
210 if (ctx->in) {
211 return NGX_AGAIN;
212 }
213
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000214 return last;
215 }
216
Igor Sysoev89690bf2004-03-23 06:01:52 +0000217 last = ctx->output_filter(ctx->filter_ctx, out);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000218
Igor Sysoev9ac946b2005-10-24 15:09:41 +0000219 if (last == NGX_ERROR || last == NGX_DONE) {
Igor Sysoev9bfb4342004-04-18 19:06:02 +0000220 return last;
221 }
Igor Sysoev9ac946b2005-10-24 15:09:41 +0000222
223 ngx_chain_update_chains(&ctx->free, &ctx->busy, &out, ctx->tag);
224 last_out = &out;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000225 }
226}
227
228
Igor Sysoevd43bee82004-11-20 19:52:20 +0000229static ngx_inline ngx_int_t
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000230ngx_output_chain_need_to_copy(ngx_output_chain_ctx_t *ctx, ngx_buf_t *buf)
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000231{
Igor Sysoevf6906042004-11-25 16:17:31 +0000232 ngx_uint_t sendfile;
233
Igor Sysoev369145c2004-05-28 15:49:23 +0000234 if (ngx_buf_special(buf)) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000235 return 0;
236 }
237
Igor Sysoevf6906042004-11-25 16:17:31 +0000238 sendfile = ctx->sendfile;
239
240#if (NGX_SENDFILE_LIMIT)
241
242 if (buf->in_file && buf->file_pos >= NGX_SENDFILE_LIMIT) {
243 sendfile = 0;
244 }
245
246#endif
247
248 if (!sendfile) {
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000249
Igor Sysoev369145c2004-05-28 15:49:23 +0000250 if (!ngx_buf_in_memory(buf)) {
Igor Sysoev65977492003-11-02 22:56:18 +0000251 return 1;
252 }
253
Igor Sysoev369145c2004-05-28 15:49:23 +0000254 buf->in_file = 0;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000255 }
256
Igor Sysoev369145c2004-05-28 15:49:23 +0000257 if (ctx->need_in_memory && !ngx_buf_in_memory(buf)) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000258 return 1;
259 }
260
Igor Sysoev369145c2004-05-28 15:49:23 +0000261 if (ctx->need_in_temp && (buf->memory || buf->mmap)) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000262 return 1;
263 }
264
265 return 0;
266}
267
268
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000269static ngx_int_t
270ngx_output_chain_add_copy(ngx_pool_t *pool, ngx_chain_t **chain,
271 ngx_chain_t *in)
Igor Sysoevf6906042004-11-25 16:17:31 +0000272{
273 ngx_chain_t *cl, **ll;
274#if (NGX_SENDFILE_LIMIT)
275 ngx_buf_t *b, *buf;
276#endif
277
278 ll = chain;
279
280 for (cl = *chain; cl; cl = cl->next) {
281 ll = &cl->next;
282 }
283
284 while (in) {
285
Igor Sysoevc1571722005-03-19 12:38:37 +0000286 cl = ngx_alloc_chain_link(pool);
287 if (cl == NULL) {
Igor Sysoevf6906042004-11-25 16:17:31 +0000288 return NGX_ERROR;
289 }
290
291#if (NGX_SENDFILE_LIMIT)
292
293 buf = in->buf;
294
295 if (buf->in_file
296 && buf->file_pos < NGX_SENDFILE_LIMIT
297 && buf->file_last > NGX_SENDFILE_LIMIT)
298 {
Igor Sysoevc1571722005-03-19 12:38:37 +0000299 b = ngx_calloc_buf(pool);
300 if (b == NULL) {
Igor Sysoevf6906042004-11-25 16:17:31 +0000301 return NGX_ERROR;
302 }
303
304 ngx_memcpy(b, buf, sizeof(ngx_buf_t));
305
306 if (ngx_buf_in_memory(buf)) {
307 buf->pos += (ssize_t) (NGX_SENDFILE_LIMIT - buf->file_pos);
308 b->last = buf->pos;
309 }
310
311 buf->file_pos = NGX_SENDFILE_LIMIT;
312 b->file_last = NGX_SENDFILE_LIMIT;
313
314 cl->buf = b;
315
316 } else {
317 cl->buf = buf;
318 in = in->next;
319 }
320
321#else
322 cl->buf = in->buf;
323 in = in->next;
324
325#endif
326
327 *ll = cl;
328 ll = &cl->next;
329 }
330
331 *ll = NULL;
332
333 return NGX_OK;
334}
335
336
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000337static ngx_int_t
338ngx_output_chain_copy_buf(ngx_buf_t *dst, ngx_buf_t *src, ngx_uint_t sendfile)
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000339{
Igor Sysoev42b12b32004-12-02 18:40:46 +0000340 off_t size;
Igor Sysoevd9d0ca12003-11-21 06:30:49 +0000341 ssize_t n;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000342
Igor Sysoev369145c2004-05-28 15:49:23 +0000343 size = ngx_buf_size(src);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000344
Igor Sysoev42b12b32004-12-02 18:40:46 +0000345 if (size > dst->end - dst->pos) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000346 size = dst->end - dst->pos;
347 }
348
Igor Sysoevf6906042004-11-25 16:17:31 +0000349#if (NGX_SENDFILE_LIMIT)
350
351 if (src->in_file && src->file_pos >= NGX_SENDFILE_LIMIT) {
352 sendfile = 0;
353 }
354
355#endif
356
Igor Sysoev369145c2004-05-28 15:49:23 +0000357 if (ngx_buf_in_memory(src)) {
Igor Sysoev42b12b32004-12-02 18:40:46 +0000358 ngx_memcpy(dst->pos, src->pos, (size_t) size);
359 src->pos += (size_t) size;
360 dst->last += (size_t) size;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000361
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000362 if (src->in_file) {
363
364 if (sendfile) {
365 dst->in_file = 1;
366 dst->file = src->file;
367 dst->file_pos = src->file_pos;
368 dst->file_last = src->file_pos + size;
369
370 } else {
371 dst->in_file = 0;
372 }
373
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000374 src->file_pos += size;
Igor Sysoev924bd792004-10-11 15:07:03 +0000375
376 } else {
377 dst->in_file = 0;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000378 }
379
Igor Sysoevb2c5db52007-06-03 19:58:30 +0000380 if (src->pos == src->last) {
381 dst->flush = src->flush;
382 dst->last_buf = src->last_buf;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000383 }
384
385 } else {
Igor Sysoev42b12b32004-12-02 18:40:46 +0000386 n = ngx_read_file(src->file, dst->pos, (size_t) size, src->file_pos);
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000387
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000388 if (n == NGX_ERROR) {
Igor Sysoev4959ec42005-05-23 12:07:45 +0000389 return (ngx_int_t) n;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000390 }
391
392#if (NGX_FILE_AIO_READ)
393 if (n == NGX_AGAIN) {
Igor Sysoev4959ec42005-05-23 12:07:45 +0000394 return (ngx_int_t) n;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000395 }
396#endif
397
Igor Sysoev42b12b32004-12-02 18:40:46 +0000398 if (n != size) {
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000399 ngx_log_error(NGX_LOG_ALERT, src->file->log, 0,
Igor Sysoev42b12b32004-12-02 18:40:46 +0000400 ngx_read_file_n " reads only %z of %O from file",
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000401 n, size);
402 if (n == 0) {
403 return NGX_ERROR;
404 }
405 }
406
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000407 dst->last += n;
408
Igor Sysoev924bd792004-10-11 15:07:03 +0000409 if (sendfile) {
410 dst->in_file = 1;
411 dst->file = src->file;
412 dst->file_pos = src->file_pos;
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000413 dst->file_last = src->file_pos + n;
Igor Sysoev924bd792004-10-11 15:07:03 +0000414
415 } else {
Igor Sysoev369145c2004-05-28 15:49:23 +0000416 dst->in_file = 0;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000417 }
418
Igor Sysoevc0edbcc2004-10-21 15:34:38 +0000419 src->file_pos += n;
420
Igor Sysoev52a93432007-06-06 05:56:51 +0000421 if (src->file_pos == src->file_last) {
Igor Sysoevb2c5db52007-06-03 19:58:30 +0000422 dst->flush = src->flush;
423 dst->last_buf = src->last_buf;
Igor Sysoev10fc9ef2003-10-27 08:53:49 +0000424 }
425 }
426
427 return NGX_OK;
428}
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000429
430
Igor Sysoev8184d1b2005-03-04 14:06:57 +0000431ngx_int_t
432ngx_chain_writer(void *data, ngx_chain_t *in)
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000433{
Igor Sysoev68ee8f12003-10-30 08:51:06 +0000434 ngx_chain_writer_ctx_t *ctx = data;
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000435
Igor Sysoev693bf6d2008-04-09 18:56:36 +0000436 off_t size;
437 ngx_chain_t *cl;
438 ngx_connection_t *c;
439
440 c = ctx->connection;
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000441
Igor Sysoev42b12b32004-12-02 18:40:46 +0000442 for (size = 0; in; in = in->next) {
443
444#if 1
445 if (ngx_buf_size(in->buf) == 0 && !ngx_buf_special(in->buf)) {
446 ngx_debug_point();
447 }
448#endif
449
450 size += ngx_buf_size(in->buf);
Igor Sysoev967fd632004-08-27 15:40:59 +0000451
Igor Sysoev693bf6d2008-04-09 18:56:36 +0000452 ngx_log_debug2(NGX_LOG_DEBUG_CORE, c->log, 0,
Igor Sysoev70c1d0f2007-06-03 19:56:27 +0000453 "chain writer buf fl:%d s:%uO",
454 in->buf->flush, ngx_buf_size(in->buf));
Igor Sysoev967fd632004-08-27 15:40:59 +0000455
Igor Sysoevc1571722005-03-19 12:38:37 +0000456 cl = ngx_alloc_chain_link(ctx->pool);
457 if (cl == NULL) {
Igor Sysoev1b735832004-11-11 14:07:14 +0000458 return NGX_ERROR;
459 }
Igor Sysoevc1571722005-03-19 12:38:37 +0000460
Igor Sysoev1b735832004-11-11 14:07:14 +0000461 cl->buf = in->buf;
462 cl->next = NULL;
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000463 *ctx->last = cl;
464 ctx->last = &cl->next;
465 }
466
Igor Sysoev693bf6d2008-04-09 18:56:36 +0000467 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000468 "chain writer in: %p", ctx->out);
Igor Sysoev9c610952004-03-16 13:35:20 +0000469
Igor Sysoev42b12b32004-12-02 18:40:46 +0000470 for (cl = ctx->out; cl; cl = cl->next) {
471
472#if 1
Igor Sysoev42b12b32004-12-02 18:40:46 +0000473 if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
474 ngx_debug_point();
475 }
476
477#endif
478
479 size += ngx_buf_size(cl->buf);
480 }
481
Igor Sysoev693bf6d2008-04-09 18:56:36 +0000482 if (size == 0 && !c->buffered) {
Igor Sysoev42b12b32004-12-02 18:40:46 +0000483 return NGX_OK;
484 }
485
Igor Sysoev693bf6d2008-04-09 18:56:36 +0000486 ctx->out = c->send_chain(c, ctx->out, ctx->limit);
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000487
Igor Sysoev693bf6d2008-04-09 18:56:36 +0000488 ngx_log_debug1(NGX_LOG_DEBUG_CORE, c->log, 0,
Igor Sysoev1b735832004-11-11 14:07:14 +0000489 "chain writer out: %p", ctx->out);
Igor Sysoev9c610952004-03-16 13:35:20 +0000490
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000491 if (ctx->out == NGX_CHAIN_ERROR) {
492 return NGX_ERROR;
493 }
494
495 if (ctx->out == NULL) {
496 ctx->last = &ctx->out;
Igor Sysoevb8ddf752007-05-28 11:09:18 +0000497
Igor Sysoev693bf6d2008-04-09 18:56:36 +0000498 if (!c->buffered) {
Igor Sysoevacac0032007-05-29 12:06:42 +0000499 return NGX_OK;
500 }
Igor Sysoev2b0c76c2003-10-27 21:01:00 +0000501 }
502
503 return NGX_AGAIN;
504}