# HG changeset patch # User Igor Sysoev # Date 1070008840 0 # Node ID a65b630b3a662ece13630d9a4a44baf6fe025f0d # Parent 34995c5ec6c44ca80294d5d79fd1a0c8b87edce5 nginx-0.0.1-2003-11-28-11:40:40 import diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -29,6 +29,11 @@ #endif +/* STUB: ngx_mutex.h */ +#define ngx_mutex_lock(m) +#define ngx_mutex_unlock(m) + + /* STUB: autoconf */ typedef int ngx_int_t; typedef u_int ngx_uint_t; diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c --- a/src/http/modules/ngx_http_index_handler.c +++ b/src/http/modules/ngx_http_index_handler.c @@ -5,8 +5,9 @@ typedef struct { - ngx_array_t indices; - size_t max_index_len; + ngx_array_t indices; + size_t max_index_len; + ngx_http_cache_hash_t *cache; } ngx_http_index_conf_t; @@ -19,10 +20,10 @@ typedef struct { #define NGX_HTTP_DEFAULT_INDEX "index.html" -static int ngx_http_index_test_dir(ngx_http_request_t *r, - ngx_http_index_ctx_t *ctx); -static int ngx_http_index_error(ngx_http_request_t *r, - ngx_http_index_ctx_t *ctx, ngx_err_t err); +static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r, + ngx_http_index_ctx_t *ctx); +static ngx_int_t ngx_http_index_error(ngx_http_request_t *r, + ngx_http_index_ctx_t *ctx, ngx_err_t err); static int ngx_http_index_init(ngx_cycle_t *cycle); static void *ngx_http_index_create_conf(ngx_conf_t *cf); @@ -32,16 +33,23 @@ static char *ngx_http_index_set_index(ng void *conf); -static ngx_command_t ngx_http_index_commands[] = { +static ngx_command_t ngx_http_index_commands[] = { + + { ngx_string("index"), + NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, + ngx_http_index_set_index, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, - {ngx_string("index"), - NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, - ngx_http_index_set_index, - NGX_HTTP_LOC_CONF_OFFSET, - 0, - NULL}, + { ngx_string("index_cache"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234, + ngx_http_set_cache_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_index_conf_t, cache), + NULL }, - ngx_null_command + ngx_null_command }; @@ -81,19 +89,48 @@ ngx_module_t ngx_http_index_module = { int ngx_http_index_handler(ngx_http_request_t *r) { - int rc; char *name, *file; + uint32_t crc; + ngx_int_t rc; ngx_str_t redirect, *index; ngx_err_t err; ngx_fd_t fd; + ngx_http_cache_t *cache; ngx_http_index_ctx_t *ctx; - ngx_http_index_conf_t *icf; + ngx_http_index_conf_t *ilcf; ngx_http_core_loc_conf_t *clcf; if (r->uri.data[r->uri.len - 1] != '/') { return NGX_DECLINED; } + ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module); + + if (ilcf->cache) { + cache = ngx_http_cache_get(ilcf->cache, &r->uri, &crc); + +ngx_log_debug(r->connection->log, "index cache get: %x" _ cache); + + if (cache && ilcf->cache->update >= ngx_cached_time - cache->updated) { + + cache->accessed = ngx_cached_time; + + redirect.len = cache->data.value.len; + if (!(redirect.data = ngx_palloc(r->pool, redirect.len + 1))) { + ngx_http_cache_unlock(ilcf->cache, cache); + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + ngx_memcpy(redirect.data, cache->data.value.data, redirect.len + 1); + ngx_http_cache_unlock(ilcf->cache, cache); + + return ngx_http_internal_redirect(r, &redirect, NULL); + } + + } else { + cache = NULL; + } + ctx = ngx_http_get_module_ctx(r, ngx_http_index_module); if (ctx == NULL) { ngx_http_create_ctx(r, ctx, ngx_http_index_module, @@ -101,12 +138,11 @@ int ngx_http_index_handler(ngx_http_requ NGX_HTTP_INTERNAL_SERVER_ERROR); } - icf = ngx_http_get_module_loc_conf(r, ngx_http_index_module); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (r->path.data == NULL) { r->path_allocated = clcf->doc_root.len + r->uri.len - + icf->max_index_len; + + ilcf->max_index_len; ngx_test_null(r->path.data, ngx_palloc(r->pool, r->path_allocated), NGX_HTTP_INTERNAL_SERVER_ERROR); @@ -121,8 +157,8 @@ int ngx_http_index_handler(ngx_http_requ file = redirect.data + r->uri.len; } - index = icf->indices.elts; - for (/* void */; ctx->index < icf->indices.nelts; ctx->index++) { + index = ilcf->indices.elts; + for (/* void */; ctx->index < ilcf->indices.nelts; ctx->index++) { if (index[ctx->index].data[0] == '/') { name = index[ctx->index].data; @@ -185,6 +221,58 @@ ngx_log_error(NGX_LOG_DEBUG, r->connecti + index[ctx->index].len; } + if (ilcf->cache) { + + if (cache) { + if (redirect.len == cache->data.value.len + && ngx_memcmp(cache->data.value.data, redirect.data, + redirect.len) == 0) + { + cache->accessed = ngx_cached_time; + cache->updated = ngx_cached_time; + ngx_http_cache_unlock(ilcf->cache, cache); + + return ngx_http_internal_redirect(r, &redirect, NULL); + + } else { + if (redirect.len > cache->data.value.len) { + ngx_free(cache->data.value.data); + cache->data.value.data = NULL; + } + } + } + + if (cache == NULL) { + cache = ngx_http_cache_alloc(ilcf->cache, &r->uri, crc, + r->connection->log); + } + +ngx_log_debug(r->connection->log, "index cache alloc: %x" _ cache); + + if (cache) { + cache->fd = NGX_INVALID_FILE; + cache->accessed = ngx_cached_time; + cache->last_modified = 0; + cache->updated = ngx_cached_time; + + cache->data.value.len = redirect.len; + if (cache->data.value.data == NULL) { + cache->data.value.data = ngx_alloc(redirect.len + 1, + r->connection->log); + if (cache->data.value.data == NULL) { + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + } + + ngx_memcpy(cache->data.value.data, redirect.data, + redirect.len + 1); + } + } + + if (cache) { + ngx_http_cache_unlock(ilcf->cache, cache); + } + return ngx_http_internal_redirect(r, &redirect, NULL); } @@ -192,8 +280,8 @@ ngx_log_error(NGX_LOG_DEBUG, r->connecti } -static int ngx_http_index_test_dir(ngx_http_request_t *r, - ngx_http_index_ctx_t *ctx) +static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r, + ngx_http_index_ctx_t *ctx) { ngx_err_t err; @@ -228,8 +316,8 @@ ngx_log_debug(r->connection->log, "IS_DI } -static int ngx_http_index_error(ngx_http_request_t *r, - ngx_http_index_ctx_t *ctx, ngx_err_t err) +static ngx_int_t ngx_http_index_error(ngx_http_request_t *r, + ngx_http_index_ctx_t *ctx, ngx_err_t err) { if (err == NGX_EACCES) { ngx_log_error(NGX_LOG_ERR, r->connection->log, err, @@ -273,6 +361,8 @@ static void *ngx_http_index_create_conf( NGX_CONF_ERROR); conf->max_index_len = 0; + conf->cache = NULL; + return conf; } @@ -317,6 +407,10 @@ static char *ngx_http_index_merge_conf(n conf->max_index_len = prev->max_index_len; } + if (conf->cache == NULL) { + conf->cache = prev->cache; + } + return NGX_CONF_OK; } @@ -326,14 +420,14 @@ static char *ngx_http_index_merge_conf(n static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { - ngx_http_index_conf_t *icf = conf; + ngx_http_index_conf_t *ilcf = conf; int i; ngx_str_t *index, *value; value = cf->args->elts; - if (value[1].data[0] == '/' && icf->indices.nelts == 0) { + if (value[1].data[0] == '/' && ilcf->indices.nelts == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "first index \"%s\" in \"%s\" directive " "must not be absolute", @@ -349,12 +443,12 @@ static char *ngx_http_index_set_index(ng return NGX_CONF_ERROR; } - ngx_test_null(index, ngx_push_array(&icf->indices), NGX_CONF_ERROR); + ngx_test_null(index, ngx_push_array(&ilcf->indices), NGX_CONF_ERROR); index->len = value[i].len; index->data = value[i].data; - if (icf->max_index_len < index->len + 1) { - icf->max_index_len = index->len + 1; + if (ilcf->max_index_len < index->len + 1) { + ilcf->max_index_len = index->len + 1; } } 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 @@ -97,7 +97,7 @@ ngx_log_debug(r->connection->log, "cache if (cache && ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) - || ccf->open_files->check_time >= ngx_time() - cache->updated)) + || ccf->open_files->update >= ngx_cached_time - cache->updated)) { cache->refs++; r->file.fd = cache->fd; diff --git a/src/http/ngx_http_cache.c b/src/http/ngx_http_cache.c --- a/src/http/ngx_http_cache.c +++ b/src/http/ngx_http_cache.c @@ -88,8 +88,9 @@ ngx_http_cache_t *ngx_http_cache_get(ngx *crc = ngx_crc(key->data, key->len); - c = cache->elts - + *crc % cache->hash * cache->nelts * sizeof(ngx_http_cache_t); + c = cache->elts + *crc % cache->hash * cache->nelts; + + ngx_mutex_lock(&cache->mutex); for (i = 0; i < cache->nelts; i++) { if (c[i].crc == *crc @@ -97,10 +98,13 @@ ngx_http_cache_t *ngx_http_cache_get(ngx && ngx_rstrncmp(c[i].key.data, key->data, key->len) == 0) { c[i].refs++; + ngx_mutex_unlock(&cache->mutex); return &c[i]; } } + ngx_mutex_unlock(&cache->mutex); + return NULL; } @@ -113,24 +117,28 @@ ngx_http_cache_t *ngx_http_cache_alloc(n ngx_uint_t i; ngx_http_cache_t *c, *found; - old = ngx_time() + 1; + old = ngx_cached_time + 1; found = NULL; - c = cache->elts - + crc % cache->hash * cache->nelts * sizeof(ngx_http_cache_t); + c = cache->elts + crc % cache->hash * cache->nelts; + + ngx_mutex_lock(&cache->mutex); for (i = 0; i < cache->nelts; i++) { - if (c[i].key.data == NULL) { + if (c[i].refs > 0) { + /* a busy entry */ + continue; + } + if (c[i].key.data == NULL) { /* a free entry is found */ - found = &c[i]; break; } - /* looking for the oldest cache entry that is not been using */ + /* looking for the oldest cache entry */ - if (c[i].refs == 0 && old > c[i].accessed) { + if (old > c[i].accessed) { old = c[i].accessed; found = &c[i]; @@ -148,6 +156,7 @@ ngx_http_cache_t *ngx_http_cache_alloc(n if (found->key.data == NULL) { found->key.data = ngx_alloc(key->len, log); if (found->key.data == NULL) { + ngx_mutex_unlock(&cache->mutex); return NULL; } } @@ -157,9 +166,12 @@ ngx_http_cache_t *ngx_http_cache_alloc(n found->crc = crc; found->key.len = key->len; found->refs = 1; + found->count = 0; found->deleted = 0; } + ngx_mutex_unlock(&cache->mutex); + return found; } @@ -380,6 +392,11 @@ static char *ngx_http_core_merge_loc_con ngx_http_cache_conf_t *conf = child; if (conf->open_files == NULL) { + conf->open_files = prev->open_files; + } + +#if 0 + if (conf->open_files == NULL) { if (prev->open_files) { conf->open_files = prev->open_files; @@ -402,6 +419,129 @@ static char *ngx_http_core_merge_loc_con } } } +#endif return NGX_CONF_OK; } + + +char *ngx_http_set_cache_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + char *p = conf; + + ngx_int_t i, dup, invalid; + ngx_str_t *value, line; + ngx_http_cache_hash_t *ch, **chp; + + chp = (ngx_http_cache_hash_t **) (p + cmd->offset); + if (*chp) { + return "is duplicate"; + } + + if (!(ch = ngx_pcalloc(cf->pool, sizeof(ngx_http_cache_hash_t)))) { + return NGX_CONF_ERROR; + } + *chp = ch; + + dup = 0; + invalid = 0; + + value = cf->args->elts; + + for (i = 1; i < cf->args->nelts; i++) { + + if (value[i].data[1] != '=') { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid value \"%s\"", value[i].data); + return NGX_CONF_ERROR; + } + + switch (value[i].data[0]) { + + case 'h': + if (ch->hash) { + dup = 1; + break; + } + + ch->hash = ngx_atoi(value[i].data + 2, value[i].len - 2); + if (ch->hash == (size_t) NGX_ERROR || ch->hash == 0) { + invalid = 1; + break; + } + + continue; + + case 'n': + if (ch->nelts) { + dup = 1; + break; + } + + ch->nelts = ngx_atoi(value[i].data + 2, value[i].len - 2); + if (ch->nelts == (size_t) NGX_ERROR || ch->nelts == 0) { + invalid = 1; + break; + } + + continue; + + case 'l': + if (ch->life) { + dup = 1; + break; + } + + line.len = value[i].len - 2; + line.data = value[i].data + 2; + + ch->life = ngx_parse_time(&line, 1); + if (ch->life == NGX_ERROR || ch->life == 0) { + invalid = 1; + break; + } + + continue; + + case 'u': + if (ch->update) { + dup = 1; + break; + } + + line.len = value[i].len - 2; + line.data = value[i].data + 2; + + ch->update = ngx_parse_time(&line, 1); + if (ch->update == NGX_ERROR || ch->update == 0) { + invalid = 1; + break; + } + + continue; + + default: + invalid = 1; + } + + if (dup) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "duplicate value \"%s\"", value[i].data); + return NGX_CONF_ERROR; + } + + if (invalid) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid value \"%s\"", value[i].data); + return NGX_CONF_ERROR; + } + } + + ch->elts = ngx_pcalloc(cf->pool, + ch->hash * ch->nelts * sizeof(ngx_http_cache_t)); + if (ch->elts == NULL) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -44,8 +44,8 @@ typedef struct { ngx_http_cache_t *elts; size_t hash; size_t nelts; - time_t life_time; - time_t check_time; + time_t life; + time_t update; ngx_pool_t *pool; } ngx_http_cache_hash_t; @@ -74,6 +74,13 @@ typedef struct { } ngx_http_cache_conf_t; +#define ngx_http_cache_unlock(ch, ce) \ + ngx_mutex_lock(&ch->mutex); \ + ce->refs--; \ + ngx_mutex_unlock(&ch->mutex); + + + #define NGX_HTTP_CACHE_STALE 1 #define NGX_HTTP_CACHE_AGED 2 #define NGX_HTTP_CACHE_THE_SAME 3 @@ -93,6 +100,9 @@ ngx_http_cache_t *ngx_http_cache_alloc(n int ngx_garbage_collector_http_cache_handler(ngx_gc_t *gc, ngx_str_t *name, ngx_dir_t *dir); +char *ngx_http_set_cache_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); + + extern ngx_module_t ngx_http_cache_module; diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c --- a/src/os/unix/ngx_linux_sendfile_chain.c +++ b/src/os/unix/ngx_linux_sendfile_chain.c @@ -4,6 +4,17 @@ #include +/* + * On Linux up to 2.4.21 sendfile() (syscall #187) works with 32-bit + * offsets only and the including breaks building + * if off_t is 64 bit wide. So we use own sendfile() definition where + * offset paramter is int32_t. It allows to use sendfile() with + * the file parts below 2G. + * + * Linux 2.4.21 has a new sendfile64() syscall #239. + */ + + ngx_chain_t *ngx_linux_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in) { int rc;