# HG changeset patch # User Igor Sysoev # Date 1044981743 0 # Node ID 4f3e2abcc2c421b1c8811947906c571f67ef8a2b # Parent 50186b49f2ada074d53f40437f50c990153675e0 nginx-0.0.1-2003-02-11-19:42:23 import diff --git a/src/core/ngx_hunk.h b/src/core/ngx_hunk.h --- a/src/core/ngx_hunk.h +++ b/src/core/ngx_hunk.h @@ -55,6 +55,8 @@ struct ngx_hunk_s { ngx_file_t *file; }; + + typedef struct ngx_chain_s ngx_chain_t; struct ngx_chain_s { ngx_hunk_t *hunk; @@ -62,6 +64,9 @@ struct ngx_chain_s { }; +#define NGX_CHAIN_ERROR (ngx_chain_t *) NGX_ERROR + + ngx_hunk_t *ngx_create_temp_hunk(ngx_pool_t *pool, int size, int before, int after); diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c --- a/src/http/modules/ngx_http_static_handler.c +++ b/src/http/modules/ngx_http_static_handler.c @@ -141,6 +141,8 @@ int ngx_http_static_handler(ngx_http_req if (r->header_only) return rc; +#if 0 + h->type = NGX_HUNK_FILE|NGX_HUNK_LAST; h->pos.file = 0; h->last.file = ngx_file_size(r->file.info); @@ -152,5 +154,42 @@ int ngx_http_static_handler(ngx_http_req ngx_log_debug(r->connection->log, "0 output_filter: %d" _ rc); +#else + +#define BLK 10000 + + { + int i, s; + s = ngx_file_size(r->file.info); + + for (i = 0; i < s; i += BLK) { + ngx_test_null(h, ngx_pcalloc(r->pool, sizeof(ngx_hunk_t)), + NGX_HTTP_INTERNAL_SERVER_ERROR); + + ngx_test_null(h->file, ngx_pcalloc(r->pool, sizeof(ngx_file_t)), + NGX_HTTP_INTERNAL_SERVER_ERROR); + + h->type = NGX_HUNK_FILE; + if (s - i <= BLK) { + h->type |= NGX_HUNK_LAST; + } + + h->pos.file = i; + h->last.file = i + BLK; + if (h->last.file > s) { + h->last.file = s; + } + + h->file->fd = r->file.fd; + h->file->log = r->connection->log; + + rc = ngx_http_output_filter(r, h); + + ngx_log_debug(r->connection->log, "0 output_filter: %d" _ rc); + } + } + +#endif + return rc; } diff --git a/src/http/ngx_http_output_filter.c b/src/http/ngx_http_output_filter.c --- a/src/http/ngx_http_output_filter.c +++ b/src/http/ngx_http_output_filter.c @@ -57,7 +57,6 @@ ngx_module_t ngx_http_output_filter_mod }; -#if 1 #define next_filter ngx_http_output_filter_module_ctx.next_output_body_filter @@ -67,6 +66,7 @@ ngx_module_t ngx_http_output_filter_mod || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP) \ && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP)))) + int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) { int rc; @@ -84,8 +84,9 @@ int ngx_http_output_filter(ngx_http_requ sizeof(ngx_http_output_filter_ctx_t)); } - /* the incoming chain ctx->in is empty */ - if (ctx->in == NULL) { + /* the short path for the case when the chain ctx->incoming is empty + and there is no hunk or the hunk does not require the copy */ + if (ctx->incoming == NULL) { if (hunk == NULL) { return next_filter(r, NULL); @@ -98,91 +99,53 @@ int ngx_http_output_filter(ngx_http_requ return next_filter(r, &ctx->out); } + } - /* we need to copy the incoming hunk to our hunk */ + /* add the incoming hunk to the chain ctx->incoming */ + if (hunk) { - /* allocate ctx->hunk if it's needed */ - if (ctx->hunk == NULL) { + /* the output of the only hunk is common case so we have + special chain entry ctx->in for it */ + if (ctx->incoming == NULL) { + ctx->in.hunk = hunk; + ctx->in.next = NULL; + ctx->incoming = &ctx->in; - conf = (ngx_http_output_filter_conf_t *) - ngx_http_get_module_loc_conf(r->main ? r->main : r, - ngx_http_output_filter_module); + } else { + for (ce = ctx->incoming; ce->next; ce = ce->next) { + /* void */ ; + } + + ngx_add_hunk_to_chain(ce->next, hunk, r->pool, NGX_ERROR); + } + } - if (hunk->type & NGX_HUNK_LAST) { - size = hunk->last.mem - hunk->pos.mem; - if (size > conf->hunk_size) { - size = conf->hunk_size; - } + /* allocate our hunk if it's needed */ + if (ctx->hunk == NULL) { - } else { + conf = (ngx_http_output_filter_conf_t *) + ngx_http_get_module_loc_conf(r->main ? r->main : r, + ngx_http_output_filter_module); + + if (hunk->type & NGX_HUNK_LAST) { + size = hunk->last.mem - hunk->pos.mem; + if (size > conf->hunk_size) { size = conf->hunk_size; } - ngx_test_null(ctx->hunk, - ngx_create_temp_hunk(r->pool, size, 50, 50), - NGX_ERROR); - - ctx->hunk->type |= NGX_HUNK_RECYCLED; + } else { + size = conf->hunk_size; } - /* copy the incoming hunk or its part to our hunk - and pass it to the next filter */ - - do { - rc = ngx_http_output_filter_copy_hunk(ctx->hunk, hunk); - - if (rc == NGX_ERROR) { - return rc; - } - -#if (NGX_FILE_AIO_READ) - - if (rc == NGX_AGAIN) { - /* add the incoming hunk to the incoming chain */ - ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, NGX_ERROR); - return rc; - } - -#endif - ctx->out.hunk = ctx->hunk; - ctx->out.next = NULL; - - rc = next_filter(r, &ctx->out); - - if (rc == NGX_ERROR) { - return rc; - } + ngx_test_null(ctx->hunk, + ngx_create_temp_hunk(r->pool, size, 50, 50), + NGX_ERROR); - if (rc == NGX_AGAIN) { - /* add the incoming hunk to the incoming chain */ - ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, NGX_ERROR); - return rc; - } - - /* NGX_OK */ - - /* set our hunk free */ - ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; - - /* repeat until we will have copied the whole incoming hunk */ - } while (hunk->pos.mem < hunk->last.mem); + ctx->hunk->type |= NGX_HUNK_RECYCLED; - return NGX_OK; - } - - /* the incoming chain ctx->in is not empty */ - - /* add the incoming hunk to the incoming chain */ - if (hunk) { - for (ce = ctx->in; ce->next; ce = ce->next) { - /* void */ ; - } - - ngx_add_hunk_to_chain(ce->next, hunk, r->pool, NGX_ERROR); - } /* our hunk is still busy */ - if (ctx->hunk->pos.mem < ctx->hunk->last.mem) { + } else if (ctx->hunk->pos.mem < ctx->hunk->last.mem) { rc = next_filter(r, NULL); if (rc == NGX_ERROR || rc == NGX_AGAIN) { @@ -190,6 +153,8 @@ int ngx_http_output_filter(ngx_http_requ } /* NGX_OK */ + + /* set our hunk free */ ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; } @@ -197,10 +162,10 @@ int ngx_http_output_filter(ngx_http_requ pe = NULL; #endif - /* process the incoming chain ctx->in */ + /* process the chain ctx->incoming */ do { /* find the hunks that do not need to be copied ... */ - for (ce = ctx->in; ce; ce = ce->next) { + for (ce = ctx->incoming; ce; ce = ce->next) { if (need_to_copy(r, ce->hunk)) { break; } @@ -208,11 +173,11 @@ int ngx_http_output_filter(ngx_http_requ } /* ... and pass them to the next filter */ - if (ctx->in != ce) { + if (ctx->incoming != ce) { - ctx->out.hunk = ctx->in->hunk; - ctx->out.next = ctx->in->next; - ctx->in = ce; + ctx->out.hunk = ctx->incoming->hunk; + ctx->out.next = ctx->incoming->next; + ctx->incoming = ce; pe->next = NULL; rc = next_filter(r, &ctx->out); @@ -222,16 +187,16 @@ int ngx_http_output_filter(ngx_http_requ } /* NGX_OK */ - if (ctx->in == NULL) { + if (ctx->incoming == NULL) { return rc; } } - - /* copy the first hunk or its part from the incoming chain ctx->in + /* copy the first hunk or its part from the chain ctx->incoming to our hunk and pass it to the next filter */ do { - rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk); + rc = ngx_http_output_filter_copy_hunk(ctx->hunk, + ctx->incoming->hunk); if (rc == NGX_ERROR) { return rc; @@ -259,243 +224,19 @@ int ngx_http_output_filter(ngx_http_requ ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; /* repeat until we will have copied the whole first hunk from - the incoming chain ctx->in */ - } while (ctx->in->hunk->pos.mem < ctx->in->hunk->last.mem); + the chain ctx->incoming */ + } while (ctx->incoming->hunk->pos.mem < ctx->incoming->hunk->last.mem); /* delete the completed hunk from the incoming chain */ - ctx->in = ctx->in->next; + ctx->incoming = ctx->incoming->next; - /* repeat until we will have processed the whole incoming chain ctx->in */ - } while (ctx->in); + /* repeat until we will have processed the whole chain ctx->incoming */ + } while (ctx->incoming); return NGX_OK; } -#else - - -int ngx_http_output_filter(ngx_http_request_t *r, ngx_hunk_t *hunk) -{ - int rc, once; - u_int flags; - size_t size; - ngx_chain_t *ce; - ngx_http_output_filter_ctx_t *ctx; - ngx_http_output_filter_conf_t *conf; - - ctx = (ngx_http_output_filter_ctx_t *) - ngx_http_get_module_ctx(r->main ? r->main : r, - ngx_http_output_filter_module); - - if (ctx == NULL) { - ngx_http_create_ctx(r, ctx, ngx_http_output_filter_module, - sizeof(ngx_http_output_filter_ctx_t)); - } - - if (hunk && (hunk->type & NGX_HUNK_LAST)) { - ctx->last = 1; - } - -#if (NGX_SUPPRESS_WARN) - rc = NGX_ALERT; -#endif - - for (once = 1; once || ctx->in; once = 0) { - - /* input chain is not empty */ - if (ctx->in) { - - /* add hunk to input chain */ - if (once && hunk) { - for (ce = ctx->in; ce->next; ce = ce->next) { - /* void */ ; - } - - ngx_add_hunk_to_chain(ce->next, hunk, r->pool, NGX_ERROR); - } - - /* our hunk is still busy */ - if (ctx->hunk->pos.mem < ctx->hunk->last.mem) { - rc = ngx_http_output_filter_module_ctx. - next_output_body_filter(r, NULL); - - /* our hunk is free */ - } else { - ctx->out.hunk = ctx->hunk; - - /* XXX: should we check hunk type before copy it ? */ - rc = ngx_http_output_filter_copy_hunk(ctx->hunk, ctx->in->hunk); -#if (NGX_FILE_AIO_READ) - if (rc == NGX_AGAIN) { - return rc; - } -#endif - if (rc == NGX_ERROR) { - return rc; - } - - /* NGX_OK */ - - /* whole hunk is copied so we send to next filter chain part - up to next hunk that need to be copied */ - if (ctx->in->hunk->pos.mem == ctx->in->hunk->last.mem) { - ctx->out.next = ctx->in->next; - - for (ce = ctx->in->next; ce; ce = ce->next) { - if (ce->hunk->type & NGX_HUNK_FILE) { - break; - } - - if ((ce->hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP)) - && (r->filter & NGX_HTTP_FILTER_NEED_TEMP)) - { - break; - } - } - - ctx->out.next = ce; - - } else { - ctx->out.next = NULL; - } - - rc = ngx_http_output_filter_module_ctx. - next_output_body_filter(r, &ctx->out); - } - - /* delete completed hunks from input chain */ - for (ce = ctx->in; ce; ce = ce->next) { - if (ce->hunk->pos.file == ce->hunk->last.file) { - ctx->in = ce->next; - } - } - - if (rc == NGX_OK && ctx->hunk) { - ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; - } else { - return rc; - } - - /* input chain is empty */ - } else { - - if (hunk == NULL) { - rc = ngx_http_output_filter_module_ctx. - next_output_body_filter(r, NULL); - - } else { - - /* we need to copy hunk to our hunk */ - if (((r->filter & NGX_HTTP_FILTER_NEED_IN_MEMORY) - && (hunk->type & NGX_HUNK_FILE)) - || ((r->filter & NGX_HTTP_FILTER_NEED_TEMP) - && (hunk->type & (NGX_HUNK_MEMORY|NGX_HUNK_MMAP))) - ) { - - /* out hunk is still busy */ - if (ctx->hunk && ctx->hunk->pos.mem < ctx->hunk->last.mem) { - ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, - NGX_ERROR); - - rc = ngx_http_output_filter_module_ctx. - next_output_body_filter(r, NULL); - - } else { - if (ctx->hunk == NULL) { - - conf = (ngx_http_output_filter_conf_t *) - ngx_http_get_module_loc_conf( - r->main ? r->main : r, - ngx_http_output_filter_module); - - if (hunk->type & NGX_HUNK_LAST) { - size = hunk->last.mem - hunk->pos.mem; - if (size > conf->hunk_size) { - size = conf->hunk_size; - } - - } else { - size = conf->hunk_size; - } - - ngx_test_null(ctx->hunk, - ngx_create_temp_hunk(r->pool, size, - 50, 50), - NGX_ERROR); - ctx->hunk->type |= NGX_HUNK_RECYCLED; - - rc = ngx_http_output_filter_copy_hunk(ctx->hunk, - hunk); -#if (NGX_FILE_AIO_READ) - if (rc == NGX_AGAIN) { - /* add hunk to input chain */ - ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, - NGX_ERROR); - - return rc; - } -#endif - if (rc == NGX_ERROR) { - return rc; - } - - if (hunk->pos.mem < hunk->last.mem) { - ngx_add_hunk_to_chain(ctx->in, hunk, r->pool, - NGX_ERROR); - } - - ctx->out.hunk = ctx->hunk; - ctx->out.next = NULL; - - rc = ngx_http_output_filter_module_ctx. - next_output_body_filter(r, &ctx->out); - } - } - - } else { - ctx->out.hunk = hunk; - ctx->out.next = NULL; - - rc = ngx_http_output_filter_module_ctx. - next_output_body_filter(r, &ctx->out); - } - } - } - - /* set free our hunk if operation has completed */ - if (rc == NGX_OK && ctx->hunk) { - ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; - } - } - -#if (NGX_SUPPRESS_WARN) - if (rc == NGX_ALERT) { - ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, - "ngx_http_output_filter: rc == NGX_ALERT"); - return NGX_ERROR; - } -#endif - - if (rc == NGX_OK && ctx->last) { - return NGX_OK; - } - - if (rc == NGX_OK) { - if (ctx->hunk) { /* XXX: double upper code ? */ - ctx->hunk->pos.mem = ctx->hunk->last.mem = ctx->hunk->start; - } -#if (NGX_LEVEL_EVENT) - ngx_del_event(r->connection->write, NGX_WRITE_EVENT); -#endif - } - - return rc; -} - -#endif - - static int ngx_http_output_filter_copy_hunk(ngx_hunk_t *dst, ngx_hunk_t *src) { ssize_t n, size; @@ -510,16 +251,23 @@ static int ngx_http_output_filter_copy_h if (n == NGX_ERROR) { return n; + } #if (NGX_FILE_AIO_READ) - } else if (n == NGX_AGAIN) { + + if (n == NGX_AGAIN) { return n; + } + #endif - } else { - ngx_assert((n == size), /* void */ ; , src->file->log, - ngx_read_file_n " reads only %d of %d" _ - n _ size); + if (n != size) { + ngx_log_error(NGX_LOG_ALERT, src->file->log, 0, + ngx_read_file_n " reads only %d of %d from file", + n, size); + if (n == 0) { + return NGX_ERROR; + } } src->pos.mem += n; diff --git a/src/http/ngx_http_output_filter.h b/src/http/ngx_http_output_filter.h --- a/src/http/ngx_http_output_filter.h +++ b/src/http/ngx_http_output_filter.h @@ -18,9 +18,10 @@ typedef struct { typedef struct { - ngx_hunk_t *hunk; - ngx_chain_t *in; - ngx_chain_t out; + ngx_hunk_t *hunk; /* the temporary hunk to copy */ + ngx_chain_t *incoming; + ngx_chain_t in; /* one chain entry for input */ + ngx_chain_t out; /* one chain entry for output */ } ngx_http_output_filter_ctx_t; diff --git a/src/http/ngx_http_write_filter.c b/src/http/ngx_http_write_filter.c --- a/src/http/ngx_http_write_filter.c +++ b/src/http/ngx_http_write_filter.c @@ -57,9 +57,9 @@ ngx_module_t ngx_http_write_filter_modu int ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in) { - int last; - off_t size, flush; - ngx_chain_t *ch, **prev, *chain; + int last; + off_t size, flush; + ngx_chain_t *ce, **le, *chain; ngx_http_write_filter_ctx_t *ctx; ngx_http_write_filter_conf_t *conf; @@ -74,51 +74,51 @@ int ngx_http_write_filter(ngx_http_reque size = flush = 0; last = 0; - prev = &ctx->out; + le = &ctx->out; - /* find size, flush point and last link of saved chain */ - for (ch = ctx->out; ch; ch = ch->next) { - prev = &ch->next; - size += ch->hunk->last.file - ch->hunk->pos.file; + /* find the size, the flush point and the last entry of saved chain */ + for (ce = ctx->out; ce; ce = ce->next) { + le = &ce->next; + size += ce->hunk->last.file - ce->hunk->pos.file; -#if (NGX_DEBUG_WRITE_FILTER) +#if (NGX_DEBUG_WRITE_FILTER0) ngx_log_debug(r->connection->log, "write filter: old chunk: %x " QX_FMT " " QD_FMT _ - ch->hunk->type _ ch->hunk->pos.file _ - ch->hunk->last.file - ch->hunk->pos.file); + ce->hunk->type _ ce->hunk->pos.file _ + ce->hunk->last.file - ce->hunk->pos.file); #endif - if (ch->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) { + if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) { flush = size; } - if (ch->hunk->type & NGX_HUNK_LAST) { + if (ce->hunk->type & NGX_HUNK_LAST) { last = 1; } } - /* add new chain to existent one */ + /* add the new chain to the existent one */ for (/* void */; in; in = in->next) { - ngx_test_null(ch, ngx_palloc(r->pool, sizeof(ngx_chain_t)), NGX_ERROR); + ngx_test_null(ce, ngx_palloc(r->pool, sizeof(ngx_chain_t)), NGX_ERROR); - ch->hunk = in->hunk; - ch->next = NULL; - *prev = ch; - prev = &ch->next; - size += ch->hunk->last.file - ch->hunk->pos.file; + ce->hunk = in->hunk; + ce->next = NULL; + *le = ce; + le = &ce->next; + size += ce->hunk->last.file - ce->hunk->pos.file; -#if (NGX_DEBUG_WRITE_FILTER) - ngx_log_debug(r->connection->log, "write filter: new chunk: %x " +#if (NGX_DEBUG_WRITE_FILTER0) + ngx_log_debug(r->connection->log, "write filter: new hunk: %x " QX_FMT " " QD_FMT _ - ch->hunk->type _ ch->hunk->pos.file _ - ch->hunk->last.file - ch->hunk->pos.file); + ce->hunk->type _ ce->hunk->pos.file _ + ce->hunk->last.file - ce->hunk->pos.file); #endif - if (ch->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) { + if (ce->hunk->type & (NGX_HUNK_FLUSH|NGX_HUNK_RECYCLED)) { flush = size; } - if (ch->hunk->type & NGX_HUNK_LAST) { + if (ce->hunk->type & NGX_HUNK_LAST) { last = 1; } } @@ -127,25 +127,35 @@ int ngx_http_write_filter(ngx_http_reque ngx_http_get_module_loc_conf(r->main ? r->main : r, ngx_http_write_filter_module); -#if (NGX_DEBUG_WRITE_FILTER) +#if (NGX_DEBUG_WRITE_FILTER0) ngx_log_debug(r->connection->log, "write filter: last:%d flush:%d" _ last _ flush); #endif + /* avoid the output if there is no last hunk, no flush point and + size of the hunks is smaller then 'write_buffer' */ if (!last && flush == 0 && size < conf->buffer_output) { return NGX_OK; } chain = ngx_event_write(r->connection, ctx->out, flush); - if (chain == (ngx_chain_t *) -1) { + +#if (NGX_DEBUG_WRITE_FILTER) + ngx_log_debug(r->connection->log, "write filter %x" _ chain); +#endif + + if (chain == NGX_CHAIN_ERROR) { return NGX_ERROR; } ctx->out = chain; - ngx_log_debug(r->connection->log, "write filter %x" _ chain); + if (chain == NULL) { + return NGX_OK; - return (chain ? NGX_AGAIN : NGX_OK); + } else { + return NGX_AGAIN; + } }