diff options
Diffstat (limited to 'src/nxt_var.c')
-rw-r--r-- | src/nxt_var.c | 418 |
1 files changed, 235 insertions, 183 deletions
diff --git a/src/nxt_var.c b/src/nxt_var.c index 0a722d17..f55a2d30 100644 --- a/src/nxt_var.c +++ b/src/nxt_var.c @@ -9,7 +9,7 @@ struct nxt_var_s { size_t length; nxt_uint_t vars; - uint8_t strz; /* 1 bit */ + nxt_var_flags_t flags; u_char data[]; /* @@ -26,19 +26,12 @@ typedef struct { } nxt_var_sub_t; -typedef struct { - nxt_var_t *var; - nxt_str_t *value; -} nxt_var_value_t; - - struct nxt_var_query_s { - nxt_array_t values; /* of nxt_var_value_t */ - nxt_array_t parts; /* of nxt_str_t * */ + nxt_mp_t *pool; nxt_lvlhsh_t cache; - nxt_str_t *spare; + nxt_uint_t waiting; nxt_uint_t failed; /* 1 bit */ @@ -59,16 +52,18 @@ struct nxt_var_query_s { static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data); static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name); +static nxt_var_decl_t *nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields, + uint32_t *index); +static nxt_var_field_t *nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name, + uint32_t hash); + static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data); -static nxt_str_t *nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index); -static nxt_int_t nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, - nxt_str_t *value, nxt_mp_t *mp); +static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, + uint32_t index); static u_char *nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, nxt_bool_t *is_var); -static void nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query); - static const nxt_lvlhsh_proto_t nxt_var_hash_proto nxt_aligned(64) = { NXT_LVLHSH_DEFAULT, @@ -91,21 +86,6 @@ static uint32_t nxt_var_count; static nxt_var_handler_t *nxt_var_index; -void -nxt_var_raw(nxt_var_t *var, nxt_str_t *str) -{ - str->length = var->length; - str->start = nxt_var_raw_start(var); -} - - -nxt_bool_t -nxt_var_is_const(nxt_var_t *var) -{ - return (var->vars == 0); -} - - static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data) { @@ -134,46 +114,166 @@ nxt_var_hash_find(nxt_str_t *name) } -static nxt_int_t -nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data) +static nxt_var_decl_t * +nxt_var_decl_get(nxt_str_t *name, nxt_array_t *fields, uint32_t *index) { - return NXT_OK; + u_char *p, *end; + int64_t hash; + uint16_t field; + nxt_str_t str; + nxt_var_decl_t *decl; + nxt_var_field_t *f; + + f = NULL; + field = 0; + decl = nxt_var_hash_find(name); + + if (decl == NULL) { + p = name->start; + end = p + name->length; + + while (p < end) { + if (*p++ == '_') { + break; + } + } + + if (p == end) { + return NULL; + } + + str.start = name->start; + str.length = p - 1 - name->start; + + decl = nxt_var_hash_find(&str); + + if (decl != NULL) { + str.start = p; + str.length = end - p; + + hash = decl->field_hash(fields->mem_pool, &str); + if (nxt_slow_path(hash == -1)) { + return NULL; + } + + f = nxt_var_field_add(fields, &str, (uint32_t) hash); + if (nxt_slow_path(f == NULL)) { + return NULL; + } + + field = f->index; + } + } + + if (decl != NULL) { + if (decl->field_hash != NULL && f == NULL) { + return NULL; + } + + if (index != NULL) { + *index = (decl->index << 16) | field; + } + } + + return decl; } -static nxt_str_t * -nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index) +static nxt_var_field_t * +nxt_var_field_add(nxt_array_t *fields, nxt_str_t *name, uint32_t hash) { - nxt_lvlhsh_query_t lhq; + nxt_uint_t i; + nxt_var_field_t *field; - lhq.key_hash = nxt_murmur_hash2_uint32(&index); - lhq.key.length = sizeof(uint32_t); - lhq.key.start = (u_char *) &index; - lhq.proto = &nxt_var_cache_proto; + field = fields->elts; - if (nxt_lvlhsh_find(lh, &lhq) != NXT_OK) { + for (i = 0; i < fields->nelts; i++) { + if (field[i].hash == hash + && nxt_strstr_eq(&field[i].name, name)) + { + return field; + } + } + + field = nxt_array_add(fields); + if (nxt_slow_path(field == NULL)) { return NULL; } - return lhq.value; + field->name = *name; + field->hash = hash; + field->index = fields->nelts - 1; + + return field; +} + + +nxt_var_field_t * +nxt_var_field_get(nxt_array_t *fields, uint16_t index) +{ + nxt_uint_t nfields; + nxt_var_field_t *field; + + field = fields->elts; + nfields = fields->nelts; + + if (nfields > 0 && index <= nfields) { + return &field[index]; + } + + return NULL; } static nxt_int_t -nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, nxt_str_t *value, - nxt_mp_t *mp) +nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data) { + return NXT_OK; +} + + +static nxt_str_t * +nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index) +{ + nxt_int_t ret; + nxt_str_t *value; nxt_lvlhsh_query_t lhq; + value = query->spare; + + if (value == NULL) { + value = nxt_mp_zget(query->pool, sizeof(nxt_str_t)); + if (nxt_slow_path(value == NULL)) { + return NULL; + } + + query->spare = value; + } + lhq.key_hash = nxt_murmur_hash2_uint32(&index); lhq.replace = 0; lhq.key.length = sizeof(uint32_t); lhq.key.start = (u_char *) &index; lhq.value = value; lhq.proto = &nxt_var_cache_proto; - lhq.pool = mp; + lhq.pool = query->pool; - return nxt_lvlhsh_insert(lh, &lhq); + ret = nxt_lvlhsh_insert(&query->cache, &lhq); + if (nxt_slow_path(ret == NXT_ERROR)) { + return NULL; + } + + if (ret == NXT_OK) { + ret = nxt_var_index[index >> 16](task, value, query->ctx, + index & 0xffff); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + + query->spare = NULL; + } + + return lhq.value; } @@ -230,10 +330,13 @@ nxt_var_index_init(void) nxt_var_t * -nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz) +nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_array_t *fields, + nxt_var_flags_t flags) { u_char *p, *end, *next, *src; size_t size; + uint32_t index; + nxt_bool_t strz; nxt_var_t *var; nxt_str_t part; nxt_uint_t n; @@ -241,6 +344,8 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz) nxt_var_sub_t *subs; nxt_var_decl_t *decl; + strz = (flags & NXT_VAR_STRZ) != 0; + n = 0; p = str->start; @@ -266,7 +371,7 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz) var->length = str->length; var->vars = n; - var->strz = strz; + var->flags = flags; subs = nxt_var_subs(var); src = nxt_var_raw_start(var); @@ -284,12 +389,12 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz) next = nxt_var_next_part(p, end - p, &part, &is_var); if (is_var) { - decl = nxt_var_hash_find(&part); + decl = nxt_var_decl_get(&part, fields, &index); if (nxt_slow_path(decl == NULL)) { return NULL; } - subs[n].index = decl->index; + subs[n].index = index; subs[n].length = next - p; subs[n].position = p - str->start; @@ -304,7 +409,7 @@ nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz) nxt_int_t -nxt_var_test(nxt_str_t *str, u_char *error) +nxt_var_test(nxt_str_t *str, nxt_array_t *fields, u_char *error) { u_char *p, *end, *next; nxt_str_t part; @@ -325,7 +430,7 @@ nxt_var_test(nxt_str_t *str, u_char *error) } if (is_var) { - decl = nxt_var_hash_find(&part); + decl = nxt_var_decl_get(&part, fields, NULL); if (decl == NULL) { nxt_sprintf(error, error + NXT_MAX_ERROR_STR, @@ -420,6 +525,21 @@ nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, } +inline void +nxt_var_raw(nxt_var_t *var, nxt_str_t *str) +{ + str->length = var->length; + str->start = nxt_var_raw_start(var); +} + + +inline nxt_bool_t +nxt_var_is_const(nxt_var_t *var) +{ + return (var->vars == 0); +} + + nxt_int_t nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp) { @@ -432,14 +552,9 @@ nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp) if (nxt_slow_path(query == NULL)) { return NXT_ERROR; } - - nxt_array_init(&query->values, mp, sizeof(nxt_var_value_t)); - nxt_array_init(&query->parts, mp, sizeof(nxt_str_t *)); - - } else { - nxt_array_reset(&query->values); } + query->pool = mp; query->ctx = ctx; *query_p = query; @@ -452,13 +567,13 @@ void nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, nxt_str_t *str) { - uint32_t index; - nxt_mp_t *mp; - nxt_str_t *value; - nxt_int_t ret; - nxt_uint_t i; - nxt_var_sub_t *subs; - nxt_var_value_t *val; + u_char *p, *src; + size_t length, last, next; + nxt_str_t *value, **part; + nxt_uint_t i; + nxt_bool_t strz, logging; + nxt_array_t parts; + nxt_var_sub_t *subs; if (nxt_var_is_const(var)) { nxt_var_raw(var, str); @@ -469,53 +584,74 @@ nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, return; } - mp = query->values.mem_pool; + nxt_memzero(&parts, sizeof(nxt_array_t)); + nxt_array_init(&parts, query->pool, sizeof(nxt_str_t *)); + + strz = (var->flags & NXT_VAR_STRZ) != 0; + logging = (var->flags & NXT_VAR_LOGGING) != 0; + subs = nxt_var_subs(var); - value = query->spare; - for (i = 0; i < var->vars; i++) { + length = var->length; - if (value == NULL) { - value = nxt_mp_zget(mp, sizeof(nxt_str_t)); - if (nxt_slow_path(value == NULL)) { - goto fail; - } + for (i = 0; i < var->vars; i++) { + value = nxt_var_cache_value(task, query, subs[i].index); + if (nxt_slow_path(value == NULL)) { + goto fail; } - index = subs[i].index; + part = nxt_array_add(&parts); + if (nxt_slow_path(part == NULL)) { + goto fail; + } - ret = nxt_var_cache_add(&query->cache, index, value, mp); + *part = value; - if (ret != NXT_OK) { - if (nxt_slow_path(ret == NXT_ERROR)) { - goto fail; - } + length += value->length - subs[i].length; - continue; /* NXT_DECLINED */ + if (logging && value->start == NULL) { + length += 1; } + } - ret = nxt_var_index[index](task, query, value, query->ctx); + p = nxt_mp_nget(query->pool, length + strz); + if (nxt_slow_path(p == NULL)) { + goto fail; + } - value = NULL; + str->length = length; + str->start = p; - if (ret != NXT_OK) { - if (nxt_slow_path(ret != NXT_AGAIN)) { - goto fail; - } + part = parts.elts; + src = nxt_var_raw_start(var); + + last = 0; - query->waiting++; + for (i = 0; i < var->vars; i++) { + next = subs[i].position; + + if (next != last) { + p = nxt_cpymem(p, &src[last], next - last); } + + p = nxt_cpymem(p, part[i]->start, part[i]->length); + + if (logging && part[i]->start == NULL) { + *p++ = '-'; + } + + last = next + subs[i].length; } - query->spare = value; + if (last != var->length) { + p = nxt_cpymem(p, &src[last], var->length - last); + } - val = nxt_array_add(&query->values); - if (nxt_slow_path(val == NULL)) { - goto fail; + if (strz) { + *p = '\0'; } - val->var = var; - val->value = str; + nxt_debug(task, "var: \"%*s\" -> \"%V\"", length, src, str); return; @@ -534,7 +670,9 @@ nxt_var_query_resolve(nxt_task_t *task, nxt_var_query_t *query, void *data, query->error = error; if (query->waiting == 0) { - nxt_var_query_finish(task, query); + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + query->failed ? query->error : query->ready, + task, query->ctx, query->data); } } @@ -546,94 +684,8 @@ nxt_var_query_handle(nxt_task_t *task, nxt_var_query_t *query, query->failed |= failed; if (--query->waiting == 0) { - nxt_var_query_finish(task, query); - } -} - - -static void -nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query) -{ - u_char *p, *src; - size_t length, last, next; - nxt_str_t *str, **part; - nxt_var_t *var; - nxt_uint_t i, j; - nxt_var_sub_t *subs; - nxt_var_value_t *val; - - if (query->failed) { - goto done; + nxt_work_queue_add(&task->thread->engine->fast_work_queue, + query->failed ? query->error : query->ready, + task, query->ctx, query->data); } - - val = query->values.elts; - - for (i = 0; i < query->values.nelts; i++) { - var = val[i].var; - - subs = nxt_var_subs(var); - length = var->length; - - for (j = 0; j < var->vars; j++) { - str = nxt_var_cache_find(&query->cache, subs[j].index); - - nxt_assert(str != NULL); - - part = nxt_array_add(&query->parts); - - if (nxt_slow_path(part == NULL)) { - query->failed = 1; - goto done; - } - - *part = str; - - length += str->length - subs[j].length; - } - - p = nxt_mp_nget(query->values.mem_pool, length + var->strz); - if (nxt_slow_path(p == NULL)) { - query->failed = 1; - goto done; - } - - val[i].value->length = length; - val[i].value->start = p; - - part = query->parts.elts; - src = nxt_var_raw_start(var); - - last = 0; - - for (j = 0; j < var->vars; j++) { - next = subs[j].position; - - if (next != last) { - p = nxt_cpymem(p, &src[last], next - last); - } - - p = nxt_cpymem(p, part[j]->start, part[j]->length); - - last = next + subs[j].length; - } - - if (last != var->length) { - p = nxt_cpymem(p, &src[last], var->length - last); - } - - if (var->strz) { - *p = '\0'; - } - - nxt_array_reset(&query->parts); - - nxt_debug(task, "var: \"%*s\" -> \"%V\"", var->length, src, - val[i].value); - } - -done: - - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - query->failed ? query->error : query->ready, - task, query->ctx, query->data); } |