Mercurial > hg > nginx-mail
diff src/http/ngx_http_file_cache.c @ 665:0b460e61bdcd default tip
Merge with nginx 1.0.0.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 25 Apr 2011 04:22:17 +0400 |
parents | b4dcae568a2a |
children |
line wrap: on
line diff
--- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -12,11 +12,15 @@ static ngx_int_t ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c); +static ssize_t ngx_http_file_cache_aio_read(ngx_http_request_t *r, + ngx_http_cache_t *c); #if (NGX_HAVE_FILE_AIO) static void ngx_http_cache_aio_event_handler(ngx_event_t *ev); #endif static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache, ngx_http_cache_t *c); +static ngx_int_t ngx_http_file_cache_name(ngx_http_request_t *r, + ngx_path_t *path); static ngx_http_file_cache_node_t * ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key); static void ngx_http_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp, @@ -42,6 +46,7 @@ static ngx_int_t ngx_http_file_cache_del ngx_str_t ngx_http_cache_status[] = { ngx_string("MISS"), + ngx_string("BYPASS"), ngx_string("EXPIRED"), ngx_string("STALE"), ngx_string("UPDATING"), @@ -140,6 +145,60 @@ ngx_http_file_cache_init(ngx_shm_zone_t } +ngx_int_t +ngx_http_file_cache_new(ngx_http_request_t *r) +{ + ngx_http_cache_t *c; + + c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t)); + if (c == NULL) { + return NGX_ERROR; + } + + if (ngx_array_init(&c->keys, r->pool, 4, sizeof(ngx_str_t)) != NGX_OK) { + return NGX_ERROR; + } + + r->cache = c; + c->file.log = r->connection->log; + c->file.fd = NGX_INVALID_FILE; + + return NGX_OK; +} + + +ngx_int_t +ngx_http_file_cache_create(ngx_http_request_t *r) +{ + ngx_http_cache_t *c; + ngx_pool_cleanup_t *cln; + ngx_http_file_cache_t *cache; + + ngx_http_file_cache_create_key(r); + + c = r->cache; + cache = c->file_cache; + + cln = ngx_pool_cleanup_add(r->pool, 0); + if (cln == NULL) { + return NGX_ERROR; + } + + if (ngx_http_file_cache_exists(cache, c) == NGX_ERROR) { + return NGX_ERROR; + } + + cln->handler = ngx_http_file_cache_cleanup; + cln->data = c; + + if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) { + return NGX_ERROR; + } + + return NGX_OK; +} + + void ngx_http_file_cache_create_key(ngx_http_request_t *r) { @@ -178,10 +237,8 @@ ngx_http_file_cache_create_key(ngx_http_ ngx_int_t ngx_http_file_cache_open(ngx_http_request_t *r) { - u_char *p; ngx_int_t rc, rv; ngx_uint_t cold, test; - ngx_path_t *path; ngx_http_cache_t *c; ngx_pool_cleanup_t *cln; ngx_open_file_info_t of; @@ -247,27 +304,10 @@ ngx_http_file_cache_open(ngx_http_reques } } - path = cache->path; - - c->file.name.len = path->name.len + 1 + path->len - + 2 * NGX_HTTP_CACHE_KEY_LEN; - - c->file.name.data = ngx_pnalloc(r->pool, c->file.name.len + 1); - if (c->file.name.data == NULL) { + if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) { return NGX_ERROR; } - ngx_memcpy(c->file.name.data, path->name.data, path->name.len); - - p = c->file.name.data + path->name.len + 1 + path->len; - p = ngx_hex_dump(p, c->key, NGX_HTTP_CACHE_KEY_LEN); - *p = '\0'; - - ngx_create_hashed_filename(path, c->file.name.data, c->file.name.len); - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, - "cache file: \"%s\"", c->file.name.data); - if (!test) { return NGX_DECLINED; } @@ -281,6 +321,7 @@ ngx_http_file_cache_open(ngx_http_reques of.min_uses = clcf->open_file_cache_min_uses; of.events = clcf->open_file_cache_events; of.directio = NGX_OPEN_FILE_DIRECTIO_OFF; + of.read_ahead = clcf->read_ahead; if (ngx_open_cached_file(clcf->open_file_cache, &c->file.name, &of, r->pool) != NGX_OK) @@ -327,42 +368,13 @@ ngx_http_file_cache_read(ngx_http_reques ngx_http_file_cache_t *cache; ngx_http_file_cache_header_t *h; - c = r->cache; - -#if (NGX_HAVE_FILE_AIO) - { - ngx_http_core_loc_conf_t *clcf; - - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - - if (clcf->aio) { - n = ngx_file_aio_read(&c->file, c->buf->pos, c->body_start, 0, r->pool); - - if (n == NGX_AGAIN) { - c->file.aio->data = r; - c->file.aio->handler = ngx_http_cache_aio_event_handler; + n = ngx_http_file_cache_aio_read(r, c); - r->main->blocked++; - r->aio = 1; - - return NGX_AGAIN; - } - - } else { - n = ngx_read_file(&c->file, c->buf->pos, c->body_start, 0); - } - } -#else - - n = ngx_read_file(&c->file, c->buf->pos, c->body_start, 0); - -#endif - - if (n == NGX_ERROR) { + if (n < 0) { return n; } - if ((size_t) n <= c->header_start) { + if ((size_t) n < c->header_start) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, "cache file \"%s\" is too small", c->file.name.data); return NGX_ERROR; @@ -370,7 +382,7 @@ ngx_http_file_cache_read(ngx_http_reques h = (ngx_http_file_cache_header_t *) c->buf->pos; - if (h->crc32 != c->crc32 || (size_t) h->header_start != c->header_start) { + if (h->crc32 != c->crc32) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, "cache file \"%s\" has md5 collision", c->file.name.data); return NGX_DECLINED; @@ -382,6 +394,7 @@ ngx_http_file_cache_read(ngx_http_reques c->last_modified = h->last_modified; c->date = h->date; c->valid_msec = h->valid_msec; + c->header_start = h->header_start; c->body_start = h->body_start; r->cached = 1; @@ -415,6 +428,7 @@ ngx_http_file_cache_read(ngx_http_reques } else { c->node->updating = 1; + c->updating = 1; rc = NGX_HTTP_CACHE_STALE; } @@ -431,8 +445,46 @@ ngx_http_file_cache_read(ngx_http_reques } +static ssize_t +ngx_http_file_cache_aio_read(ngx_http_request_t *r, ngx_http_cache_t *c) +{ #if (NGX_HAVE_FILE_AIO) + ssize_t n; + ngx_http_core_loc_conf_t *clcf; + if (!ngx_file_aio) { + goto noaio; + } + + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (!clcf->aio) { + goto noaio; + } + + n = ngx_file_aio_read(&c->file, c->buf->pos, c->body_start, 0, r->pool); + + if (n != NGX_AGAIN) { + return n; + } + + c->file.aio->data = r; + c->file.aio->handler = ngx_http_cache_aio_event_handler; + + r->main->blocked++; + r->aio = 1; + + return NGX_AGAIN; + +noaio: + +#endif + + return ngx_read_file(&c->file, c->buf->pos, c->body_start, 0); +} + + +#if (NGX_HAVE_FILE_AIO) static void ngx_http_cache_aio_event_handler(ngx_event_t *ev) @@ -465,6 +517,9 @@ ngx_http_file_cache_exists(ngx_http_file if (fcn) { ngx_queue_remove(&fcn->queue); + fcn->uses++; + fcn->count++; + if (fcn->error) { if (fcn->valid_sec < ngx_time()) { @@ -476,9 +531,6 @@ ngx_http_file_cache_exists(ngx_http_file goto done; } - fcn->uses++; - fcn->count++; - if (fcn->exists) { c->exists = fcn->exists; @@ -527,12 +579,15 @@ ngx_http_file_cache_exists(ngx_http_file ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node); + fcn->uses = 1; + fcn->count = 1; + fcn->updating = 0; + fcn->deleting = 0; + renew: rc = NGX_DECLINED; - fcn->uses = 1; - fcn->count = 1; fcn->valid_msec = 0; fcn->error = 0; fcn->exists = 0; @@ -559,6 +614,37 @@ failed: } +static ngx_int_t +ngx_http_file_cache_name(ngx_http_request_t *r, ngx_path_t *path) +{ + u_char *p; + ngx_http_cache_t *c; + + c = r->cache; + + c->file.name.len = path->name.len + 1 + path->len + + 2 * NGX_HTTP_CACHE_KEY_LEN; + + c->file.name.data = ngx_pnalloc(r->pool, c->file.name.len + 1); + if (c->file.name.data == NULL) { + return NGX_ERROR; + } + + ngx_memcpy(c->file.name.data, path->name.data, path->name.len); + + p = c->file.name.data + path->name.len + 1 + path->len; + p = ngx_hex_dump(p, c->key, NGX_HTTP_CACHE_KEY_LEN); + *p = '\0'; + + ngx_create_hashed_filename(path, c->file.name.data, c->file.name.len); + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "cache file: \"%s\"", c->file.name.data); + + return NGX_OK; +} + + static ngx_http_file_cache_node_t * ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key) { @@ -691,7 +777,7 @@ ngx_http_file_cache_set_header(ngx_http_ void ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf) { - off_t size; + off_t size, length; ngx_int_t rc; ngx_file_uniq_t uniq; ngx_file_info_t fi; @@ -709,10 +795,12 @@ ngx_http_file_cache_update(ngx_http_requ "http file cache update"); c->updated = 1; + c->updating = 0; cache = c->file_cache; uniq = 0; + length = 0; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http file cache rename: \"%s\" to \"%s\"", @@ -737,10 +825,11 @@ ngx_http_file_cache_update(ngx_http_requ } else { uniq = ngx_file_uniq(&fi); + length = ngx_file_size(&fi); } } - size = (c->length + cache->bsize - 1) / cache->bsize; + size = (length + cache->bsize - 1) / cache->bsize; ngx_shmtx_lock(&cache->shpool->mutex); @@ -750,7 +839,7 @@ ngx_http_file_cache_update(ngx_http_requ size = size - (c->node->length + cache->bsize - 1) / cache->bsize; - c->node->length = c->length; + c->node->length = length; cache->sh->size += size; @@ -767,7 +856,6 @@ ngx_http_file_cache_update(ngx_http_requ ngx_int_t ngx_http_cache_send(ngx_http_request_t *r) { - off_t size; ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; @@ -790,21 +878,18 @@ ngx_http_cache_send(ngx_http_request_t * return NGX_HTTP_INTERNAL_SERVER_ERROR; } + r->header_only = (c->length - c->body_start) == 0; + rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } - size = c->length - c->body_start; - if (size == 0) { - return rc; - } - b->file_pos = c->body_start; b->file_last = c->length; - b->in_file = size ? 1: 0; + b->in_file = 1; b->last_buf = (r == r->main) ? 1: 0; b->last_in_chain = 1; @@ -820,46 +905,57 @@ ngx_http_cache_send(ngx_http_request_t * void -ngx_http_file_cache_free(ngx_http_request_t *r, ngx_temp_file_t *tf) +ngx_http_file_cache_free(ngx_http_cache_t *c, ngx_temp_file_t *tf) { - ngx_http_cache_t *c; - ngx_http_file_cache_t *cache; - - c = r->cache; + ngx_http_file_cache_t *cache; + ngx_http_file_cache_node_t *fcn; if (c->updated) { return; } - c->updated = 1; - cache = c->file_cache; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http file cache free"); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->file.log, 0, + "http file cache free, fd: %d", c->file.fd); ngx_shmtx_lock(&cache->shpool->mutex); - c->node->count--; + fcn = c->node; + fcn->count--; + + if (c->updating) { + fcn->updating = 0; + } if (c->error) { - c->node->valid_sec = c->valid_sec; - c->node->valid_msec = c->valid_msec; - c->node->error = c->error; + fcn->error = c->error; + + if (c->valid_sec) { + fcn->valid_sec = c->valid_sec; + fcn->valid_msec = c->valid_msec; + } + + } else if (!fcn->exists && fcn->count == 0 && c->min_uses == 1) { + ngx_queue_remove(&fcn->queue); + ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); + ngx_slab_free_locked(cache->shpool, fcn); + c->node = NULL; } - c->node->updating = 0; - ngx_shmtx_unlock(&cache->shpool->mutex); + c->updated = 1; + c->updating = 0; + if (c->temp_file) { if (tf && tf->file.fd != NGX_INVALID_FILE) { - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->file.log, 0, "http file cache incomplete: \"%s\"", tf->file.name.data); if (ngx_delete_file(tf->file.name.data) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, + ngx_log_error(NGX_LOG_CRIT, c->file.log, ngx_errno, ngx_delete_file_n " \"%s\" failed", tf->file.name.data); } @@ -873,28 +969,19 @@ ngx_http_file_cache_cleanup(void *data) { ngx_http_cache_t *c = data; - ngx_http_file_cache_t *cache; - if (c->updated) { return; } - c->updated = 1; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->file.log, 0, "http file cache cleanup"); - if (c->error) { - return; + if (c->updating) { + ngx_log_error(NGX_LOG_ALERT, c->file.log, 0, + "stalled cache updating, error:%ui", c->error); } - cache = c->file_cache; - - ngx_shmtx_lock(&cache->shpool->mutex); - - c->node->count--; - - ngx_shmtx_unlock(&cache->shpool->mutex); + ngx_http_file_cache_free(c, NULL); } @@ -923,7 +1010,7 @@ ngx_http_file_cache_forced_expire(ngx_ht ngx_memcpy(name, path->name.data, path->name.len); wait = 10; - tries = 0; + tries = 20; ngx_shmtx_lock(&cache->shpool->mutex); @@ -938,28 +1025,18 @@ ngx_http_file_cache_forced_expire(ngx_ht fcn->count, fcn->exists, fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]); - if (fcn->count) { + if (fcn->count == 0) { + ngx_http_file_cache_delete(cache, q, name); + wait = 0; - if (tries++ < 20) { + } else { + if (--tries) { continue; } wait = 1; - - break; } - if (!fcn->exists) { - - ngx_queue_remove(q); - ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); - ngx_slab_free_locked(cache->shpool, fcn); - - break; - } - - ngx_http_file_cache_delete(cache, q, name); - break; } @@ -1022,41 +1099,33 @@ ngx_http_file_cache_expire(ngx_http_file fcn->count, fcn->exists, fcn->key[0], fcn->key[1], fcn->key[2], fcn->key[3]); - if (fcn->count) { - - p = ngx_hex_dump(key, (u_char *) &fcn->node.key, - sizeof(ngx_rbtree_key_t)); - - len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t); - (void) ngx_hex_dump(p, fcn->key, len); + if (fcn->count == 0) { + ngx_http_file_cache_delete(cache, q, name); + continue; + } - /* - * abnormally exited workers may leave locked cache entries, - * and although it may be safe to remove them completely, - * we prefer to remove them from inactive queue and rbtree - * only, and to allow other leaks - */ - - ngx_queue_remove(q); - ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); - - ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, - "ignore long locked inactive cache entry %*s, count:%d", - 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count); - + if (fcn->deleting) { continue; } - if (!fcn->exists) { + p = ngx_hex_dump(key, (u_char *) &fcn->node.key, + sizeof(ngx_rbtree_key_t)); + len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t); + (void) ngx_hex_dump(p, fcn->key, len); - ngx_queue_remove(q); - ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); - ngx_slab_free_locked(cache->shpool, fcn); + /* + * abnormally exited workers may leave locked cache entries, + * and although it may be safe to remove them completely, + * we prefer to remove them from inactive queue and rbtree + * only, and to allow other leaks + */ - continue; - } + ngx_queue_remove(q); + ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); - ngx_http_file_cache_delete(cache, q, name); + ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, + "ignore long locked inactive cache entry %*s, count:%d", + 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count); } ngx_shmtx_unlock(&cache->shpool->mutex); @@ -1078,39 +1147,42 @@ ngx_http_file_cache_delete(ngx_http_file fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue); - cache->sh->size -= (fcn->length + cache->bsize - 1) / cache->bsize; - - path = cache->path; - - p = name + path->name.len + 1 + path->len; + if (fcn->exists) { + cache->sh->size -= (fcn->length + cache->bsize - 1) / cache->bsize; - p = ngx_hex_dump(p, (u_char *) &fcn->node.key, sizeof(ngx_rbtree_key_t)); + path = cache->path; + p = name + path->name.len + 1 + path->len; + p = ngx_hex_dump(p, (u_char *) &fcn->node.key, + sizeof(ngx_rbtree_key_t)); + len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t); + p = ngx_hex_dump(p, fcn->key, len); + *p = '\0'; - len = NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t); - p = ngx_hex_dump(p, fcn->key, len); - *p = '\0'; - - ngx_queue_remove(q); + fcn->count++; + fcn->deleting = 1; + ngx_shmtx_unlock(&cache->shpool->mutex); - ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); - - ngx_slab_free_locked(cache->shpool, fcn); + len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN; + ngx_create_hashed_filename(path, name, len); - ngx_shmtx_unlock(&cache->shpool->mutex); - - len = path->name.len + 1 + path->len + 2 * NGX_HTTP_CACHE_KEY_LEN; + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, + "http file cache expire: \"%s\"", name); - ngx_create_hashed_filename(path, name, len); + if (ngx_delete_file(name) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno, + ngx_delete_file_n " \"%s\" failed", name); + } - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, - "http file cache expire: \"%s\"", name); - - if (ngx_delete_file(name) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, ngx_cycle->log, ngx_errno, - ngx_delete_file_n " \"%s\" failed", name); + ngx_shmtx_lock(&cache->shpool->mutex); + fcn->count--; + fcn->deleting = 0; } - ngx_shmtx_lock(&cache->shpool->mutex); + if (fcn->count == 0) { + ngx_queue_remove(q); + ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); + ngx_slab_free_locked(cache->shpool, fcn); + } } @@ -1120,7 +1192,7 @@ ngx_http_file_cache_manager(void *data) ngx_http_file_cache_t *cache = data; off_t size; - time_t next; + time_t next, wait; next = ngx_http_file_cache_expire(cache); @@ -1141,7 +1213,11 @@ ngx_http_file_cache_manager(void *data) return next; } - next = ngx_http_file_cache_forced_expire(cache); + wait = ngx_http_file_cache_forced_expire(cache); + + if (wait > 0) { + return wait; + } if (ngx_http_file_cache_manager_sleep(cache) != NGX_OK) { return next; @@ -1203,7 +1279,7 @@ ngx_http_file_cache_manager_sleep(ngx_ht if (cache->files++ > 100) { - ngx_time_update(0, 0); + ngx_time_update(); elapsed = ngx_abs((ngx_msec_int_t) (ngx_current_msec - cache->last)); @@ -1220,7 +1296,7 @@ ngx_http_file_cache_manager_sleep(ngx_ht ngx_msleep(200); - ngx_time_update(0, 0); + ngx_time_update(); } cache->last = ngx_current_msec; @@ -1366,6 +1442,8 @@ ngx_http_file_cache_add(ngx_http_file_ca fcn->valid_msec = c->valid_msec; fcn->error = 0; fcn->exists = 1; + fcn->updating = 0; + fcn->deleting = 0; fcn->uniq = c->uniq; fcn->valid_sec = c->valid_sec; fcn->body_start = c->body_start; @@ -1679,3 +1757,69 @@ ngx_http_file_cache_valid_set_slot(ngx_c return NGX_CONF_OK; } + + +ngx_int_t +ngx_http_cache(ngx_http_request_t *r, ngx_array_t *no_cache) +{ + ngx_str_t val; + ngx_uint_t i; + ngx_http_complex_value_t *cv; + + cv = no_cache->elts; + + for (i = 0; i < no_cache->nelts; i++) { + if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) { + return NGX_ERROR; + } + + if (val.len && val.data[0] != '0') { + return NGX_DECLINED; + } + } + + return NGX_OK; +} + + +char * +ngx_http_no_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + char *p = conf; + + ngx_str_t *value; + ngx_uint_t i; + ngx_array_t **a; + ngx_http_complex_value_t *cv; + ngx_http_compile_complex_value_t ccv; + + a = (ngx_array_t **) (p + cmd->offset); + + if (*a == NGX_CONF_UNSET_PTR) { + *a = ngx_array_create(cf->pool, 1, sizeof(ngx_http_complex_value_t)); + if (*a == NULL) { + return NGX_CONF_ERROR; + } + } + + value = cf->args->elts; + + for (i = 1; i < cf->args->nelts; i++) { + cv = ngx_array_push(*a); + if (cv == NULL) { + return NGX_CONF_ERROR; + } + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[i]; + ccv.complex_value = cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + + return NGX_CONF_OK; +}