nxt_var.c (2128:1ed9f036a2df) nxt_var.c (2146:362258b173b3)
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
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
29typedef struct {
30 nxt_var_t *var;
31 nxt_str_t *value;
32} nxt_var_value_t;
33
34
35struct nxt_var_query_s {
29struct nxt_var_query_s {
36 nxt_array_t values; /* of nxt_var_value_t */
37 nxt_array_t parts; /* of nxt_str_t * */
30 nxt_mp_t *pool;
38
39 nxt_lvlhsh_t cache;
31
32 nxt_lvlhsh_t cache;
40
41 nxt_str_t *spare;
33 nxt_str_t *spare;
34
42 nxt_uint_t waiting;
43 nxt_uint_t failed; /* 1 bit */
44
45 void *ctx;
46 void *data;
47
48 nxt_work_handler_t ready;
49 nxt_work_handler_t error;

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

55#define nxt_var_raw_start(var) \
56 ((var)->data + (var)->vars * sizeof(nxt_var_sub_t))
57
58
59static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data);
60static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name);
61
62static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data);
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);
63static nxt_str_t *nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index);
64static nxt_int_t nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index,
65 nxt_str_t *value, nxt_mp_t *mp);
56static nxt_str_t *nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query,
57 uint32_t index);
66
67static u_char *nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part,
68 nxt_bool_t *is_var);
69
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
70static void nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query);
71
62
72
73static const nxt_lvlhsh_proto_t nxt_var_hash_proto nxt_aligned(64) = {
74 NXT_LVLHSH_DEFAULT,
75 nxt_var_hash_test,
76 nxt_lvlhsh_alloc,
77 nxt_lvlhsh_free,
78};
79
80static const nxt_lvlhsh_proto_t nxt_var_cache_proto nxt_aligned(64) = {

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

122static nxt_int_t
123nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data)
124{
125 return NXT_OK;
126}
127
128
129static nxt_str_t *
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 *
130nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index)
120nxt_var_cache_value(nxt_task_t *task, nxt_var_query_t *query, uint32_t index)
131{
121{
122 nxt_int_t ret;
123 nxt_str_t *value;
132 nxt_lvlhsh_query_t lhq;
133
124 nxt_lvlhsh_query_t lhq;
125
134 lhq.key_hash = nxt_murmur_hash2_uint32(&index);
135 lhq.key.length = sizeof(uint32_t);
136 lhq.key.start = (u_char *) &index;
137 lhq.proto = &nxt_var_cache_proto;
126 value = query->spare;
138
127
139 if (nxt_lvlhsh_find(lh, &lhq) != NXT_OK) {
140 return NULL;
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;
141 }
142
135 }
136
143 return lhq.value;
144}
145
146
147static nxt_int_t
148nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, nxt_str_t *value,
149 nxt_mp_t *mp)
150{
151 nxt_lvlhsh_query_t lhq;
152
153 lhq.key_hash = nxt_murmur_hash2_uint32(&index);
154 lhq.replace = 0;
155 lhq.key.length = sizeof(uint32_t);
156 lhq.key.start = (u_char *) &index;
157 lhq.value = value;
158 lhq.proto = &nxt_var_cache_proto;
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;
159 lhq.pool = mp;
143 lhq.pool = query->pool;
160
144
161 return nxt_lvlhsh_insert(lh, &lhq);
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;
162}
163
164
165nxt_int_t
166nxt_var_register(nxt_var_decl_t *decl, size_t n)
167{
168 nxt_uint_t i;
169 nxt_lvlhsh_query_t lhq;

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

427
428 query = *query_p;
429
430 if (*query_p == NULL) {
431 query = nxt_mp_zget(mp, sizeof(nxt_var_query_t));
432 if (nxt_slow_path(query == NULL)) {
433 return NXT_ERROR;
434 }
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 }
435
436 nxt_array_init(&query->values, mp, sizeof(nxt_var_value_t));
437 nxt_array_init(&query->parts, mp, sizeof(nxt_str_t *));
438
439 } else {
440 nxt_array_reset(&query->values);
441 }
442
433 }
434
435 query->pool = mp;
443 query->ctx = ctx;
444
445 *query_p = query;
446
447 return NXT_OK;
448}
449
450
451void
452nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var,
453 nxt_str_t *str)
454{
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{
455 uint32_t index;
456 nxt_mp_t *mp;
457 nxt_str_t *value;
458 nxt_int_t ret;
459 nxt_uint_t i;
460 nxt_var_sub_t *subs;
461 nxt_var_value_t *val;
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;
462
463 if (nxt_var_is_const(var)) {
464 nxt_var_raw(var, str);
465 return;
466 }
467
468 if (nxt_slow_path(query->failed)) {
469 return;
470 }
471
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
472 mp = query->values.mem_pool;
464 nxt_memzero(&parts, sizeof(nxt_array_t));
465 nxt_array_init(&parts, query->pool, sizeof(nxt_str_t *));
466
473 subs = nxt_var_subs(var);
467 subs = nxt_var_subs(var);
474 value = query->spare;
475
468
469 length = var->length;
470
476 for (i = 0; i < var->vars; i++) {
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 }
477
476
478 if (value == NULL) {
479 value = nxt_mp_zget(mp, sizeof(nxt_str_t));
480 if (nxt_slow_path(value == NULL)) {
481 goto fail;
482 }
477 part = nxt_array_add(&parts);
478 if (nxt_slow_path(part == NULL)) {
479 goto fail;
483 }
484
480 }
481
485 index = subs[i].index;
482 *part = value;
486
483
487 ret = nxt_var_cache_add(&query->cache, index, value, mp);
484 length += value->length - subs[i].length;
485 }
488
486
489 if (ret != NXT_OK) {
490 if (nxt_slow_path(ret == NXT_ERROR)) {
491 goto fail;
492 }
487 p = nxt_mp_nget(query->pool, length + var->strz);
488 if (nxt_slow_path(p == NULL)) {
489 goto fail;
490 }
493
491
494 continue; /* NXT_DECLINED */
495 }
492 str->length = length;
493 str->start = p;
496
494
497 ret = nxt_var_index[index](task, value, query->ctx);
498 if (nxt_slow_path(ret != NXT_OK)) {
499 goto fail;
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);
500 }
501
505 }
506
502 value = NULL;
507 p = nxt_cpymem(p, part[i]->start, part[i]->length);
508
509 last = next + subs[i].length;
503 }
504
510 }
511
505 query->spare = value;
512 if (last != var->length) {
513 p = nxt_cpymem(p, &src[last], var->length - last);
514 }
506
515
507 val = nxt_array_add(&query->values);
508 if (nxt_slow_path(val == NULL)) {
509 goto fail;
516 if (var->strz) {
517 *p = '\0';
510 }
511
518 }
519
512 val->var = var;
513 val->value = str;
520 nxt_debug(task, "var: \"%*s\" -> \"%V\"", length, src, str);
514
515 return;
516
517fail:
518
519 query->failed = 1;
520}
521
522
523void
524nxt_var_query_resolve(nxt_task_t *task, nxt_var_query_t *query, void *data,
525 nxt_work_handler_t ready, nxt_work_handler_t error)
526{
527 query->data = data;
528 query->ready = ready;
529 query->error = error;
530
531 if (query->waiting == 0) {
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) {
532 nxt_var_query_finish(task, query);
539 nxt_work_queue_add(&task->thread->engine->fast_work_queue,
540 query->failed ? query->error : query->ready,
541 task, query->ctx, query->data);
533 }
534}
535
536
537void
538nxt_var_query_handle(nxt_task_t *task, nxt_var_query_t *query,
539 nxt_bool_t failed)
540{
541 query->failed |= failed;
542
543 if (--query->waiting == 0) {
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) {
544 nxt_var_query_finish(task, query);
553 nxt_work_queue_add(&task->thread->engine->fast_work_queue,
554 query->failed ? query->error : query->ready,
555 task, query->ctx, query->data);
545 }
546}
556 }
557}
547
548
549static void
550nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query)
551{
552 u_char *p, *src;
553 size_t length, last, next;
554 nxt_str_t *str, **part;
555 nxt_var_t *var;
556 nxt_uint_t i, j;
557 nxt_var_sub_t *subs;
558 nxt_var_value_t *val;
559
560 if (query->failed) {
561 goto done;
562 }
563
564 val = query->values.elts;
565
566 for (i = 0; i < query->values.nelts; i++) {
567 var = val[i].var;
568
569 subs = nxt_var_subs(var);
570 length = var->length;
571
572 for (j = 0; j < var->vars; j++) {
573 str = nxt_var_cache_find(&query->cache, subs[j].index);
574
575 nxt_assert(str != NULL);
576
577 part = nxt_array_add(&query->parts);
578
579 if (nxt_slow_path(part == NULL)) {
580 query->failed = 1;
581 goto done;
582 }
583
584 *part = str;
585
586 length += str->length - subs[j].length;
587 }
588
589 p = nxt_mp_nget(query->values.mem_pool, length + var->strz);
590 if (nxt_slow_path(p == NULL)) {
591 query->failed = 1;
592 goto done;
593 }
594
595 val[i].value->length = length;
596 val[i].value->start = p;
597
598 part = query->parts.elts;
599 src = nxt_var_raw_start(var);
600
601 last = 0;
602
603 for (j = 0; j < var->vars; j++) {
604 next = subs[j].position;
605
606 if (next != last) {
607 p = nxt_cpymem(p, &src[last], next - last);
608 }
609
610 p = nxt_cpymem(p, part[j]->start, part[j]->length);
611
612 last = next + subs[j].length;
613 }
614
615 if (last != var->length) {
616 p = nxt_cpymem(p, &src[last], var->length - last);
617 }
618
619 if (var->strz) {
620 *p = '\0';
621 }
622
623 nxt_array_reset(&query->parts);
624
625 nxt_debug(task, "var: \"%*s\" -> \"%V\"", var->length, src,
626 val[i].value);
627 }
628
629done:
630
631 nxt_work_queue_add(&task->thread->engine->fast_work_queue,
632 query->failed ? query->error : query->ready,
633 task, query->ctx, query->data);
634}