~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/ngx_http_write_filter_module.c

Version: ~ [ nginx-0.8.20 ] ~ [ nginx-0.7.62 ] ~ [ nginx-0.6.39 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  */
  5 
  6 
  7 #include <ngx_config.h>
  8 #include <ngx_core.h>
  9 #include <ngx_http.h>
 10 
 11 
 12 static ngx_int_t ngx_http_write_filter_init(ngx_conf_t *cf);
 13 
 14 
 15 static ngx_http_module_t  ngx_http_write_filter_module_ctx = {
 16     NULL,                                  /* preconfiguration */
 17     ngx_http_write_filter_init,            /* postconfiguration */
 18 
 19     NULL,                                  /* create main configuration */
 20     NULL,                                  /* init main configuration */
 21 
 22     NULL,                                  /* create server configuration */
 23     NULL,                                  /* merge server configuration */
 24 
 25     NULL,                                  /* create location configuration */
 26     NULL,                                  /* merge location configuration */
 27 };
 28 
 29 
 30 ngx_module_t  ngx_http_write_filter_module = {
 31     NGX_MODULE_V1,
 32     &ngx_http_write_filter_module_ctx,     /* module context */
 33     NULL,                                  /* module directives */
 34     NGX_HTTP_MODULE,                       /* module type */
 35     NULL,                                  /* init master */
 36     NULL,                                  /* init module */
 37     NULL,                                  /* init process */
 38     NULL,                                  /* init thread */
 39     NULL,                                  /* exit thread */
 40     NULL,                                  /* exit process */
 41     NULL,                                  /* exit master */
 42     NGX_MODULE_V1_PADDING
 43 };
 44 
 45 
 46 ngx_int_t
 47 ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
 48 {
 49     off_t                      size, sent, nsent, limit;
 50     ngx_uint_t                 last, flush;
 51     ngx_msec_t                 delay;
 52     ngx_chain_t               *cl, *ln, **ll, *chain;
 53     ngx_connection_t          *c;
 54     ngx_http_core_loc_conf_t  *clcf;
 55 
 56     c = r->connection;
 57 
 58     if (c->error) {
 59         return NGX_ERROR;
 60     }
 61 
 62     size = 0;
 63     flush = 0;
 64     last = 0;
 65     ll = &r->out;
 66 
 67     /* find the size, the flush point and the last link of the saved chain */
 68 
 69     for (cl = r->out; cl; cl = cl->next) {
 70         ll = &cl->next;
 71 
 72         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
 73                        "write old buf t:%d f:%d %p, pos %p, size: %z "
 74                        "file: %O, size: %z",
 75                        cl->buf->temporary, cl->buf->in_file,
 76                        cl->buf->start, cl->buf->pos,
 77                        cl->buf->last - cl->buf->pos,
 78                        cl->buf->file_pos,
 79                        cl->buf->file_last - cl->buf->file_pos);
 80 
 81 #if 1
 82         if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
 83             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
 84                           "zero size buf in writer "
 85                           "t:%d r:%d f:%d %p %p-%p %p %O-%O",
 86                           cl->buf->temporary,
 87                           cl->buf->recycled,
 88                           cl->buf->in_file,
 89                           cl->buf->start,
 90                           cl->buf->pos,
 91                           cl->buf->last,
 92                           cl->buf->file,
 93                           cl->buf->file_pos,
 94                           cl->buf->file_last);
 95 
 96             ngx_debug_point();
 97             return NGX_ERROR;
 98         }
 99 #endif
