Annotation of embedaddon/nginx/src/http/ngx_http_copy_filter_module.c, revision 1.1.1.1

1.1       misho       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 {
                     14:     ngx_bufs_t  bufs;
                     15: } ngx_http_copy_filter_conf_t;
                     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"),
                     36:       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
                     37:       ngx_conf_set_bufs_slot,
                     38:       NGX_HTTP_LOC_CONF_OFFSET,
                     39:       offsetof(ngx_http_copy_filter_conf_t, bufs),
                     40:       NULL },
                     41: 
                     42:       ngx_null_command
                     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: 
                     61: ngx_module_t  ngx_http_copy_filter_module = {
                     62:     NGX_MODULE_V1,
                     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 */
                     73:     NGX_MODULE_V1_PADDING
                     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;
                     84:     ngx_connection_t             *c;
                     85:     ngx_output_chain_ctx_t       *ctx;
                     86:     ngx_http_core_loc_conf_t     *clcf;
                     87:     ngx_http_copy_filter_conf_t  *conf;
                     88: 
                     89:     c = r->connection;
                     90: 
                     91:     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                     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);
                    105:         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
                    106: 
                    107:         ctx->sendfile = c->sendfile;
                    108:         ctx->need_in_memory = r->main_filter_need_in_memory
                    109:                               || r->filter_need_in_memory;
                    110:         ctx->need_in_temp = r->filter_need_temporary;
                    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: 
                    118:         ctx->output_filter = (ngx_output_chain_filter_pt)
                    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) {
                    146:             r->buffered &= ~NGX_HTTP_COPY_BUFFERED;
                    147: 
                    148:         } else {
                    149:             r->buffered |= NGX_HTTP_COPY_BUFFERED;
                    150:         }
                    151: 
                    152:         ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
                    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;
                    161:             ngx_http_ephemeral_t  *e;
                    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) {
                    176:                     ngx_log_error(NGX_LOG_ALERT, c->log, 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: {
                    214:     ngx_http_request_t *r;
                    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;
                    231:     ngx_http_request_t  *r;
                    232: 
                    233:     aio = ev->data;
                    234:     r = aio->data;
                    235: 
                    236:     r->main->blocked--;
                    237:     r->aio = 0;
                    238: 
                    239:     r->connection->write->handler(r->connection->write);
                    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;
                    249:     ngx_http_request_t  *r;
                    250: 
                    251:     aio = ev->data;
                    252:     r = aio->data;
                    253: 
                    254:     r->main->blocked--;
                    255:     r->aio = 0;
                    256:     ev->complete = 0;
                    257: 
                    258:     r->connection->write->handler(r->connection->write);
                    259: }
                    260: 
                    261: #endif
                    262: #endif
                    263: 
                    264: 
                    265: static void *
                    266: ngx_http_copy_filter_create_conf(ngx_conf_t *cf)
                    267: {
                    268:     ngx_http_copy_filter_conf_t *conf;
                    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: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>