summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_open_file_cache.c494
-rw-r--r--src/core/ngx_open_file_cache.h15
-rw-r--r--src/core/ngx_queue.h2
-rw-r--r--src/core/ngx_rbtree.c12
-rw-r--r--src/core/ngx_regex.c33
-rw-r--r--src/core/ngx_regex.h8
-rw-r--r--src/core/ngx_resolver.c27
-rw-r--r--src/core/ngx_slab.c15
-rw-r--r--src/core/ngx_string.c19
10 files changed, 382 insertions, 245 deletions
diff --git a/src/core/nginx.h b/src/core/nginx.h
index bae7d8339..3dac5c798 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VERSION "0.6.22"
+#define NGINX_VERSION "0.6.23"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c
index d518f4b96..9c5cc6732 100644
--- a/src/core/ngx_open_file_cache.c
+++ b/src/core/ngx_open_file_cache.c
@@ -18,22 +18,27 @@
static void ngx_open_file_cache_cleanup(void *data);
-static void ngx_open_file_cleanup(void *data);
-static void ngx_close_cached_file(ngx_open_file_cache_t *cache,
- ngx_cached_open_file_t *file, ngx_log_t *log);
static ngx_int_t ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of,
ngx_log_t *log);
+static void ngx_open_file_add_event(ngx_open_file_cache_t *cache,
+ ngx_cached_open_file_t *file, ngx_open_file_info_t *of, ngx_log_t *log);
+static void ngx_open_file_cleanup(void *data);
+static void ngx_close_cached_file(ngx_open_file_cache_t *cache,
+ ngx_cached_open_file_t *file, ngx_uint_t min_uses, ngx_log_t *log);
+static void ngx_open_file_del_event(ngx_cached_open_file_t *file);
static void ngx_expire_old_cached_files(ngx_open_file_cache_t *cache,
ngx_uint_t n, ngx_log_t *log);
static void ngx_open_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp,
ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel);
+static ngx_cached_open_file_t *
+ ngx_open_file_lookup(ngx_open_file_cache_t *cache, ngx_str_t *name,
+ uint32_t hash);
static void ngx_open_file_cache_remove(ngx_event_t *ev);
ngx_open_file_cache_t *
ngx_open_file_cache_init(ngx_pool_t *pool, ngx_uint_t max, time_t inactive)
{
- ngx_rbtree_node_t *sentinel;
ngx_pool_cleanup_t *cln;
ngx_open_file_cache_t *cache;
@@ -42,20 +47,11 @@ ngx_open_file_cache_init(ngx_pool_t *pool, ngx_uint_t max, time_t inactive)
return NULL;
}
- cache->list_head.prev = NULL;
- cache->list_head.next = &cache->list_tail;
-
- cache->list_tail.prev = &cache->list_head;
- cache->list_tail.next = NULL;
-
- sentinel = ngx_palloc(pool, sizeof(ngx_rbtree_node_t));
- if (sentinel == NULL) {
- return NULL;
- }
-
- ngx_rbtree_init(&cache->rbtree, sentinel,
+ ngx_rbtree_init(&cache->rbtree, &cache->sentinel,
ngx_open_file_cache_rbtree_insert_value);
+ ngx_queue_init(&cache->expire_queue);
+
cache->current = 0;
cache->max = max;
cache->inactive = inactive;
@@ -77,6 +73,7 @@ ngx_open_file_cache_cleanup(void *data)
{
ngx_open_file_cache_t *cache = data;
+ ngx_queue_t *q;
ngx_cached_open_file_t *file;
ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
@@ -84,14 +81,15 @@ ngx_open_file_cache_cleanup(void *data)
for ( ;; ) {
- file = cache->list_tail.prev;
-
- if (file == &cache->list_head) {
+ if (ngx_queue_empty(&cache->expire_queue)) {
break;
}
- file->next->prev = file->prev;
- file->prev->next = file->next;
+ q = ngx_queue_last(&cache->expire_queue);
+
+ file = ngx_queue_data(q, ngx_cached_open_file_t, queue);
+
+ ngx_queue_remove(q);
ngx_rbtree_delete(&cache->rbtree, &file->node);
@@ -103,7 +101,7 @@ ngx_open_file_cache_cleanup(void *data)
if (!file->err && !file->is_dir) {
file->close = 1;
file->count = 0;
- ngx_close_cached_file(cache, file, ngx_cycle->log);
+ ngx_close_cached_file(cache, file, 0, ngx_cycle->log);
} else {
ngx_free(file->name);
@@ -132,11 +130,9 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
time_t now;
uint32_t hash;
ngx_int_t rc;
- ngx_rbtree_node_t *node, *sentinel;
ngx_pool_cleanup_t *cln;
ngx_cached_open_file_t *file;
ngx_pool_cleanup_file_t *clnf;
- ngx_open_file_cache_event_t *fev;
ngx_open_file_cache_cleanup_t *ofcln;
of->err = 0;
@@ -167,145 +163,147 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
return NGX_ERROR;
}
+ now = ngx_time();
+
hash = ngx_crc32_long(name->data, name->len);
- node = cache->rbtree.root;
- sentinel = cache->rbtree.sentinel;
+ file = ngx_open_file_lookup(cache, name, hash);
- now = ngx_time();
+ if (file) {
- while (node != sentinel) {
+ file->uses++;
- if (hash < node->key) {
- node = node->left;
- continue;
- }
+ ngx_queue_remove(&file->queue);
- if (hash > node->key) {
- node = node->right;
- continue;
- }
+ if (file->fd == NGX_INVALID_FILE && file->err == 0 && !file->is_dir) {
- /* hash == node->key */
+ /* file was not used often enough to keep open */
- do {
- file = (ngx_cached_open_file_t *) node;
+ rc = ngx_open_and_stat_file(name->data, of, pool->log);
- rc = ngx_strcmp(name->data, file->name);
+ if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
+ goto failed;
+ }
- if (rc == 0) {
+ goto add_event;
+ }
- file->next->prev = file->prev;
- file->prev->next = file->next;
+ if ((file->event && file->use_event)
+ || (file->event == NULL && now - file->created < of->valid))
+ {
+ if (file->err == 0) {
- if (file->event || now - file->created < of->retest) {
- if (file->err == 0) {
- of->fd = file->fd;
- of->uniq = file->uniq;
- of->mtime = file->mtime;
- of->size = file->size;
+ of->fd = file->fd;
+ of->uniq = file->uniq;
+ of->mtime = file->mtime;
+ of->size = file->size;
- of->is_dir = file->is_dir;
- of->is_file = file->is_file;
- of->is_link = file->is_link;
- of->is_exec = file->is_exec;
+ of->is_dir = file->is_dir;
+ of->is_file = file->is_file;
+ of->is_link = file->is_link;
+ of->is_exec = file->is_exec;
- if (!file->is_dir) {
- file->count++;
- }
+ if (!file->is_dir) {
+ file->count++;
+ ngx_open_file_add_event(cache, file, of, pool->log);
+ }
- } else {
- of->err = file->err;
- }
+ } else {
+ of->err = file->err;
+ }
- goto found;
- }
+ goto found;
+ }
- ngx_log_debug4(NGX_LOG_DEBUG_CORE, pool->log, 0,
- "retest open file: %s, fd:%d, c:%d, e:%d",
- file->name, file->fd, file->count, file->err);
+ ngx_log_debug4(NGX_LOG_DEBUG_CORE, pool->log, 0,
+ "retest open file: %s, fd:%d, c:%d, e:%d",
+ file->name, file->fd, file->count, file->err);
- if (file->is_dir) {
+ if (file->is_dir) {
- /*
- * chances that directory became file are very small
- * so test_dir flag allows to use a single ngx_file_info()
- * syscall instead of three syscalls
- */
+ /*
+ * chances that directory became file are very small
+ * so test_dir flag allows to use a single syscall
+ * in ngx_file_info() instead of three syscalls
+ */
- of->test_dir = 1;
- }
+ of->test_dir = 1;
+ }
- rc = ngx_open_and_stat_file(name->data, of, pool->log);
+ rc = ngx_open_and_stat_file(name->data, of, pool->log);
- if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
- goto failed;
- }
+ if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
+ goto failed;
+ }
- if (of->is_dir) {
- if (file->is_dir || file->err) {
- goto update;
- }
+ if (of->is_dir) {
- /* file became directory */
+ if (file->is_dir || file->err) {
+ goto update;
+ }
- } else if (of->err == 0) { /* file */
+ /* file became directory */
- if (file->is_dir || file->err) {
- goto update;
- }
+ } else if (of->err == 0) { /* file */
- if (of->uniq == file->uniq
- && of->mtime == file->mtime
- && of->size == file->size)
- {
- if (ngx_close_file(of->fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed",
- name->data);
- }
+ if (file->is_dir || file->err) {
+ goto add_event;
+ }
- of->fd = file->fd;
- file->count++;
+ if (of->uniq == file->uniq
+ && of->mtime == file->mtime
+ && of->size == file->size)
+ {
+ if (ngx_close_file(of->fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
+ ngx_close_file_n " \"%s\" failed",
+ name->data);
+ }
- goto renew;
- }
+ of->fd = file->fd;
+ file->count++;
- /* file was changed */
+ if (file->event) {
+ file->use_event = 1;
+ goto renew;
+ }
- } else { /* error to cache */
+ ngx_open_file_add_event(cache, file, of, pool->log);
- if (file->err || file->is_dir) {
- goto update;
- }
+ goto renew;
+ }
- /* file was removed, etc. */
- }
+ /* file was changed */
- if (file->count == 0) {
- if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed",
- name->data);
- }
+ } else { /* error to cache */
- goto update;
- }
+ if (file->err || file->is_dir) {
+ goto update;
+ }
- ngx_rbtree_delete(&cache->rbtree, &file->node);
+ /* file was removed, etc. */
+ }
- cache->current--;
+ if (file->count == 0) {
- file->close = 1;
+ ngx_open_file_del_event(file);
- goto create;
+ if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
+ ngx_close_file_n " \"%s\" failed",
+ name->data);
}
- node = (rc < 0) ? node->left : node->right;
+ goto add_event;
+ }
- } while (node != sentinel && hash == node->key);
+ ngx_rbtree_delete(&cache->rbtree, &file->node);
- break;
+ cache->current--;
+
+ file->close = 1;
+
+ goto create;
}
/* not found */
@@ -346,50 +344,16 @@ create:
cache->current++;
+ file->uses = 1;
file->count = 0;
+ file->use_event = 0;
+ file->event = NULL;
-update:
-
- if (of->events
- && (ngx_event_flags & NGX_USE_VNODE_EVENT)
- && of->fd != NGX_INVALID_FILE)
- {
- file->event = ngx_calloc(sizeof(ngx_event_t), pool->log);
- if (file->event== NULL) {
- goto failed;
- }
-
- fev = ngx_alloc(sizeof(ngx_open_file_cache_event_t), pool->log);
- if (fev == NULL) {
- goto failed;
- }
-
- fev->fd = of->fd;
- fev->file = file;
- fev->cache = cache;
-
- file->event->handler = ngx_open_file_cache_remove;
- file->event->data = fev;
-
- /*
- * although vnode event may be called while ngx_cycle->poll
- * destruction; however, cleanup procedures are run before any
- * memory freeing and events will be canceled.
- */
-
- file->event->log = ngx_cycle->log;
+add_event:
- if (ngx_add_event(file->event, NGX_VNODE_EVENT, NGX_ONESHOT_EVENT)
- != NGX_OK)
- {
- ngx_free(file->event->data);
- ngx_free(file->event);
- goto failed;
- }
+ ngx_open_file_add_event(cache, file, of, pool->log);
- } else {
- file->event = NULL;
- }
+update:
file->fd = of->fd;
file->err = of->err;
@@ -419,16 +383,11 @@ found:
file->accessed = now;
- /* add to the inactive list head */
-
- file->next = cache->list_head.next;
- file->next->prev = file;
- file->prev = &cache->list_head;
- cache->list_head.next = file;
+ ngx_queue_insert_head(&cache->expire_queue, &file->queue);
- ngx_log_debug4(NGX_LOG_DEBUG_CORE, pool->log, 0,
- "cached open file: %s, fd:%d, c:%d, e:%d",
- file->name, file->fd, file->count, file->err);
+ ngx_log_debug5(NGX_LOG_DEBUG_CORE, pool->log, 0,
+ "cached open file: %s, fd:%d, c:%d, e:%d, u:%d",
+ file->name, file->fd, file->count, file->err, file->uses);
if (of->err == 0) {
@@ -438,6 +397,7 @@ found:
ofcln->cache = cache;
ofcln->file = file;
+ ofcln->min_uses = of->min_uses;
ofcln->log = pool->log;
}
@@ -543,6 +503,72 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
}
+/*
+ * we ignore any possible event setting error and
+ * fallback to usual periodic file retests
+ */
+
+static void
+ngx_open_file_add_event(ngx_open_file_cache_t *cache,
+ ngx_cached_open_file_t *file, ngx_open_file_info_t *of, ngx_log_t *log)
+{
+ ngx_open_file_cache_event_t *fev;
+
+ if (!(ngx_event_flags & NGX_USE_VNODE_EVENT)
+ || !of->events
+ || file->event
+ || of->fd == NGX_INVALID_FILE
+ || file->uses < of->min_uses)
+ {
+ return;
+ }
+
+ file->event = ngx_calloc(sizeof(ngx_event_t), log);
+ if (file->event== NULL) {
+ return;
+ }
+
+ fev = ngx_alloc(sizeof(ngx_open_file_cache_event_t), log);
+ if (fev == NULL) {
+ ngx_free(file->event);
+ file->event = NULL;
+ return;
+ }
+
+ fev->fd = of->fd;
+ fev->file = file;
+ fev->cache = cache;
+
+ file->event->handler = ngx_open_file_cache_remove;
+ file->event->data = fev;
+
+ /*
+ * although vnode event may be called while ngx_cycle->poll
+ * destruction, however, cleanup procedures are run before any
+ * memory freeing and events will be canceled.
+ */
+
+ file->event->log = ngx_cycle->log;
+
+ if (ngx_add_event(file->event, NGX_VNODE_EVENT, NGX_ONESHOT_EVENT)
+ != NGX_OK)
+ {
+ ngx_free(file->event->data);
+ ngx_free(file->event);
+ file->event = NULL;
+ return;
+ }
+
+ /*
+ * we do not file->use_event here because there may be a race
+ * condition between opening file and adding event, so we rely
+ * upon event notification only after first file revalidation
+ */
+
+ return;
+}
+
+
static void
ngx_open_file_cleanup(void *data)
{
@@ -550,7 +576,7 @@ ngx_open_file_cleanup(void *data)
c->file->count--;
- ngx_close_cached_file(c->cache, c->file, c->log);
+ ngx_close_cached_file(c->cache, c->file, c->min_uses, c->log);
/* drop one or two expired open files */
ngx_expire_old_cached_files(c->cache, 1, c->log);
@@ -559,50 +585,43 @@ ngx_open_file_cleanup(void *data)
static void
ngx_close_cached_file(ngx_open_file_cache_t *cache,
- ngx_cached_open_file_t *file, ngx_log_t *log)
+ ngx_cached_open_file_t *file, ngx_uint_t min_uses, ngx_log_t *log)
{
- ngx_log_debug4(NGX_LOG_DEBUG_CORE, log, 0,
- "close cached open file: %s, fd:%d, c:%d, %d",
- file->name, file->fd, file->count, file->close);
+ ngx_log_debug5(NGX_LOG_DEBUG_CORE, log, 0,
+ "close cached open file: %s, fd:%d, c:%d, u:%d, %d",
+ file->name, file->fd, file->count, file->uses, file->close);
if (!file->close) {
file->accessed = ngx_time();
- if (cache->list_head.next != file) {
-
- /* delete from inactive list */
+ ngx_queue_remove(&file->queue);
- file->next->prev = file->prev;
- file->prev->next = file->next;
+ ngx_queue_insert_head(&cache->expire_queue, &file->queue);
- /* add to the inactive list head */
-
- file->next = cache->list_head.next;
- file->next->prev = file;
- file->prev = &cache->list_head;
- cache->list_head.next = file;
+ if (file->uses >= min_uses || file->count) {
+ return;
}
+ }
+ ngx_open_file_del_event(file);
+
+ if (file->count) {
return;
}
- if (file->event) {
- (void) ngx_del_event(file->event, NGX_VNODE_EVENT,
- file->count ? NGX_FLUSH_EVENT : NGX_CLOSE_EVENT);
+ if (file->fd != NGX_INVALID_FILE) {
- ngx_free(file->event->data);
- ngx_free(file->event);
- file->event = NULL;
- }
+ if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ ngx_close_file_n " \"%s\" failed", file->name);
+ }
- if (file->count) {
- return;
+ file->fd = NGX_INVALID_FILE;
}
- if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {
- ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", file->name);
+ if (!file->close) {
+ return;
}
ngx_free(file->name);
@@ -611,10 +630,28 @@ ngx_close_cached_file(ngx_open_file_cache_t *cache,
static void
+ngx_open_file_del_event(ngx_cached_open_file_t *file)
+{
+ if (file->event == NULL) {
+ return;
+ }
+
+ (void) ngx_del_event(file->event, NGX_VNODE_EVENT,
+ file->count ? NGX_FLUSH_EVENT : NGX_CLOSE_EVENT);
+
+ ngx_free(file->event->data);
+ ngx_free(file->event);
+ file->event = NULL;
+ file->use_event = 0;
+}
+
+
+static void
ngx_expire_old_cached_files(ngx_open_file_cache_t *cache, ngx_uint_t n,
ngx_log_t *log)
{
time_t now;
+ ngx_queue_t *q;
ngx_cached_open_file_t *file;
now = ngx_time();
@@ -627,18 +664,19 @@ ngx_expire_old_cached_files(ngx_open_file_cache_t *cache, ngx_uint_t n,
while (n < 3) {
- file = cache->list_tail.prev;
-
- if (file == &cache->list_head) {
+ if (ngx_queue_empty(&cache->expire_queue)) {
return;
}
+ q = ngx_queue_last(&cache->expire_queue);
+
+ file = ngx_queue_data(q, ngx_cached_open_file_t, queue);
+
if (n++ != 0 && now - file->accessed <= cache->inactive) {
return;
}
- file->next->prev = file->prev;
- file->prev->next = file->next;
+ ngx_queue_remove(q);
ngx_rbtree_delete(&cache->rbtree, &file->node);
@@ -649,7 +687,7 @@ ngx_expire_old_cached_files(ngx_open_file_cache_t *cache, ngx_uint_t n,
if (!file->err && !file->is_dir) {
file->close = 1;
- ngx_close_cached_file(cache, file, log);
+ ngx_close_cached_file(cache, file, 0, log);
} else {
ngx_free(file->name);
@@ -700,6 +738,51 @@ ngx_open_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp,
}
+static ngx_cached_open_file_t *
+ngx_open_file_lookup(ngx_open_file_cache_t *cache, ngx_str_t *name,
+ uint32_t hash)
+{
+ ngx_int_t rc;
+ ngx_rbtree_node_t *node, *sentinel;
+ ngx_cached_open_file_t *file;
+
+ node = cache->rbtree.root;
+ sentinel = cache->rbtree.sentinel;
+
+ while (node != sentinel) {
+
+ if (hash < node->key) {
+ node = node->left;
+ continue;
+ }
+
+ if (hash > node->key) {
+ node = node->right;
+ continue;
+ }
+
+ /* hash == node->key */
+
+ do {
+ file = (ngx_cached_open_file_t *) node;
+
+ rc = ngx_strcmp(name->data, file->name);
+
+ if (rc == 0) {
+ return file;
+ }
+
+ node = (rc < 0) ? node->left : node->right;
+
+ } while (node != sentinel && hash == node->key);
+
+ break;
+ }
+
+ return NULL;
+}
+
+
static void
ngx_open_file_cache_remove(ngx_event_t *ev)
{
@@ -709,8 +792,7 @@ ngx_open_file_cache_remove(ngx_event_t *ev)
fev = ev->data;
file = fev->file;
- file->next->prev = file->prev;
- file->prev->next = file->next;
+ ngx_queue_remove(&file->queue);
ngx_rbtree_delete(&fev->cache->rbtree, &file->node);
@@ -721,7 +803,7 @@ ngx_open_file_cache_remove(ngx_event_t *ev)
file->close = 1;
- ngx_close_cached_file(fev->cache, file, ev->log);
+ ngx_close_cached_file(fev->cache, file, 0, ev->log);
/* free memory only when fev->cache and fev->file are already not needed */
diff --git a/src/core/ngx_open_file_cache.h b/src/core/ngx_open_file_cache.h
index cc0d899a2..dd294e77a 100644
--- a/src/core/ngx_open_file_cache.h
+++ b/src/core/ngx_open_file_cache.h
@@ -19,7 +19,9 @@ typedef struct {
off_t size;
ngx_err_t err;
- time_t retest;
+ time_t valid;
+
+ ngx_uint_t min_uses;
unsigned test_dir:1;
unsigned errors:1;
@@ -36,8 +38,7 @@ typedef struct ngx_cached_open_file_s ngx_cached_open_file_t;
struct ngx_cached_open_file_s {
ngx_rbtree_node_t node;
- ngx_cached_open_file_t *prev;
- ngx_cached_open_file_t *next;
+ ngx_queue_t queue;
u_char *name;
time_t created;
@@ -49,8 +50,11 @@ struct ngx_cached_open_file_s {
off_t size;
ngx_err_t err;
+ uint32_t uses;
+
unsigned count:24;
unsigned close:1;
+ unsigned use_event:1;
unsigned is_dir:1;
unsigned is_file:1;
@@ -63,8 +67,8 @@ struct ngx_cached_open_file_s {
typedef struct {
ngx_rbtree_t rbtree;
- ngx_cached_open_file_t list_head;
- ngx_cached_open_file_t list_tail;
+ ngx_rbtree_node_t sentinel;
+ ngx_queue_t expire_queue;
ngx_uint_t current;
ngx_uint_t max;
@@ -75,6 +79,7 @@ typedef struct {
typedef struct {
ngx_open_file_cache_t *cache;
ngx_cached_open_file_t *file;
+ ngx_uint_t min_uses;
ngx_log_t *log;
} ngx_open_file_cache_cleanup_t;
diff --git a/src/core/ngx_queue.h b/src/core/ngx_queue.h
index 39296add4..1407d85a6 100644
--- a/src/core/ngx_queue.h
+++ b/src/core/ngx_queue.h
@@ -22,7 +22,7 @@ struct ngx_queue_s {
#define ngx_queue_init(q) \
(q)->prev = q; \
- (q)->next = q;
+ (q)->next = q
#define ngx_queue_empty(h) \
diff --git a/src/core/ngx_rbtree.c b/src/core/ngx_rbtree.c
index 7d240fe81..749b601f2 100644
--- a/src/core/ngx_rbtree.c
+++ b/src/core/ngx_rbtree.c
@@ -242,14 +242,14 @@ ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree,
if (subst->right != sentinel) {
subst->right->parent = subst;
}
-
- /* DEBUG stuff */
- node->left = NULL;
- node->right = NULL;
- node->parent = NULL;
- node->key = 0;
}
+ /* DEBUG stuff */
+ node->left = NULL;
+ node->right = NULL;
+ node->parent = NULL;
+ node->key = 0;
+
if (red) {
return;
}
diff --git a/src/core/ngx_regex.c b/src/core/ngx_regex.c
index eda243bec..be2dae79b 100644
--- a/src/core/ngx_regex.c
+++ b/src/core/ngx_regex.c
@@ -114,6 +114,39 @@ ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, ngx_int_t size)
}
+ngx_int_t
+ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log)
+{
+ ngx_int_t n;
+ ngx_uint_t i;
+ ngx_regex_elt_t *re;
+
+ re = a->elts;
+
+ for (i = 0; i < a->nelts; i++) {
+
+ n = ngx_regex_exec(re[i].regex, s, NULL, 0);
+
+ if (n == NGX_REGEX_NO_MATCHED) {
+ continue;
+ }
+
+ if (n < 0) {
+ ngx_log_error(NGX_LOG_ALERT, log, 0,
+ ngx_regex_exec_n " failed: %d on \"%V\" using \"%s\"",
+ n, s, re[i].name);
+ return NGX_ERROR;
+ }
+
+ /* match */
+
+ return NGX_OK;
+ }
+
+ return NGX_DECLINED;
+}
+
+
static void * ngx_libc_cdecl
ngx_regex_malloc(size_t size)
{
diff --git a/src/core/ngx_regex.h b/src/core/ngx_regex.h
index 430637721..e31470f9f 100644
--- a/src/core/ngx_regex.h
+++ b/src/core/ngx_regex.h
@@ -20,12 +20,20 @@
typedef pcre ngx_regex_t;
+typedef struct {
+ ngx_regex_t *regex;
+ u_char *name;
+} ngx_regex_elt_t;
+
+
void ngx_regex_init(void);
ngx_regex_t *ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options,
ngx_pool_t *pool, ngx_str_t *err);
ngx_int_t ngx_regex_capture_count(ngx_regex_t *re);
ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures,
ngx_int_t size);
+ngx_int_t ngx_regex_exec_array(ngx_array_t *a, ngx_str_t *s, ngx_log_t *log);
+
#define ngx_regex_exec_n "pcre_exec()"
#define ngx_regex_capture_count_n "pcre_fullinfo()"
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index be0121e2e..ef2c92ba4 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -669,17 +669,8 @@ ngx_resolver_expire(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
return;
}
-#if (NGX_DEBUG)
- {
- ngx_str_t s;
-
- s.len = rn->nlen;
- s.data = rn->name;
-
- ngx_log_debug1(NGX_LOG_DEBUG_CORE, r->log, 0,
- "resolver expire \"%V\"", &s);
- }
-#endif
+ ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
+ "resolver expire \"%*s\"", (size_t) rn->nlen, rn->name);
ngx_queue_remove(q);
@@ -783,17 +774,9 @@ ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
return rn->expire - now;
}
-#if (NGX_DEBUG)
- {
- ngx_str_t s;
-
- s.len = rn->nlen;
- s.data = rn->name;
-
- ngx_log_debug2(NGX_LOG_DEBUG_CORE, r->log, 0,
- "resolver resend \"%V\" %p", &s, rn->waiting);
- }
-#endif
+ ngx_log_debug3(NGX_LOG_DEBUG_CORE, r->log, 0,
+ "resolver resend \"%*s\" %p",
+ (size_t) rn->nlen, rn->name, rn->waiting);
ngx_queue_remove(q);
diff --git a/src/core/ngx_slab.c b/src/core/ngx_slab.c
index 9f63a91eb..b187026d8 100644
--- a/src/core/ngx_slab.c
+++ b/src/core/ngx_slab.c
@@ -58,9 +58,22 @@
#if (NGX_DEBUG_MALLOC)
-#define ngx_slab_junk(p, size) ngx_memset(p, 0xD0, size)
+
+#define ngx_slab_junk(p, size) ngx_memset(p, 0xD0, size)
+
+#else
+
+#if (NGX_FREEBSD)
+
+#define ngx_slab_junk(p, size) \
+ if (ngx_freebsd_debug_malloc) ngx_memset(p, 0xD0, size)
+
#else
+
#define ngx_slab_junk(p, size)
+
+#endif
+
#endif
static ngx_slab_page_t *ngx_slab_alloc_pages(ngx_slab_pool_t *pool,
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c
index f878c559f..d9a5480da 100644
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -63,6 +63,7 @@ ngx_pstrdup(ngx_pool_t *pool, ngx_str_t *src)
* %V ngx_str_t *
* %v ngx_variable_value_t *
* %s null-terminated string
+ * %*s length and string
* %Z '\0'
* %N '\n'
* %c char
@@ -112,7 +113,7 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
* but icc issues the warning
*/
int d;
- size_t len;
+ size_t len, slen;
uint32_t ui32;
int64_t i64;
uint64_t ui64;
@@ -146,6 +147,7 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
sign = 1;
hexadecimal = 0;
max_width = 0;
+ slen = 0;
p = temp + NGX_INT64_LEN;
@@ -179,6 +181,11 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
fmt++;
continue;
+ case '*':
+ slen = va_arg(args, u_int);
+ fmt++;
+ continue;
+
default:
break;
}
@@ -214,9 +221,15 @@ ngx_vsnprintf(u_char *buf, size_t max, const char *fmt, va_list args)
case 's':
p = va_arg(args, u_char *);
- while (*p && buf < last) {
- *buf++ = *p++;
+ if (slen == 0) {
+ while (*p && buf < last) {
+ *buf++ = *p++;
+ }
+
+ } else {
+ buf = ngx_cpymem(buf, p, slen);
}
+
fmt++;
continue;