summaryrefslogtreecommitdiffhomepage
path: root/src/nxt_var.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nxt_var.c')
-rw-r--r--src/nxt_var.c418
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);
}