Annotation of embedaddon/nginx/src/http/ngx_http_write_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: 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, nsent, 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 || 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;
                    196:             c->buffered &= ~NGX_HTTP_WRITE_BUFFERED;
                    197: 
                    198:             return NGX_OK;
                    199:         }
                    200: 
                    201:         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
                    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: 
                    218:             c->buffered |= NGX_HTTP_WRITE_BUFFERED;
                    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: 
                    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: 
                    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) {
                    291:         c->buffered |= NGX_HTTP_WRITE_BUFFERED;
                    292:         return NGX_AGAIN;
                    293:     }
                    294: 
                    295:     c->buffered &= ~NGX_HTTP_WRITE_BUFFERED;
                    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: {
                    308:     ngx_http_top_body_filter = ngx_http_write_filter;
                    309: 
                    310:     return NGX_OK;
                    311: }

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