diff options
author | Igor Sysoev <igor@sysoev.ru> | 2005-12-16 18:07:08 +0300 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2005-12-16 18:07:08 +0300 |
commit | 2402502c2f35b831ee89369a532b1ff4e4e19947 (patch) | |
tree | 37fb834956f497f8b2d2862c6c3514e1a25bfb37 /src/core | |
parent | 74297c285ef173784cac505fd406267ac7c8d3c7 (diff) |
nginx-0.3.16-RELEASE importrelease-0.3.16
*) Feature: the ngx_http_map_module.
*) Feature: the "types_hash_max_size" and "types_hash_bucket_size"
directives.
*) Feature: the "ssi_value_length" directive.
*) Feature: the "worker_rlimit_core" directive.
*) Workaround: the connection number in logs was always 1 if nginx was
built by the icc 8.1 or 9.0 compilers with optimization for
Pentium 4.
*) Bugfix: the "config timefmt" SSI command set incorrect time format.
*) Bugfix: nginx did not close connection to IMAP/POP3 backend for the
SSL connections; the bug had appeared in 0.3.13.
Thanks to Rob Mueller.
*) Bugfix: segmentation fault may occurred in at SSL shutdown; the bug
had appeared in 0.3.13.
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/nginx.c | 8 | ||||
-rw-r--r-- | src/core/nginx.h | 2 | ||||
-rw-r--r-- | src/core/ngx_config.h | 4 | ||||
-rw-r--r-- | src/core/ngx_cycle.h | 1 | ||||
-rw-r--r-- | src/core/ngx_hash.c | 482 | ||||
-rw-r--r-- | src/core/ngx_hash.h | 80 | ||||
-rw-r--r-- | src/core/ngx_log.c | 2 | ||||
-rw-r--r-- | src/core/ngx_palloc.c | 12 | ||||
-rw-r--r-- | src/core/ngx_palloc.h | 2 | ||||
-rw-r--r-- | src/core/ngx_string.c | 15 |
10 files changed, 579 insertions, 29 deletions
diff --git a/src/core/nginx.c b/src/core/nginx.c index cd1551421..d30e12744 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -100,6 +100,13 @@ static ngx_command_t ngx_core_commands[] = { offsetof(ngx_core_conf_t, rlimit_nofile), NULL }, + { ngx_string("worker_rlimit_core"), + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + 0, + offsetof(ngx_core_conf_t, rlimit_core), + NULL }, + { ngx_string("worker_rlimit_sigpending"), NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -558,6 +565,7 @@ ngx_core_module_create_conf(ngx_cycle_t *cycle) ccf->debug_points = NGX_CONF_UNSET; ccf->rlimit_nofile = NGX_CONF_UNSET; + ccf->rlimit_core = NGX_CONF_UNSET; ccf->rlimit_sigpending = NGX_CONF_UNSET; ccf->user = (ngx_uid_t) NGX_CONF_UNSET_UINT; diff --git a/src/core/nginx.h b/src/core/nginx.h index 80fd49837..ce9e59654 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.3.15" +#define NGINX_VER "nginx/0.3.16" #define NGINX_VAR "NGINX" #define NGX_OLDPID_EXT ".oldbin" diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h index 96569b893..d924ec5e8 100644 --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -98,8 +98,8 @@ typedef long ngx_flag_t; #define NGX_ALIGNMENT sizeof(unsigned long) /* platform word */ #endif -#define ngx_align(p) (u_char *) (((uintptr_t) p + (NGX_ALIGNMENT - 1)) \ - & ~(NGX_ALIGNMENT - 1)) +#define ngx_align(d, a) (((d) + (a - 1)) & ~(a - 1)) +#define ngx_align_ptr(p, a) (u_char *) (((uintptr_t) (p) + (a - 1)) & ~(a - 1)) #define ngx_abort abort diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h index fc04e9ce6..cbf8c7ba1 100644 --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -60,6 +60,7 @@ typedef struct { ngx_int_t debug_points; ngx_int_t rlimit_nofile; + ngx_int_t rlimit_core; ngx_int_t rlimit_sigpending; int priority; diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c index 9d41df63b..4decd42e9 100644 --- a/src/core/ngx_hash.c +++ b/src/core/ngx_hash.c @@ -8,8 +8,488 @@ #include <ngx_core.h> +void * +ngx_hash_find(ngx_hash_t *hash, ngx_uint_t key, u_char *name, size_t len) +{ + ngx_uint_t i; + ngx_hash_elt_t *elt; + +#if 0 + ngx_str_t line; + + line.len = len; + line.data = name; + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "hf:\"%V\"", &line); +#endif + + elt = hash->buckets[key % hash->size]; + + if (elt == NULL) { + return NULL; + } + + while (elt->value) { + if (len != (size_t) elt->len) { + goto next; + } + + for (i = 0; i < len; i++) { + if (name[i] != elt->name[i]) { + goto next; + } + } + + return elt->value; + + next: + + elt = (ngx_hash_elt_t *) ngx_align_ptr(&elt->name[0] + elt->len, + sizeof(void *)); + continue; + } + + return NULL; +} + + +void * +ngx_hash_find_wildcard(ngx_hash_wildcard_t *hwc, u_char *name, size_t len) +{ + void *value; + ngx_uint_t i, n, key; + +#if 0 + ngx_str_t line; + + line.len = len; + line.data = name; + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "wc:\"%V\"", &line); +#endif + + n = len; + + while (n) { + if (name[n - 1] == '.') { + break; + } + + n--; + } + + if (n == 0) { + return NULL; + } + + key = 0; + + for (i = n; i < len; i++) { + key = ngx_hash(key, name[i]); + } + +#if 0 + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "key:\"%ui\"", key); +#endif + + value = ngx_hash_find(&hwc->hash, key, &name[n], len - n); + + if (value) { + if ((uintptr_t) value & 1) { + hwc = (ngx_hash_wildcard_t *) ((uintptr_t) value & (uintptr_t) ~1); + + value = ngx_hash_find_wildcard(hwc, name, n - 1); + + if (value) { + return value; + } + + return hwc->value; + } + + return value; + } + + return hwc->value; +} + + +#define NGX_HASH_ELT_SIZE(name) \ + sizeof(void *) + ngx_align((name)->key.len + 1, sizeof(void *)) + +ngx_int_t +ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts) +{ + u_char *elts; + size_t *test, len; + ngx_uint_t i, n, key, size, start, bucket_size; + ngx_hash_elt_t *elt, **buckets; + + for (n = 0; n < nelts; n++) { + if (names[n].key.len >= 255) { + ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, + "the \"%V\" value to hash is to long: %uz bytes, " + "the maximum length can be 255 bytes only", + &names[n].key, names[n].key.len); + return NGX_ERROR; + } + + if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *)) + { + ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, + "could not build the %s hash, you should " + "increase %s_bucket_size: %i", + hinit->name, hinit->name, hinit->bucket_size); + return NGX_ERROR; + } + } + + test = ngx_alloc(hinit->max_size * sizeof(ngx_uint_t), hinit->pool->log); + if (test == NULL) { + return NGX_ERROR; + } + + start = nelts / (ngx_cacheline_size / (2 * sizeof(void *)) - 1); + start = start ? start : 1; + + bucket_size = hinit->bucket_size - sizeof(void *); + + for (size = start; size < hinit->max_size; size++) { + + ngx_memzero(test, size * sizeof(ngx_uint_t)); + + for (n = 0; n < nelts; n++) { + if (names[n].key.data == NULL) { + continue; + } + + key = names[n].key_hash % size; + test[key] += NGX_HASH_ELT_SIZE(&names[n]); + +#if 0 + ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, + "%ui: %ui %ui \"%V\"", + size, key, test[key], &names[n].key); +#endif + + if (test[key] > bucket_size) { + goto next; + } + } + + goto found; + + next: + + continue; + } + + ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, + "could not build the %s hash, you should increase " + "either %s_max_size: %i or %s_bucket_size: %i", + hinit->name, hinit->name, hinit->max_size, + hinit->name, hinit->bucket_size); + + ngx_free(test); + + return NGX_ERROR; + +found: + + for (i = 0; i < size; i++) { + test[i] = sizeof(void *); + } + + for (n = 0; n < nelts; n++) { + if (names[n].key.data == NULL) { + continue; + } + + key = names[n].key_hash % size; + test[key] += NGX_HASH_ELT_SIZE(&names[n]); + } + + len = 0; + + for (i = 0; i < size; i++) { + if (test[i] == sizeof(void *)) { + continue; + } + + test[i] = ngx_align(test[i], ngx_cacheline_size); + + len += test[i]; + } + + if (hinit->hash == NULL) { + hinit->hash = ngx_pcalloc(hinit->pool, sizeof(ngx_hash_wildcard_t) + + size * sizeof(ngx_hash_elt_t *)); + if (hinit->hash == NULL) { + ngx_free(test); + return NGX_ERROR; + } + + buckets = (ngx_hash_elt_t **) + ((u_char *) hinit->hash + sizeof(ngx_hash_wildcard_t)); + + } else { + buckets = ngx_pcalloc(hinit->pool, size * sizeof(ngx_hash_elt_t *)); + if (buckets == NULL) { + ngx_free(test); + return NGX_ERROR; + } + } + + elts = ngx_palloc(hinit->pool, len + ngx_cacheline_size); + if (elts == NULL) { + ngx_free(test); + return NGX_ERROR; + } + + elts = ngx_align_ptr(elts, ngx_cacheline_size); + + for (i = 0; i < size; i++) { + if (test[i] == sizeof(void *)) { + continue; + } + + buckets[i] = (ngx_hash_elt_t *) elts; + elts += test[i]; + + } + + for (i = 0; i < size; i++) { + test[i] = 0; + } + + for (n = 0; n < nelts; n++) { + if (names[n].key.data == NULL) { + continue; + } + + key = names[n].key_hash % size; + elt = (ngx_hash_elt_t *) ((u_char *) buckets[key] + test[key]); + + elt->value = names[n].value; + elt->len = (u_char) names[n].key.len; + + for (i = 0; i < names[n].key.len; i++) { + elt->name[i] = ngx_tolower(names[n].key.data[i]); + } + + test[key] += NGX_HASH_ELT_SIZE(&names[n]); + } + + for (i = 0; i < size; i++) { + if (buckets[i] == NULL) { + continue; + } + + elt = (ngx_hash_elt_t *) ((u_char *) buckets[i] + test[i]); + + elt->value = NULL; + } + + ngx_free(test); + + hinit->hash->buckets = buckets; + hinit->hash->size = size; + +#if 0 + + for (i = 0; i < size; i++) { + ngx_str_t val; + ngx_uint_t key; + + elt = buckets[i]; + + if (elt == NULL) { + ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, + "%ui: NULL", i); + continue; + } + + while (elt->value) { + val.len = elt->len; + val.data = &elt->name[0]; + + key = hinit->key(val.data, val.len); + + ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, + "%ui: %p \"%V\" %ui", i, elt, &val, key); + + elt = (ngx_hash_elt_t *) ngx_align_ptr(&elt->name[0] + elt->len, + sizeof(void *)); + } + } + +#endif + + return NGX_OK; +} + + +ngx_int_t +ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, + ngx_uint_t nelts) +{ + size_t len; + ngx_uint_t i, n; + ngx_array_t curr_names, next_names; + ngx_hash_key_t *name, *next_name; + ngx_hash_init_t h; + ngx_hash_wildcard_t *wdc; + + if (ngx_array_init(&curr_names, hinit->temp_pool, nelts, + sizeof(ngx_hash_key_t)) + != NGX_OK) + { + return NGX_ERROR; + } + + if (ngx_array_init(&next_names, hinit->temp_pool, nelts, + sizeof(ngx_hash_key_t)) + != NGX_OK) + { + return NGX_ERROR; + } + + for (n = 0; n < nelts; n = i) { + +#if 0 + ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, + "wc0: \"%V\"", &names[n].key); +#endif + + for (len = 0; len < names[n].key.len; len++) { + if (names[n].key.data[len] == '.') { + len++; + break; + } + } + + name = ngx_array_push(&curr_names); + if (name == NULL) { + return NGX_ERROR; + } + + name->key.len = len - 1; + name->key.data = names[n].key.data; + name->key_hash = hinit->key(name->key.data, name->key.len); + name->value = names[n].value; + +#if 0 + ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, + "wc1: \"%V\"", &name->key); +#endif + + next_names.nelts = 0; + + if (names[n].key.len != len) { + next_name = ngx_array_push(&next_names); + if (next_name == NULL) { + return NGX_ERROR; + } + + next_name->key.len = names[n].key.len - len; + next_name->key.data = names[n].key.data + len; + next_name->key_hash= 0; + next_name->value = names[n].value; + +#if 0 + ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, + "wc2: \"%V\"", &next_name->key); +#endif + } + + for (i = n + 1; i < nelts; i++) { + if (ngx_strncmp(names[n].key.data, names[i].key.data, len) != 0) { + break; + } + + next_name = ngx_array_push(&next_names); + if (next_name == NULL) { + return NGX_ERROR; + } + + next_name->key.len = names[i].key.len - len; + next_name->key.data = names[i].key.data + len; + next_name->key_hash= 0; + next_name->value = names[i].value; + +#if 0 + ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, + "wc2: \"%V\"", &next_name->key); +#endif + } + + if (next_names.nelts) { + h = *hinit; + h.hash = NULL; + + if (ngx_hash_wildcard_init(&h, (ngx_hash_key_t *) next_names.elts, + next_names.nelts) + != NGX_OK) + { + return NGX_ERROR; + } + + wdc = (ngx_hash_wildcard_t *) h.hash; + + if (names[n].key.len == len) { + wdc->value = names[n].value; +#if 0 + ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, + "wdc: \"%V\"", wdc->value); +#endif + } + + name->value = (void *) ((uintptr_t) wdc | 1); + } + } + + if (ngx_hash_init(hinit, (ngx_hash_key_t *) curr_names.elts, + curr_names.nelts) + != NGX_OK) + { + return NGX_ERROR; + } + + return NGX_OK; +} + + +ngx_uint_t +ngx_hash_key(u_char *data, size_t len) +{ + ngx_uint_t i, key; + + key = 0; + + for (i = 0; i < len; i++) { + key = ngx_hash(key, data[i]); + } + + return key; +} + + +ngx_uint_t +ngx_hash_key_lc(u_char *data, size_t len) +{ + ngx_uint_t i, key; + + key = 0; + + for (i = 0; i < len; i++) { + key = ngx_hash(key, ngx_tolower(data[i])); + } + + return key; +} + + ngx_int_t -ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names, ngx_uint_t nelts) +ngx_hash0_init(ngx_hash0_t *hash, ngx_pool_t *pool, void *names, + ngx_uint_t nelts) { u_char *p; ngx_str_t *name, *bucket; diff --git a/src/core/ngx_hash.h b/src/core/ngx_hash.h index e9912579a..7449d0571 100644 --- a/src/core/ngx_hash.h +++ b/src/core/ngx_hash.h @@ -13,25 +13,81 @@ typedef struct { - void **buckets; - ngx_uint_t hash_size; - - ngx_uint_t max_size; - ngx_uint_t bucket_limit; - size_t bucket_size; - char *name; - ngx_uint_t min_buckets; + void *value; + u_char len; + u_char name[1]; +} ngx_hash_elt_t; + + +typedef struct { + ngx_hash_elt_t **buckets; + ngx_uint_t size; } ngx_hash_t; typedef struct { - ngx_uint_t hash; - ngx_str_t key; - ngx_str_t value; + ngx_hash_t hash; + void *value; +} ngx_hash_wildcard_t; + + +typedef struct { + ngx_str_t key; + ngx_uint_t key_hash; + void *value; +} ngx_hash_key_t; + + +typedef ngx_uint_t (*ngx_hash_key_pt) (u_char *data, size_t len); + + +typedef struct { + ngx_hash_t *hash; + ngx_hash_key_pt key; + + ngx_uint_t max_size; + ngx_uint_t bucket_size; + + char *name; + ngx_pool_t *pool; + ngx_pool_t *temp_pool; +} ngx_hash_init_t; + + +typedef struct { + void **buckets; + ngx_uint_t hash_size; + + ngx_uint_t max_size; + ngx_uint_t bucket_limit; + size_t bucket_size; + char *name; + ngx_uint_t min_buckets; +} ngx_hash0_t; + + +typedef struct { + ngx_uint_t hash; + ngx_str_t key; + ngx_str_t value; } ngx_table_elt_t; -ngx_int_t ngx_hash_init(ngx_hash_t *hash, ngx_pool_t *pool, void *names, +void *ngx_hash_find(ngx_hash_t *hash, ngx_uint_t key, u_char *name, size_t len); +void *ngx_hash_find_wildcard(ngx_hash_wildcard_t *hwc, u_char *name, + size_t len); + +ngx_int_t ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, + ngx_uint_t nelts); +ngx_int_t ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, + ngx_uint_t nelts); + +#define ngx_hash(key, c) key * 31 + c +ngx_uint_t ngx_hash_key(u_char *data, size_t len); +ngx_uint_t ngx_hash_key_lc(u_char *data, size_t len); + + +ngx_int_t ngx_hash0_init(ngx_hash0_t *hash, ngx_pool_t *pool, void *names, ngx_uint_t nelts); diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c index 6cbedde82..9e23592ea 100644 --- a/src/core/ngx_log.c +++ b/src/core/ngx_log.c @@ -324,7 +324,7 @@ ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) cf->cycle->new_log->file->name = value[1]; if (ngx_conf_full_name(cf->cycle, &cf->cycle->new_log->file->name) - == NGX_ERROR) + == NGX_ERROR) { return NGX_CONF_ERROR; } diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c index 3bb0b3598..a0229b2ea 100644 --- a/src/core/ngx_palloc.c +++ b/src/core/ngx_palloc.c @@ -90,10 +90,16 @@ ngx_palloc(ngx_pool_t *pool, size_t size) if (size <= (size_t) NGX_MAX_ALLOC_FROM_POOL && size <= (size_t) (pool->end - (u_char *) pool) - - (size_t) ngx_align(sizeof(ngx_pool_t))) + - (size_t) ngx_align_ptr(sizeof(ngx_pool_t), NGX_ALIGNMENT)) { for (p = pool->current; /* void */ ; p = p->next) { - m = ngx_align(p->last); + + if (size < sizeof(int) || (size & 1)) { + m = p->last; + + } else { + m = ngx_align_ptr(p->last, NGX_ALIGNMENT); + } if ((size_t) (p->end - m) >= size) { p->last = m + size; @@ -122,7 +128,7 @@ ngx_palloc(ngx_pool_t *pool, size_t size) } p->next = n; - m = ngx_align(n->last); + m = ngx_align_ptr(n->last, NGX_ALIGNMENT); n->last = m + size; return m; diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h index 30590ee9e..239728102 100644 --- a/src/core/ngx_palloc.h +++ b/src/core/ngx_palloc.h @@ -13,7 +13,7 @@ /* - * NGX_MAX_ALLOC_FROM_POOL should be (ngx_page_size - 1), i.e. 4095 on x86. + * NGX_MAX_ALLOC_FROM_POOL should be (ngx_pagesize - 1), i.e. 4095 on x86. * On FreeBSD 5.x it allows to use the zero copy sending. * On Windows NT it decreases a number of locked pages in a kernel. */ diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index f042d7c33..2bb335a07 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -980,20 +980,21 @@ ngx_unescape_uri(u_char **dst, u_char **src, size_t size) break; } - /* skip the invalid quoted character */ + /* the invalid quoted character */ - s++; - size--; + state = sw_usual; + + *d++ = ch; break; case sw_quoted_second: + state = sw_usual; + if (ch >= '0' && ch <= '9') { ch = (u_char) ((decoded << 4) + ch - '0'); - state = sw_usual; - if (ch > '%' && ch < 0x7f) { *d++ = ch; break; @@ -1013,8 +1014,6 @@ ngx_unescape_uri(u_char **dst, u_char **src, size_t size) goto done; } - state = sw_usual; - if (ch > '%' && ch < 0x7f) { *d++ = ch; break; @@ -1025,7 +1024,7 @@ ngx_unescape_uri(u_char **dst, u_char **src, size_t size) break; } - /* skip the invalid quoted character */ + /* the invalid quoted character */ break; } |