Groonga 3.0.9 Source Code Document
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ngx_http_copy_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 typedef struct {
16 
17 
18 #if (NGX_HAVE_FILE_AIO)
19 static void ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx,
20  ngx_file_t *file);
21 static void ngx_http_copy_aio_event_handler(ngx_event_t *ev);
22 #if (NGX_HAVE_AIO_SENDFILE)
23 static void ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev);
24 #endif
25 #endif
26 
27 static void *ngx_http_copy_filter_create_conf(ngx_conf_t *cf);
28 static char *ngx_http_copy_filter_merge_conf(ngx_conf_t *cf,
29  void *parent, void *child);
30 static ngx_int_t ngx_http_copy_filter_init(ngx_conf_t *cf);
31 
32 
33 static ngx_command_t ngx_http_copy_filter_commands[] = {
34 
35  { ngx_string("output_buffers"),
39  offsetof(ngx_http_copy_filter_conf_t, bufs),
40  NULL },
41 
43 };
44 
45 
46 static ngx_http_module_t ngx_http_copy_filter_module_ctx = {
47  NULL, /* preconfiguration */
48  ngx_http_copy_filter_init, /* postconfiguration */
49 
50  NULL, /* create main configuration */
51  NULL, /* init main configuration */
52 
53  NULL, /* create server configuration */
54  NULL, /* merge server configuration */
55 
56  ngx_http_copy_filter_create_conf, /* create location configuration */
57  ngx_http_copy_filter_merge_conf /* merge location configuration */
58 };
59 
60 
63  &ngx_http_copy_filter_module_ctx, /* module context */
64  ngx_http_copy_filter_commands, /* module directives */
65  NGX_HTTP_MODULE, /* module type */
66  NULL, /* init master */
67  NULL, /* init module */
68  NULL, /* init process */
69  NULL, /* init thread */
70  NULL, /* exit thread */
71  NULL, /* exit process */
72  NULL, /* exit master */
74 };
75 
76 
77 static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
78 
79 
80 static ngx_int_t
81 ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in)
82 {
83  ngx_int_t rc;
88 
89  c = r->connection;
90 
92  "http copy filter: \"%V?%V\"", &r->uri, &r->args);
93 
94  ctx = ngx_http_get_module_ctx(r, ngx_http_copy_filter_module);
95 
96  if (ctx == NULL) {
97  ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t));
98  if (ctx == NULL) {
99  return NGX_ERROR;
100  }
101 
102  ngx_http_set_ctx(r, ctx, ngx_http_copy_filter_module);
103 
104  conf = ngx_http_get_module_loc_conf(r, ngx_http_copy_filter_module);
106 
107  ctx->sendfile = c->sendfile;
109  || r->filter_need_in_memory;
111 
112  ctx->alignment = clcf->directio_alignment;
113 
114  ctx->pool = r->pool;
115  ctx->bufs = conf->bufs;
116  ctx->tag = (ngx_buf_tag_t) &ngx_http_copy_filter_module;
117 
119  ngx_http_next_body_filter;
120  ctx->filter_ctx = r;
121 
122 #if (NGX_HAVE_FILE_AIO)
123  if (ngx_file_aio) {
124  if (clcf->aio) {
125  ctx->aio_handler = ngx_http_copy_aio_handler;
126  }
127 #if (NGX_HAVE_AIO_SENDFILE)
128  c->aio_sendfile = (clcf->aio == NGX_HTTP_AIO_SENDFILE);
129 #endif
130  }
131 #endif
132 
133  if (in && in->buf && ngx_buf_size(in->buf)) {
134  r->request_output = 1;
135  }
136  }
137 
138 #if (NGX_HAVE_FILE_AIO)
139  ctx->aio = r->aio;
140 #endif
141 
142  for ( ;; ) {
143  rc = ngx_output_chain(ctx, in);
144 
145  if (ctx->in == NULL) {
147 
148  } else {
150  }
151 
153  "http copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args);
154 
155 #if (NGX_HAVE_FILE_AIO && NGX_HAVE_AIO_SENDFILE)
156 
157  if (c->busy_sendfile) {
158  ssize_t n;
159  off_t offset;
160  ngx_file_t *file;
162 
163  if (r->aio) {
164  c->busy_sendfile = NULL;
165  return rc;
166  }
167 
168  file = c->busy_sendfile->file;
169  offset = c->busy_sendfile->file_pos;
170 
171  if (file->aio) {
172  c->aio_sendfile = (offset != file->aio->last_offset);
173  file->aio->last_offset = offset;
174 
175  if (c->aio_sendfile == 0) {
177  "sendfile(%V) returned busy again",
178  &file->name);
179  }
180  }
181 
182  c->busy_sendfile = NULL;
183  e = (ngx_http_ephemeral_t *) &r->uri_start;
184 
185  n = ngx_file_aio_read(file, &e->aio_preload, 1, offset, r->pool);
186 
187  if (n > 0) {
188  in = NULL;
189  continue;
190  }
191 
192  rc = n;
193 
194  if (rc == NGX_AGAIN) {
195  file->aio->data = r;
196  file->aio->handler = ngx_http_copy_aio_sendfile_event_handler;
197 
198  r->main->blocked++;
199  r->aio = 1;
200  }
201  }
202 #endif
203 
204  return rc;
205  }
206 }
207 
208 
209 #if (NGX_HAVE_FILE_AIO)
210 
211 static void
212 ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx, ngx_file_t *file)
213 {
215 
216  r = ctx->filter_ctx;
217 
218  file->aio->data = r;
219  file->aio->handler = ngx_http_copy_aio_event_handler;
220 
221  r->main->blocked++;
222  r->aio = 1;
223  ctx->aio = 1;
224 }
225 
226 
227 static void
228 ngx_http_copy_aio_event_handler(ngx_event_t *ev)
229 {
230  ngx_event_aio_t *aio;
232 
233  aio = ev->data;
234  r = aio->data;
235 
236  r->main->blocked--;
237  r->aio = 0;
238 
240 }
241 
242 
243 #if (NGX_HAVE_AIO_SENDFILE)
244 
245 static void
246 ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev)
247 {
248  ngx_event_aio_t *aio;
250 
251  aio = ev->data;
252  r = aio->data;
253 
254  r->main->blocked--;
255  r->aio = 0;
256  ev->complete = 0;
257 
259 }
260 
261 #endif
262 #endif
263 
264 
265 static void *
266 ngx_http_copy_filter_create_conf(ngx_conf_t *cf)
267 {
269 
270  conf = ngx_palloc(cf->pool, sizeof(ngx_http_copy_filter_conf_t));
271  if (conf == NULL) {
272  return NULL;
273  }
274 
275  conf->bufs.num = 0;
276 
277  return conf;
278 }
279 
280 
281 static char *
282 ngx_http_copy_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
283 {
284  ngx_http_copy_filter_conf_t *prev = parent;
285  ngx_http_copy_filter_conf_t *conf = child;
286 
287  ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 1, 32768);
288 
289  return NULL;
290 }
291 
292 
293 static ngx_int_t
294 ngx_http_copy_filter_init(ngx_conf_t *cf)
295 {
296  ngx_http_next_body_filter = ngx_http_top_body_filter;
297  ngx_http_top_body_filter = ngx_http_copy_filter;
298 
299  return NGX_OK;
300 }
301