Deleted Added
1
2/*
3 * Copyright (C) NGINX, Inc.
4 */
5
6#include <nxt_main.h>
7
8

--- 12 unchanged lines hidden (view full) ---

21
22typedef struct {
23 uint32_t index;
24 uint32_t length;
25 uint32_t position;
26} nxt_var_sub_t;
27
28
29struct nxt_var_query_s {
30 nxt_mp_t *pool;
31
32 nxt_lvlhsh_t cache;
33 nxt_str_t *spare;
34
35 nxt_uint_t waiting;
36 nxt_uint_t failed; /* 1 bit */
37
38 void *ctx;
39 void *data;
40
41 nxt_work_handler_t ready;
42 nxt_work_handler_t error;

--- 5 unchanged lines hidden (view full) ---

48#define nxt_var_raw_start(var) \
49 ((var)->data + (var)->vars * sizeof(nxt_var_sub_t))
50
51
52static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
53static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name);
54
55static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data);
56static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query,
57 uint32_t index);
58
59static u_char *nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part,
60 nxt_bool_t *is_var);
61
62
63static const nxt_lvlhsh_proto_t nxt_var_hash_proto nxt_aligned(64) = {
64 NXT_LVLHSH_DEFAULT,
65 nxt_var_hash_test,
66 nxt_lvlhsh_alloc,
67 nxt_lvlhsh_free,
68};
69
70static const nxt_lvlhsh_proto_t nxt_var_cache_proto nxt_aligned(64) = {

--- 41 unchanged lines hidden (view full) ---

112static nxt_int_t
113nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data)
114{
115 return NXT_OK;
116}
117
118
119static nxt_str_t *
120nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index)
121{
122 nxt_int_t ret;
123 nxt_str_t *value;
124 nxt_lvlhsh_query_t lhq;
125
126 value = query->spare;
127
128 if (value == NULL) {
129 value = nxt_mp_zget(query->pool, sizeof(nxt_str_t));
130 if (nxt_slow_path(value == NULL)) {
131 return NULL;
132 }
133
134 query->spare = value;
135 }
136
137 lhq.key_hash = nxt_murmur_hash2_uint32(&index);
138 lhq.replace = 0;
139 lhq.key.length = sizeof(uint32_t);
140 lhq.key.start = (u_char *) &index;
141 lhq.value = value;
142 lhq.proto = &nxt_var_cache_proto;
143 lhq.pool = query->pool;
144
145 ret = nxt_lvlhsh_insert(&query->cache, &lhq);
146 if (nxt_slow_path(ret == NXT_ERROR)) {
147 return NULL;
148 }
149
150 if (ret == NXT_OK) {
151 ret = nxt_var_index[index](task, value, query->ctx);
152 if (nxt_slow_path(ret != NXT_OK)) {
153 return NULL;
154 }
155
156 query->spare = NULL;
157 }
158
159 return lhq.value;
160}
161
162
163nxt_int_t
164nxt_var_register(nxt_var_decl_t *decl, size_t n)
165{
166 nxt_uint_t i;
167 nxt_lvlhsh_query_t lhq;

--- 257 unchanged lines hidden (view full) ---

425
426 query = *query_p;
427
428 if (*query_p == NULL) {
429 query = nxt_mp_zget(mp, sizeof(nxt_var_query_t));
430 if (nxt_slow_path(query == NULL)) {
431 return NXT_ERROR;
432 }
433 }
434
435 query->pool = mp;
436 query->ctx = ctx;
437
438 *query_p = query;
439
440 return NXT_OK;
441}
442
443
444void
445nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var,
446 nxt_str_t *str)
447{
448 u_char *p, *src;
449 size_t length, last, next;
450 nxt_str_t *value, **part;
451 nxt_uint_t i;
452 nxt_array_t parts;
453 nxt_var_sub_t *subs;
454
455 if (nxt_var_is_const(var)) {
456 nxt_var_raw(var, str);
457 return;
458 }
459
460 if (nxt_slow_path(query->failed)) {
461 return;
462 }
463
464 nxt_memzero(&parts, sizeof(nxt_array_t));
465 nxt_array_init(&parts, query->pool, sizeof(nxt_str_t *));
466
467 subs = nxt_var_subs(var);
468
469 length = var->length;
470
471 for (i = 0; i < var->vars; i++) {
472 value = nxt_var_cache_value(task, query, subs[i].index);
473 if (nxt_slow_path(value == NULL)) {
474 goto fail;
475 }
476
477 part = nxt_array_add(&parts);
478 if (nxt_slow_path(part == NULL)) {
479 goto fail;
480 }
481
482 *part = value;
483
484 length += value->length - subs[i].length;
485 }
486
487 p = nxt_mp_nget(query->pool, length + var->strz);
488 if (nxt_slow_path(p == NULL)) {
489 goto fail;
490 }
491
492 str->length = length;
493 str->start = p;
494
495 part = parts.elts;
496 src = nxt_var_raw_start(var);
497
498 last = 0;
499
500 for (i = 0; i < var->vars; i++) {
501 next = subs[i].position;
502
503 if (next != last) {
504 p = nxt_cpymem(p, &src[last], next - last);
505 }
506
507 p = nxt_cpymem(p, part[i]->start, part[i]->length);
508
509 last = next + subs[i].length;
510 }
511
512 if (last != var->length) {
513 p = nxt_cpymem(p, &src[last], var->length - last);
514 }
515
516 if (var->strz) {
517 *p = '\0';
518 }
519
520 nxt_debug(task, "var: \"%*s\" -> \"%V\"", length, src, str);
521
522 return;
523
524fail:
525
526 query->failed = 1;
527}
528
529
530void
531nxt_var_query_resolve(nxt_task_t *task, nxt_var_query_t *query, void *data,
532 nxt_work_handler_t ready, nxt_work_handler_t error)
533{
534 query->data = data;
535 query->ready = ready;
536 query->error = error;
537
538 if (query->waiting == 0) {
539 nxt_work_queue_add(&task->thread->engine->fast_work_queue,
540 query->failed ? query->error : query->ready,
541 task, query->ctx, query->data);
542 }
543}
544
545
546void
547nxt_var_query_handle(nxt_task_t *task, nxt_var_query_t *query,
548 nxt_bool_t failed)
549{
550 query->failed |= failed;
551
552 if (--query->waiting == 0) {
553 nxt_work_queue_add(&task->thread->engine->fast_work_queue,
554 query->failed ? query->error : query->ready,
555 task, query->ctx, query->data);
556 }
557}