# HG changeset patch # User Vladimir Homutov # Date 1476797618 -10800 # Node ID 1bf4f21b1b72e3d657f14e9b36d2637f14b34b88 # Parent 8081e1f3ab8b9ccb4e2d7f9240cbfb8e404a3c95 Core: show file contents only once while dumping configuration. Files are considered the same if the path used by nginx during parsing matches. diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -10,6 +10,7 @@ #define NGX_CONF_BUFFER 4096 +static ngx_int_t ngx_conf_add_dump(ngx_conf_t *cf, ngx_str_t *filename); static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last); static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf); static void ngx_conf_flush_files(ngx_cycle_t *cycle); @@ -97,17 +98,70 @@ ngx_conf_param(ngx_conf_t *cf) } +static ngx_int_t +ngx_conf_add_dump(ngx_conf_t *cf, ngx_str_t *filename) +{ + off_t size; + u_char *p; + uint32_t hash; + ngx_buf_t *buf; + ngx_str_node_t *sn; + ngx_conf_dump_t *cd; + + hash = ngx_crc32_long(filename->data, filename->len); + + sn = ngx_str_rbtree_lookup(&cf->cycle->config_dump_rbtree, filename, hash); + + if (sn) { + cf->conf_file->dump = NULL; + return NGX_OK; + } + + p = ngx_pstrdup(cf->cycle->pool, filename); + if (p == NULL) { + return NGX_ERROR; + } + + cd = ngx_array_push(&cf->cycle->config_dump); + if (cd == NULL) { + return NGX_ERROR; + } + + size = ngx_file_size(&cf->conf_file->file.info); + + buf = ngx_create_temp_buf(cf->cycle->pool, (size_t) size); + if (buf == NULL) { + return NGX_ERROR; + } + + cd->name.data = p; + cd->name.len = filename->len; + cd->buffer = buf; + + cf->conf_file->dump = buf; + + sn = ngx_palloc(cf->temp_pool, sizeof(ngx_str_node_t)); + if (sn == NULL) { + return NGX_ERROR; + } + + sn->node.key = hash; + sn->str = cd->name; + + ngx_rbtree_insert(&cf->cycle->config_dump_rbtree, &sn->node); + + return NGX_OK; +} + + char * ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename) { char *rv; - u_char *p; - off_t size; ngx_fd_t fd; ngx_int_t rc; - ngx_buf_t buf, *tbuf; + ngx_buf_t buf; ngx_conf_file_t *prev, conf_file; - ngx_conf_dump_t *cd; enum { parse_file = 0, parse_block, @@ -167,29 +221,10 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t #endif ) { - p = ngx_pstrdup(cf->cycle->pool, filename); - if (p == NULL) { - goto failed; - } - - size = ngx_file_size(&cf->conf_file->file.info); - - tbuf = ngx_create_temp_buf(cf->cycle->pool, (size_t) size); - if (tbuf == NULL) { + if (ngx_conf_add_dump(cf, filename) != NGX_OK) { goto failed; } - cd = ngx_array_push(&cf->cycle->config_dump); - if (cd == NULL) { - goto failed; - } - - cd->name.len = filename->len; - cd->name.data = p; - cd->buffer = tbuf; - - cf->conf_file->dump = tbuf; - } else { cf->conf_file->dump = NULL; } diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -132,6 +132,9 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) return NULL; } + ngx_rbtree_init(&cycle->config_dump_rbtree, &cycle->config_dump_sentinel, + ngx_str_rbtree_insert_value); + if (old_cycle->open_files.part.nelts) { n = old_cycle->open_files.part.nelts; for (part = old_cycle->open_files.part.next; part; part = part->next) { diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -56,7 +56,11 @@ struct ngx_cycle_s { ngx_array_t listening; ngx_array_t paths; + ngx_array_t config_dump; + ngx_rbtree_t config_dump_rbtree; + ngx_rbtree_node_t config_dump_sentinel; + ngx_list_t open_files; ngx_list_t shared_memory;