Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_http.h>
0011 
0012 
0013 typedef struct {
0014     ngx_bufs_t  bufs;
0015 } ngx_http_copy_filter_conf_t;
0016 
0017 
0018 #if (NGX_HAVE_FILE_AIO)
0019 static void ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx,
0020     ngx_file_t *file);
0021 static void ngx_http_copy_aio_event_handler(ngx_event_t *ev);
0022 #if (NGX_HAVE_AIO_SENDFILE)
0023 static ssize_t ngx_http_copy_aio_sendfile_preload(ngx_buf_t *file);
0024 static void ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev);
0025 #endif
0026 #endif
0027 #if (NGX_THREADS)
0028 static ngx_int_t ngx_http_copy_thread_handler(ngx_thread_task_t *task,
0029     ngx_file_t *file);
0030 static void ngx_http_copy_thread_event_handler(ngx_event_t *ev);
0031 #endif
0032 
0033 static void *ngx_http_copy_filter_create_conf(ngx_conf_t *cf);
0034 static char *ngx_http_copy_filter_merge_conf(ngx_conf_t *cf,
0035     void *parent, void *child);
0036 static ngx_int_t ngx_http_copy_filter_init(ngx_conf_t *cf);
0037 
0038 
0039 static ngx_command_t  ngx_http_copy_filter_commands[] = {
0040 
0041     { ngx_string("output_buffers"),
0042       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
0043       ngx_conf_set_bufs_slot,
0044       NGX_HTTP_LOC_CONF_OFFSET,
0045       offsetof(ngx_http_copy_filter_conf_t, bufs),
0046       NULL },
0047 
0048       ngx_null_command
0049 };
0050 
0051 
0052 static ngx_http_module_t  ngx_http_copy_filter_module_ctx = {
0053     NULL,                                  /* preconfiguration */
0054     ngx_http_copy_filter_init,             /* postconfiguration */
0055 
0056     NULL,                                  /* create main configuration */
0057     NULL,                                  /* init main configuration */
0058 
0059     NULL,                                  /* create server configuration */
0060     NULL,                                  /* merge server configuration */
0061 
0062     ngx_http_copy_filter_create_conf,      /* create location configuration */
0063     ngx_http_copy_filter_merge_conf        /* merge location configuration */
0064 };
0065 
0066 
0067 ngx_module_t  ngx_http_copy_filter_module = {
0068     NGX_MODULE_V1,
0069     &ngx_http_copy_filter_module_ctx,      /* module context */
0070     ngx_http_copy_filter_commands,         /* module directives */
0071     NGX_HTTP_MODULE,                       /* module type */
0072     NULL,                                  /* init master */
0073     NULL,                                  /* init module */
0074     NULL,                                  /* init process */
0075     NULL,                                  /* init thread */
0076     NULL,                                  /* exit thread */
0077     NULL,                                  /* exit process */
0078     NULL,                                  /* exit master */
0079     NGX_MODULE_V1_PADDING
0080 };
0081 
0082 
0083 static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
0084 
0085 
0086 static ngx_int_t
0087 ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in)
0088 {
0089     ngx_int_t                     rc;
0090     ngx_connection_t             *c;
0091     ngx_output_chain_ctx_t       *ctx;
0092     ngx_http_core_loc_conf_t     *clcf;
0093     ngx_http_copy_filter_conf_t  *conf;
0094 
0095     c = r->connection;
0096 
0097     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
0098                    "http copy filter: \"%V?%V\"", &r->uri, &r->args);
0099 
0100     ctx = ngx_http_get_module_ctx(r, ngx_http_copy_filter_module);
0101 
0102     if (ctx == NULL) {
0103         ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t));
0104         if (ctx == NULL) {
0105             return NGX_ERROR;
0106         }
0107 
0108         ngx_http_set_ctx(r, ctx, ngx_http_copy_filter_module);
0109 
0110         conf = ngx_http_get_module_loc_conf(r, ngx_http_copy_filter_module);
0111         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
0112 
0113         ctx->sendfile = c->sendfile;
0114         ctx->need_in_memory = r->main_filter_need_in_memory
0115                               || r->filter_need_in_memory;
0116         ctx->need_in_temp = r->filter_need_temporary;
0117 
0118         ctx->alignment = clcf->directio_alignment;
0119 
0120         ctx->pool = r->pool;
0121         ctx->bufs = conf->bufs;
0122         ctx->tag = (ngx_buf_tag_t) &ngx_http_copy_filter_module;
0123 
0124         ctx->output_filter = (ngx_output_chain_filter_pt)
0125                                   ngx_http_next_body_filter;
0126         ctx->filter_ctx = r;
0127 
0128 #if (NGX_HAVE_FILE_AIO)
0129         if (ngx_file_aio && clcf->aio == NGX_HTTP_AIO_ON) {
0130             ctx->aio_handler = ngx_http_copy_aio_handler;
0131 #if (NGX_HAVE_AIO_SENDFILE)
0132             ctx->aio_preload = ngx_http_copy_aio_sendfile_preload;
0133 #endif
0134         }
0135 #endif
0136 
0137 #if (NGX_THREADS)
0138         if (clcf->aio == NGX_HTTP_AIO_THREADS) {
0139             ctx->thread_handler = ngx_http_copy_thread_handler;
0140         }
0141 #endif
0142 
0143         if (in && in->buf && ngx_buf_size(in->buf)) {
0144             r->request_output = 1;
0145         }
0146     }
0147 
0148 #if (NGX_HAVE_FILE_AIO || NGX_THREADS)
0149     ctx->aio = r->aio;
0150 #endif
0151 
0152     rc = ngx_output_chain(ctx, in);
0153 
0154     if (ctx->in == NULL) {
0155         r->buffered &= ~NGX_HTTP_COPY_BUFFERED;
0156 
0157     } else {
0158         r->buffered |= NGX_HTTP_COPY_BUFFERED;
0159     }
0160 
0161     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
0162                    "http copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args);
0163 
0164     return rc;
0165 }
0166 
0167 
0168 #if (NGX_HAVE_FILE_AIO)
0169 
0170 static void
0171 ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx, ngx_file_t *file)
0172 {
0173     ngx_http_request_t *r;
0174 
0175     r = ctx->filter_ctx;
0176 
0177     file->aio->data = r;
0178     file->aio->handler = ngx_http_copy_aio_event_handler;
0179 
0180     r->main->blocked++;
0181     r->aio = 1;
0182     ctx->aio = 1;
0183 }
0184 
0185 
0186 static void
0187 ngx_http_copy_aio_event_handler(ngx_event_t *ev)
0188 {
0189     ngx_event_aio_t     *aio;
0190     ngx_connection_t    *c;
0191     ngx_http_request_t  *r;
0192 
0193     aio = ev->data;
0194     r = aio->data;
0195     c = r->connection;
0196 
0197     ngx_http_set_log_request(c->log, r);
0198 
0199     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
0200                    "http aio: \"%V?%V\"", &r->uri, &r->args);
0201 
0202     r->main->blocked--;
0203     r->aio = 0;
0204 
0205     r->write_event_handler(r);
0206 
0207     ngx_http_run_posted_requests(c);
0208 }
0209 
0210 
0211 #if (NGX_HAVE_AIO_SENDFILE)
0212 
0213 static ssize_t
0214 ngx_http_copy_aio_sendfile_preload(ngx_buf_t *file)
0215 {
0216     ssize_t                  n;
0217     static u_char            buf[1];
0218     ngx_event_aio_t         *aio;
0219     ngx_http_request_t      *r;
0220     ngx_output_chain_ctx_t  *ctx;
0221 
0222     n = ngx_file_aio_read(file->file, buf, 1, file->file_pos, NULL);
0223 
0224     if (n == NGX_AGAIN) {
0225         aio = file->file->aio;
0226         aio->handler = ngx_http_copy_aio_sendfile_event_handler;
0227 
0228         r = aio->data;
0229         r->main->blocked++;
0230         r->aio = 1;
0231 
0232         ctx = ngx_http_get_module_ctx(r, ngx_http_copy_filter_module);
0233         ctx->aio = 1;
0234     }
0235 
0236     return n;
0237 }
0238 
0239 
0240 static void
0241 ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev)
0242 {
0243     ngx_event_aio_t     *aio;
0244     ngx_http_request_t  *r;
0245 
0246     aio = ev->data;
0247     r = aio->data;
0248 
0249     r->main->blocked--;
0250     r->aio = 0;
0251     ev->complete = 0;
0252 
0253     r->connection->write->handler(r->connection->write);
0254 }
0255 
0256 #endif
0257 #endif
0258 
0259 
0260 #if (NGX_THREADS)
0261 
0262 static ngx_int_t
0263 ngx_http_copy_thread_handler(ngx_thread_task_t *task, ngx_file_t *file)
0264 {
0265     ngx_str_t                  name;
0266     ngx_thread_pool_t         *tp;
0267     ngx_http_request_t        *r;
0268     ngx_output_chain_ctx_t    *ctx;
0269     ngx_http_core_loc_conf_t  *clcf;
0270 
0271     r = file->thread_ctx;
0272 
0273     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
0274     tp = clcf->thread_pool;
0275 
0276     if (tp == NULL) {
0277         if (ngx_http_complex_value(r, clcf->thread_pool_value, &name)
0278             != NGX_OK)
0279         {
0280             return NGX_ERROR;
0281         }
0282 
0283         tp = ngx_thread_pool_get((ngx_cycle_t *) ngx_cycle, &name);
0284 
0285         if (tp == NULL) {
0286             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
0287                           "thread pool \"%V\" not found", &name);
0288             return NGX_ERROR;
0289         }
0290     }
0291 
0292     task->event.data = r;
0293     task->event.handler = ngx_http_copy_thread_event_handler;
0294 
0295     if (ngx_thread_task_post(tp, task) != NGX_OK) {
0296         return NGX_ERROR;
0297     }
0298 
0299     r->main->blocked++;
0300     r->aio = 1;
0301 
0302     ctx = ngx_http_get_module_ctx(r, ngx_http_copy_filter_module);
0303     ctx->aio = 1;
0304 
0305     return NGX_OK;
0306 }
0307 
0308 
0309 static void
0310 ngx_http_copy_thread_event_handler(ngx_event_t *ev)
0311 {
0312     ngx_connection_t    *c;
0313     ngx_http_request_t  *r;
0314 
0315     r = ev->data;
0316     c = r->connection;
0317 
0318     ngx_http_set_log_request(c->log, r);
0319 
0320     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
0321                    "http thread: \"%V?%V\"", &r->uri, &r->args);
0322 
0323     r->main->blocked--;
0324     r->aio = 0;
0325 
0326     if (r->done) {
0327         /*
0328          * trigger connection event handler if the subrequest was
0329          * already finalized; this can happen if the handler is used
0330          * for sendfile() in threads
0331          */
0332 
0333         c->write->handler(c->write);
0334 
0335     } else {
0336         r->write_event_handler(r);
0337         ngx_http_run_posted_requests(c);
0338     }
0339 }
0340 
0341 #endif
0342 
0343 
0344 static void *
0345 ngx_http_copy_filter_create_conf(ngx_conf_t *cf)
0346 {
0347     ngx_http_copy_filter_conf_t *conf;
0348 
0349     conf = ngx_palloc(cf->pool, sizeof(ngx_http_copy_filter_conf_t));
0350     if (conf == NULL) {
0351         return NULL;
0352     }
0353 
0354     conf->bufs.num = 0;
0355 
0356     return conf;
0357 }
0358 
0359 
0360 static char *
0361 ngx_http_copy_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
0362 {
0363     ngx_http_copy_filter_conf_t *prev = parent;
0364     ngx_http_copy_filter_conf_t *conf = child;
0365 
0366     ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 2, 32768);
0367 
0368     return NULL;
0369 }
0370 
0371 
0372 static ngx_int_t
0373 ngx_http_copy_filter_init(ngx_conf_t *cf)
0374 {
0375     ngx_http_next_body_filter = ngx_http_top_body_filter;
0376     ngx_http_top_body_filter = ngx_http_copy_filter;
0377 
0378     return NGX_OK;
0379 }
0380