100 
101         size += ngx_buf_size(cl->buf);
102 
103         if (cl->buf->flush || cl->buf->recycled) {
104             flush = 1;
105         }
106 
107         if (cl->buf->last_buf) {
108             last = 1;
109         }
110     }
111 
112     /* add the new chain to the existent one */
113 
114     for (ln = in; ln; ln = ln->next) {
115         cl = ngx_alloc_chain_link(r->pool);
116         if (cl == NULL) {
117             return NGX_ERROR;
118         }
119 
120         cl->buf = ln->buf;
121         *ll = cl;
122         ll = &cl->next;
123 
124         ngx_log_debug7(NGX_LOG_DEBUG_EVENT, c->log, 0,
125                        "write new buf t:%d f:%d %p, pos %p, size: %z "
126                        "file: %O, size: %z",
127                        cl->buf->temporary, cl->buf->in_file,
128                        cl->buf->start, cl->buf->pos,
129                        cl->buf->last - cl->buf->pos,
130                        cl->buf->file_pos,
131                        cl->buf->file_last - cl->buf->file_pos);
132 
133 #if 1
134         if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
135             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
136                           "zero size buf in writer "
137                           "t:%d r:%d f:%d %p %p-%p %p %O-%O",
138                           cl->buf->temporary,
139                           cl->buf->recycled,
140                           cl->buf->in_file,
141                           cl->buf->start,
142                           cl->buf->pos,
143                           cl->buf->last,
144                           cl->buf->file,
145                           cl->buf->file_pos,
146                           cl->buf->file_last);
147 
148             ngx_debug_point();
149             return NGX_ERROR;
150         }
151 #endif
152 
153         size += ngx_buf_size(cl->buf);
154 
155         if (cl->buf->flush || cl->buf->recycled) {
156             flush = 1;
157         }
158 
159         if (cl->buf->last_buf) {
160             last = 1;
161         }
162     }
163 
164     *ll = NULL;
165 
166     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
167                    "http write filter: l:%d f:%d s:%O", last, flush, size);
168 
169     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
170 
171     /*
172      * avoid the output if there are no last buf, no flush point,
173      * there are the incoming bufs and the size of all bufs
174      * is smaller than "postpone_output" directive
175      */
176 
177     if (!last && !flush && in && size < (off_t) clcf->postpone_output) {
178         return NGX_OK;
179     }
180 
181     if (c->write->delayed) {
182         c->buffered |= NGX_HTTP_WRITE_BUFFERED;
183         return NGX_AGAIN;
184     }
185 
186     if (size == 0 && !(c->buffered & NGX_LOWLEVEL_BUFFERED)) {
187         if (last) {
188             r->out = NULL;
189             c->buffered &= ~NGX_HTTP_WRITE_BUFFERED;
190 
191             return NGX_OK;
192         }
193 
194         if (flush) {
195             do {
196                 r->out = r->out->next;
197             } while (r->out);
198 
199             c->buffered &= ~NGX_HTTP_WRITE_BUFFERED;
200 
201             return NGX_OK;
202         }
203 
204         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
205                       "the http output chain is empty");
206 
207         ngx_debug_point();
208 
209         return NGX_ERROR;
210     }
211 
212     if (r->limit_rate) {
213         limit = r->limit_rate * (ngx_time() - r->start_sec + 1)
214                 - (c->sent - clcf->limit_rate_after);
215 
216         if (limit <= 0) {
217             c->write->delayed = 1;
218             ngx_add_timer(c->write,
219                           (ngx_msec_t) (- limit * 1000 / r->limit_rate + 1));
220 
221             c->buffered |= NGX_HTTP_WRITE_BUFFERED;
222 
223             return NGX_AGAIN;
224         }
225 
226     } else if (clcf->sendfile_max_chunk) {
227         limit = clcf->sendfile_max_chunk;
228 
229     } else {
230         limit = 0;
231     }
232 
233     sent = c->sent;
234 
235     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
236                    "http write filter limit %O", limit);
237 
238     chain = c->send_chain(c, r->out, limit);
239 
240     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
241                    "http write filter %p", chain);
242 
243     if (chain == NGX_CHAIN_ERROR) {
244         c->error = 1;
245         return NGX_ERROR;
246     }
247 
248     if (r->limit_rate) {
249 
250         nsent = c->sent;
251 
252         if (clcf->limit_rate_after) {
253 
254             sent -= clcf->limit_rate_after;
255             if (sent < 0) {
256                 sent = 0;
257             }
258 
259             nsent -= clcf->limit_rate_after;
260             if (nsent < 0) {
261                 nsent = 0;
262             }
263         }
264 
265         delay = (ngx_msec_t) ((nsent - sent) * 1000 / r->limit_rate + 1);
266 
267         if (delay > 0) {
268             c->write->delayed = 1;
269             ngx_add_timer(c->write, delay);
270         }
271 
272     } else if (c->write->ready
273                && clcf->sendfile_max_chunk
274                && (size_t) (c->sent - sent)
275                       >= clcf->sendfile_max_chunk - 2 * ngx_pagesize)
276     {
277         c->write->delayed = 1;
278         ngx_add_timer(c->write, 1);
279     }
280 
281     for (cl = r->out; cl && cl != chain; /* void */) {
282         ln = cl;
283         cl = cl->next;
284         ngx_free_chain(r->pool, ln);
285     }
286 
287     r->out = chain;
288 
289     if (chain) {
290         c->buffered |= NGX_HTTP_WRITE_BUFFERED;
291         return NGX_AGAIN;
292     }
293 
294     c->buffered &= ~NGX_HTTP_WRITE_BUFFERED;
295 
296     if ((c->buffered & NGX_LOWLEVEL_BUFFERED) && r->postponed == NULL) {
297         return NGX_AGAIN;
298     }
299 
300     return NGX_OK;
301 }
302 
303 
304 static ngx_int_t
305 ngx_http_write_filter_init(ngx_conf_t *cf)
306 {
307     ngx_http_top_body_filter = ngx_http_write_filter;
308 
309     return NGX_OK;
310 }
311 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.