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

Linux Cross Reference
Nginx/http/ngx_http_write_filter_module.c

Version: ~ [ nginx-0.6.26 ] ~ [ nginx-0.5.35 ] ~ [ nginx-0.5.20 ] ~ [ nginx-0.5.19 ] ~

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

~ [ 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.