Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_http_write_filter_module.c
Go to the documentation of this file.
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 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 
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 */
44 };
45 
46 
49 {
50  off_t size, sent, nsent, limit;
51  ngx_uint_t last, flush;
52  ngx_msec_t delay;
53  ngx_chain_t *cl, *ln, **ll, *chain;
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 
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)) {
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 
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 
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)) {
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 
168  "http write filter: l:%d f:%d s:%O", last, flush, size);
169 
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) {
184  return NGX_AGAIN;
185  }
186 
187  if (size == 0 && !(c->buffered & NGX_LOWLEVEL_BUFFERED)) {
188  if (last || flush) {
189  for (cl = r->out; cl; /* void */) {
190  ln = cl;
191  cl = cl->next;
192  ngx_free_chain(r->pool, ln);
193  }
194 
195  r->out = NULL;
197 
198  return NGX_OK;
199  }
200 
202  "the http output chain is empty");
203 
204  ngx_debug_point();
205 
206  return NGX_ERROR;
207  }
208 
209  if (r->limit_rate) {
210  limit = (off_t) r->limit_rate * (ngx_time() - r->start_sec + 1)
211  - (c->sent - clcf->limit_rate_after);
212 
213  if (limit <= 0) {
214  c->write->delayed = 1;
215  ngx_add_timer(c->write,
216  (ngx_msec_t) (- limit * 1000 / r->limit_rate + 1));
217 
219 
220  return NGX_AGAIN;
221  }
222 
223  if (clcf->sendfile_max_chunk
224  && (off_t) clcf->sendfile_max_chunk < limit)
225  {
226  limit = clcf->sendfile_max_chunk;
227  }
228 
229  } else {
230  limit = clcf->sendfile_max_chunk;
231  }
232 
233  sent = c->sent;
234 
236  "http write filter limit %O", limit);
237 
238  chain = c->send_chain(c, r->out, limit);
239 
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);
266 
267  if (delay > 0) {
268  limit = 0;
269  c->write->delayed = 1;
270  ngx_add_timer(c->write, delay);
271  }
272  }
273 
274  if (limit
275  && c->write->ready
276  && c->sent - sent >= limit - (off_t) (2 * ngx_pagesize))
277  {
278  c->write->delayed = 1;
279  ngx_add_timer(c->write, 1);
280  }
281 
282  for (cl = r->out; cl && cl != chain; /* void */) {
283  ln = cl;
284  cl = cl->next;
285  ngx_free_chain(r->pool, ln);
286  }
287 
288  r->out = chain;
289 
290  if (chain) {
292  return NGX_AGAIN;
293  }
294 
296 
297  if ((c->buffered & NGX_LOWLEVEL_BUFFERED) && r->postponed == NULL) {
298  return NGX_AGAIN;
299  }
300 
301  return NGX_OK;
302 }
303 
304 
305 static ngx_int_t
306 ngx_http_write_filter_init(ngx_conf_t *cf)
307 {
309 
310  return NGX_OK;
311 }