11563Svbart@nginx.com 21563Svbart@nginx.com /* 31563Svbart@nginx.com * Copyright (C) NGINX, Inc. 41563Svbart@nginx.com */ 51563Svbart@nginx.com 61563Svbart@nginx.com #include <nxt_main.h> 71563Svbart@nginx.com 81563Svbart@nginx.com 91563Svbart@nginx.com struct nxt_var_s { 101953Sz.hong@f5.com size_t length; 111953Sz.hong@f5.com nxt_uint_t vars; 121959Sz.hong@f5.com uint8_t strz; /* 1 bit */ 131953Sz.hong@f5.com u_char data[]; 141563Svbart@nginx.com 151563Svbart@nginx.com /* 161953Sz.hong@f5.com nxt_var_sub_t subs[vars]; 171953Sz.hong@f5.com u_char raw[length]; 181563Svbart@nginx.com */ 191563Svbart@nginx.com }; 201563Svbart@nginx.com 211563Svbart@nginx.com 221563Svbart@nginx.com typedef struct { 231953Sz.hong@f5.com uint32_t index; 241953Sz.hong@f5.com uint32_t length; 251953Sz.hong@f5.com uint32_t position; 261953Sz.hong@f5.com } nxt_var_sub_t; 271953Sz.hong@f5.com 281953Sz.hong@f5.com 291953Sz.hong@f5.com typedef struct { 301953Sz.hong@f5.com nxt_var_t *var; 311953Sz.hong@f5.com nxt_str_t *value; 321563Svbart@nginx.com } nxt_var_value_t; 331563Svbart@nginx.com 341563Svbart@nginx.com 351563Svbart@nginx.com struct nxt_var_query_s { 361563Svbart@nginx.com nxt_array_t values; /* of nxt_var_value_t */ 371563Svbart@nginx.com nxt_array_t parts; /* of nxt_str_t * */ 381563Svbart@nginx.com 391563Svbart@nginx.com nxt_lvlhsh_t cache; 401563Svbart@nginx.com 411563Svbart@nginx.com nxt_str_t *spare; 421563Svbart@nginx.com nxt_uint_t waiting; 431563Svbart@nginx.com nxt_uint_t failed; /* 1 bit */ 441563Svbart@nginx.com 451563Svbart@nginx.com void *ctx; 461563Svbart@nginx.com void *data; 471563Svbart@nginx.com 481563Svbart@nginx.com nxt_work_handler_t ready; 491563Svbart@nginx.com nxt_work_handler_t error; 501563Svbart@nginx.com }; 511563Svbart@nginx.com 521563Svbart@nginx.com 531953Sz.hong@f5.com #define nxt_var_subs(var) ((nxt_var_sub_t *) (var)->data) 541563Svbart@nginx.com 551953Sz.hong@f5.com #define nxt_var_raw_start(var) \ 561953Sz.hong@f5.com ((var)->data + (var)->vars * sizeof(nxt_var_sub_t)) 571563Svbart@nginx.com 581563Svbart@nginx.com 591563Svbart@nginx.com static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data); 601563Svbart@nginx.com static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name); 611563Svbart@nginx.com 621563Svbart@nginx.com static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data); 631563Svbart@nginx.com static nxt_str_t *nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index); 641563Svbart@nginx.com static nxt_int_t nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, 651563Svbart@nginx.com nxt_str_t *value, nxt_mp_t *mp); 661563Svbart@nginx.com 671563Svbart@nginx.com static u_char *nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, 681563Svbart@nginx.com nxt_bool_t *is_var); 691563Svbart@nginx.com 701563Svbart@nginx.com static void nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query); 711563Svbart@nginx.com 721563Svbart@nginx.com 731563Svbart@nginx.com static const nxt_lvlhsh_proto_t nxt_var_hash_proto nxt_aligned(64) = { 741563Svbart@nginx.com NXT_LVLHSH_DEFAULT, 751563Svbart@nginx.com nxt_var_hash_test, 761563Svbart@nginx.com nxt_lvlhsh_alloc, 771563Svbart@nginx.com nxt_lvlhsh_free, 781563Svbart@nginx.com }; 791563Svbart@nginx.com 801563Svbart@nginx.com static const nxt_lvlhsh_proto_t nxt_var_cache_proto nxt_aligned(64) = { 811563Svbart@nginx.com NXT_LVLHSH_DEFAULT, 821563Svbart@nginx.com nxt_var_cache_test, 831563Svbart@nginx.com nxt_mp_lvlhsh_alloc, 841563Svbart@nginx.com nxt_mp_lvlhsh_free, 851563Svbart@nginx.com }; 861563Svbart@nginx.com 871563Svbart@nginx.com 881563Svbart@nginx.com static nxt_lvlhsh_t nxt_var_hash; 891563Svbart@nginx.com static uint32_t nxt_var_count; 901563Svbart@nginx.com 911563Svbart@nginx.com static nxt_var_handler_t *nxt_var_index; 921563Svbart@nginx.com 931563Svbart@nginx.com 941954Sz.hong@f5.com void 951954Sz.hong@f5.com nxt_var_raw(nxt_var_t *var, nxt_str_t *str) 961954Sz.hong@f5.com { 971954Sz.hong@f5.com str->length = var->length; 981954Sz.hong@f5.com str->start = nxt_var_raw_start(var); 991954Sz.hong@f5.com } 1001954Sz.hong@f5.com 1011954Sz.hong@f5.com 1021954Sz.hong@f5.com nxt_bool_t 1031954Sz.hong@f5.com nxt_var_is_const(nxt_var_t *var) 1041954Sz.hong@f5.com { 1051954Sz.hong@f5.com return (var->vars == 0); 1061954Sz.hong@f5.com } 1071954Sz.hong@f5.com 1081954Sz.hong@f5.com 1091563Svbart@nginx.com static nxt_int_t 1101563Svbart@nginx.com nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data) 1111563Svbart@nginx.com { 1121563Svbart@nginx.com nxt_var_decl_t *decl; 1131563Svbart@nginx.com 1141563Svbart@nginx.com decl = data; 1151563Svbart@nginx.com 1161563Svbart@nginx.com return nxt_strstr_eq(&lhq->key, &decl->name) ? NXT_OK : NXT_DECLINED; 1171563Svbart@nginx.com } 1181563Svbart@nginx.com 1191563Svbart@nginx.com 1201563Svbart@nginx.com static nxt_var_decl_t * 1211563Svbart@nginx.com nxt_var_hash_find(nxt_str_t *name) 1221563Svbart@nginx.com { 1231563Svbart@nginx.com nxt_lvlhsh_query_t lhq; 1241563Svbart@nginx.com 1251563Svbart@nginx.com lhq.key_hash = nxt_djb_hash(name->start, name->length); 1261563Svbart@nginx.com lhq.key = *name; 1271563Svbart@nginx.com lhq.proto = &nxt_var_hash_proto; 1281563Svbart@nginx.com 1291563Svbart@nginx.com if (nxt_lvlhsh_find(&nxt_var_hash, &lhq) != NXT_OK) { 1301563Svbart@nginx.com return NULL; 1311563Svbart@nginx.com } 1321563Svbart@nginx.com 1331563Svbart@nginx.com return lhq.value; 1341563Svbart@nginx.com } 1351563Svbart@nginx.com 1361563Svbart@nginx.com 1371563Svbart@nginx.com static nxt_int_t 1381563Svbart@nginx.com nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data) 1391563Svbart@nginx.com { 1401563Svbart@nginx.com return NXT_OK; 1411563Svbart@nginx.com } 1421563Svbart@nginx.com 1431563Svbart@nginx.com 1441563Svbart@nginx.com static nxt_str_t * 1451563Svbart@nginx.com nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index) 1461563Svbart@nginx.com { 1471563Svbart@nginx.com nxt_lvlhsh_query_t lhq; 1481563Svbart@nginx.com 1491563Svbart@nginx.com lhq.key_hash = nxt_murmur_hash2_uint32(&index); 1501563Svbart@nginx.com lhq.key.length = sizeof(uint32_t); 1511563Svbart@nginx.com lhq.key.start = (u_char *) &index; 1521563Svbart@nginx.com lhq.proto = &nxt_var_cache_proto; 1531563Svbart@nginx.com 1541563Svbart@nginx.com if (nxt_lvlhsh_find(lh, &lhq) != NXT_OK) { 1551563Svbart@nginx.com return NULL; 1561563Svbart@nginx.com } 1571563Svbart@nginx.com 1581563Svbart@nginx.com return lhq.value; 1591563Svbart@nginx.com } 1601563Svbart@nginx.com 1611563Svbart@nginx.com 1621563Svbart@nginx.com static nxt_int_t 1631563Svbart@nginx.com nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, nxt_str_t *value, 1641563Svbart@nginx.com nxt_mp_t *mp) 1651563Svbart@nginx.com { 1661563Svbart@nginx.com nxt_lvlhsh_query_t lhq; 1671563Svbart@nginx.com 1681563Svbart@nginx.com lhq.key_hash = nxt_murmur_hash2_uint32(&index); 1691563Svbart@nginx.com lhq.replace = 0; 1701563Svbart@nginx.com lhq.key.length = sizeof(uint32_t); 1711563Svbart@nginx.com lhq.key.start = (u_char *) &index; 1721563Svbart@nginx.com lhq.value = value; 1731563Svbart@nginx.com lhq.proto = &nxt_var_cache_proto; 1741563Svbart@nginx.com lhq.pool = mp; 1751563Svbart@nginx.com 1761563Svbart@nginx.com return nxt_lvlhsh_insert(lh, &lhq); 1771563Svbart@nginx.com } 1781563Svbart@nginx.com 1791563Svbart@nginx.com 1801563Svbart@nginx.com nxt_int_t 1811563Svbart@nginx.com nxt_var_register(nxt_var_decl_t *decl, size_t n) 1821563Svbart@nginx.com { 1831563Svbart@nginx.com nxt_uint_t i; 1841563Svbart@nginx.com nxt_lvlhsh_query_t lhq; 1851563Svbart@nginx.com 1861563Svbart@nginx.com lhq.replace = 0; 1871563Svbart@nginx.com lhq.proto = &nxt_var_hash_proto; 1881563Svbart@nginx.com 1891563Svbart@nginx.com for (i = 0; i < n; i++) { 1901563Svbart@nginx.com lhq.key = decl[i].name; 1911563Svbart@nginx.com lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); 1921563Svbart@nginx.com lhq.value = &decl[i]; 1931563Svbart@nginx.com 1941563Svbart@nginx.com if (nxt_slow_path(nxt_lvlhsh_insert(&nxt_var_hash, &lhq) != NXT_OK)) { 1951563Svbart@nginx.com return NXT_ERROR; 1961563Svbart@nginx.com } 1971563Svbart@nginx.com } 1981563Svbart@nginx.com 1991563Svbart@nginx.com nxt_var_count += n; 2001563Svbart@nginx.com 2011563Svbart@nginx.com return NXT_OK; 2021563Svbart@nginx.com } 2031563Svbart@nginx.com 2041563Svbart@nginx.com 2051563Svbart@nginx.com nxt_int_t 2061563Svbart@nginx.com nxt_var_index_init(void) 2071563Svbart@nginx.com { 2081563Svbart@nginx.com nxt_uint_t i; 2091563Svbart@nginx.com nxt_var_decl_t *decl; 2101563Svbart@nginx.com nxt_var_handler_t *index; 2111563Svbart@nginx.com nxt_lvlhsh_each_t lhe; 2121563Svbart@nginx.com 2131563Svbart@nginx.com index = nxt_memalign(64, nxt_var_count * sizeof(nxt_var_handler_t)); 2141563Svbart@nginx.com if (index == NULL) { 2151563Svbart@nginx.com return NXT_ERROR; 2161563Svbart@nginx.com } 2171563Svbart@nginx.com 2181563Svbart@nginx.com nxt_lvlhsh_each_init(&lhe, &nxt_var_hash_proto); 2191563Svbart@nginx.com 2201563Svbart@nginx.com for (i = 0; i < nxt_var_count; i++) { 2211563Svbart@nginx.com decl = nxt_lvlhsh_each(&nxt_var_hash, &lhe); 2221563Svbart@nginx.com decl->index = i; 2231563Svbart@nginx.com index[i] = decl->handler; 2241563Svbart@nginx.com } 2251563Svbart@nginx.com 2261563Svbart@nginx.com nxt_var_index = index; 2271563Svbart@nginx.com 2281563Svbart@nginx.com return NXT_OK; 2291563Svbart@nginx.com } 2301563Svbart@nginx.com 2311563Svbart@nginx.com 2321563Svbart@nginx.com nxt_var_t * 2331959Sz.hong@f5.com nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp, nxt_bool_t strz) 2341563Svbart@nginx.com { 2351953Sz.hong@f5.com u_char *p, *end, *next, *src; 2361953Sz.hong@f5.com size_t size; 2371953Sz.hong@f5.com nxt_var_t *var; 2381953Sz.hong@f5.com nxt_str_t part; 2391953Sz.hong@f5.com nxt_uint_t n; 2401953Sz.hong@f5.com nxt_bool_t is_var; 2411953Sz.hong@f5.com nxt_var_sub_t *subs; 2421953Sz.hong@f5.com nxt_var_decl_t *decl; 2431563Svbart@nginx.com 2441563Svbart@nginx.com n = 0; 2451563Svbart@nginx.com 2461563Svbart@nginx.com p = str->start; 2471563Svbart@nginx.com end = p + str->length; 2481563Svbart@nginx.com 2491563Svbart@nginx.com while (p < end) { 2501563Svbart@nginx.com p = nxt_var_next_part(p, end - p, &part, &is_var); 2511563Svbart@nginx.com if (nxt_slow_path(p == NULL)) { 2521563Svbart@nginx.com return NULL; 2531563Svbart@nginx.com } 2541563Svbart@nginx.com 2551563Svbart@nginx.com if (is_var) { 2561563Svbart@nginx.com n++; 2571563Svbart@nginx.com } 2581563Svbart@nginx.com } 2591563Svbart@nginx.com 2601953Sz.hong@f5.com size = sizeof(nxt_var_t) + n * sizeof(nxt_var_sub_t) + str->length; 2611563Svbart@nginx.com 2621959Sz.hong@f5.com var = nxt_mp_get(mp, size + strz); 2631563Svbart@nginx.com if (nxt_slow_path(var == NULL)) { 2641563Svbart@nginx.com return NULL; 2651563Svbart@nginx.com } 2661563Svbart@nginx.com 2671953Sz.hong@f5.com var->length = str->length; 2681563Svbart@nginx.com var->vars = n; 2691959Sz.hong@f5.com var->strz = strz; 2701563Svbart@nginx.com 2711953Sz.hong@f5.com subs = nxt_var_subs(var); 2721953Sz.hong@f5.com src = nxt_var_raw_start(var); 2731563Svbart@nginx.com 2741953Sz.hong@f5.com nxt_memcpy(src, str->start, str->length); 2751953Sz.hong@f5.com 2761959Sz.hong@f5.com if (strz) { 2771959Sz.hong@f5.com src[str->length] = '\0'; 2781959Sz.hong@f5.com } 2791959Sz.hong@f5.com 2801563Svbart@nginx.com n = 0; 2811563Svbart@nginx.com p = str->start; 2821563Svbart@nginx.com 2831563Svbart@nginx.com while (p < end) { 2841953Sz.hong@f5.com next = nxt_var_next_part(p, end - p, &part, &is_var); 2851563Svbart@nginx.com 2861563Svbart@nginx.com if (is_var) { 2871563Svbart@nginx.com decl = nxt_var_hash_find(&part); 2881563Svbart@nginx.com if (nxt_slow_path(decl == NULL)) { 2891563Svbart@nginx.com return NULL; 2901563Svbart@nginx.com } 2911563Svbart@nginx.com 2921953Sz.hong@f5.com subs[n].index = decl->index; 2931953Sz.hong@f5.com subs[n].length = next - p; 2941953Sz.hong@f5.com subs[n].position = p - str->start; 2951563Svbart@nginx.com 2961563Svbart@nginx.com n++; 2971953Sz.hong@f5.com } 2981563Svbart@nginx.com 2991953Sz.hong@f5.com p = next; 3001563Svbart@nginx.com } 3011563Svbart@nginx.com 3021563Svbart@nginx.com return var; 3031563Svbart@nginx.com } 3041563Svbart@nginx.com 3051563Svbart@nginx.com 3061563Svbart@nginx.com nxt_int_t 3071563Svbart@nginx.com nxt_var_test(nxt_str_t *str, u_char *error) 3081563Svbart@nginx.com { 3091563Svbart@nginx.com u_char *p, *end, *next; 3101563Svbart@nginx.com nxt_str_t part; 3111563Svbart@nginx.com nxt_bool_t is_var; 3121563Svbart@nginx.com nxt_var_decl_t *decl; 3131563Svbart@nginx.com 3141563Svbart@nginx.com p = str->start; 3151563Svbart@nginx.com end = p + str->length; 3161563Svbart@nginx.com 3171563Svbart@nginx.com while (p < end) { 3181563Svbart@nginx.com next = nxt_var_next_part(p, end - p, &part, &is_var); 3191563Svbart@nginx.com 3201563Svbart@nginx.com if (next == NULL) { 3211563Svbart@nginx.com nxt_sprintf(error, error + NXT_MAX_ERROR_STR, 3221563Svbart@nginx.com "Invalid variable at position %uz%Z", p - str->start); 3231563Svbart@nginx.com 3241563Svbart@nginx.com return NXT_ERROR; 3251563Svbart@nginx.com } 3261563Svbart@nginx.com 3271563Svbart@nginx.com if (is_var) { 3281563Svbart@nginx.com decl = nxt_var_hash_find(&part); 3291563Svbart@nginx.com 3301563Svbart@nginx.com if (decl == NULL) { 3311563Svbart@nginx.com nxt_sprintf(error, error + NXT_MAX_ERROR_STR, 3321563Svbart@nginx.com "Unknown variable \"%V\"%Z", &part); 3331563Svbart@nginx.com 3341563Svbart@nginx.com return NXT_ERROR; 3351563Svbart@nginx.com } 3361563Svbart@nginx.com } 3371563Svbart@nginx.com 3381563Svbart@nginx.com p = next; 3391563Svbart@nginx.com } 3401563Svbart@nginx.com 3411563Svbart@nginx.com return NXT_OK; 3421563Svbart@nginx.com } 3431563Svbart@nginx.com 3441563Svbart@nginx.com 3451563Svbart@nginx.com static u_char * 3461563Svbart@nginx.com nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, 3471563Svbart@nginx.com nxt_bool_t *is_var) 3481563Svbart@nginx.com { 3491563Svbart@nginx.com u_char *p, *end, ch, c; 3501563Svbart@nginx.com nxt_bool_t bracket; 3511563Svbart@nginx.com 3521563Svbart@nginx.com end = start + length; 3531563Svbart@nginx.com 3541563Svbart@nginx.com p = nxt_memchr(start, '$', length); 3551563Svbart@nginx.com 3561563Svbart@nginx.com if (p == start) { 3571563Svbart@nginx.com *is_var = 1; 3581563Svbart@nginx.com 3591563Svbart@nginx.com p++; 3601563Svbart@nginx.com 3611563Svbart@nginx.com if (p == end) { 3621563Svbart@nginx.com return NULL; 3631563Svbart@nginx.com } 3641563Svbart@nginx.com 3651563Svbart@nginx.com if (*p == '{') { 3661563Svbart@nginx.com bracket = 1; 3671563Svbart@nginx.com 3681563Svbart@nginx.com if (end - p < 2) { 3691563Svbart@nginx.com return NULL; 3701563Svbart@nginx.com } 3711563Svbart@nginx.com 3721563Svbart@nginx.com p++; 3731563Svbart@nginx.com 3741563Svbart@nginx.com } else { 3751563Svbart@nginx.com bracket = 0; 3761563Svbart@nginx.com } 3771563Svbart@nginx.com 3781563Svbart@nginx.com start = p; 3791563Svbart@nginx.com 3801563Svbart@nginx.com for ( ;; ) { 3811563Svbart@nginx.com ch = *p; 3821563Svbart@nginx.com 3831563Svbart@nginx.com c = (u_char) (ch | 0x20); 3841563Svbart@nginx.com if ((c < 'a' || c > 'z') && ch != '_') { 3851563Svbart@nginx.com 3861563Svbart@nginx.com if (bracket && ch != '}') { 3871563Svbart@nginx.com return NULL; 3881563Svbart@nginx.com } 3891563Svbart@nginx.com 3901563Svbart@nginx.com break; 3911563Svbart@nginx.com } 3921563Svbart@nginx.com 3931563Svbart@nginx.com p++; 3941563Svbart@nginx.com 3951563Svbart@nginx.com if (p == end) { 3961563Svbart@nginx.com if (bracket) { 3971563Svbart@nginx.com return NULL; 3981563Svbart@nginx.com } 3991563Svbart@nginx.com 4001563Svbart@nginx.com break; 4011563Svbart@nginx.com } 4021563Svbart@nginx.com } 4031563Svbart@nginx.com 4041563Svbart@nginx.com length = p - start; 4051563Svbart@nginx.com end = p + bracket; 4061563Svbart@nginx.com 4071563Svbart@nginx.com } else { 4081563Svbart@nginx.com *is_var = 0; 4091563Svbart@nginx.com 4101563Svbart@nginx.com if (p != NULL) { 4111563Svbart@nginx.com length = p - start; 4121563Svbart@nginx.com end = p; 4131563Svbart@nginx.com } 4141563Svbart@nginx.com } 4151563Svbart@nginx.com 4161563Svbart@nginx.com part->length = length; 4171563Svbart@nginx.com part->start = start; 4181563Svbart@nginx.com 4191563Svbart@nginx.com return end; 4201563Svbart@nginx.com } 4211563Svbart@nginx.com 4221563Svbart@nginx.com 4231563Svbart@nginx.com nxt_int_t 4241563Svbart@nginx.com nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp) 4251563Svbart@nginx.com { 4261563Svbart@nginx.com nxt_var_query_t *query; 4271563Svbart@nginx.com 4281563Svbart@nginx.com query = *query_p; 4291563Svbart@nginx.com 4301563Svbart@nginx.com if (*query_p == NULL) { 4311563Svbart@nginx.com query = nxt_mp_zget(mp, sizeof(nxt_var_query_t)); 4321563Svbart@nginx.com if (nxt_slow_path(query == NULL)) { 4331563Svbart@nginx.com return NXT_ERROR; 4341563Svbart@nginx.com } 4351563Svbart@nginx.com 4361563Svbart@nginx.com nxt_array_init(&query->values, mp, sizeof(nxt_var_value_t)); 4371563Svbart@nginx.com nxt_array_init(&query->parts, mp, sizeof(nxt_str_t *)); 4381563Svbart@nginx.com 4391563Svbart@nginx.com } else { 4401563Svbart@nginx.com nxt_array_reset(&query->values); 4411563Svbart@nginx.com } 4421563Svbart@nginx.com 4431563Svbart@nginx.com query->ctx = ctx; 4441563Svbart@nginx.com 4451563Svbart@nginx.com *query_p = query; 4461563Svbart@nginx.com 4471563Svbart@nginx.com return NXT_OK; 4481563Svbart@nginx.com } 4491563Svbart@nginx.com 4501563Svbart@nginx.com 4511563Svbart@nginx.com void 4521563Svbart@nginx.com nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, 4531563Svbart@nginx.com nxt_str_t *str) 4541563Svbart@nginx.com { 4551953Sz.hong@f5.com uint32_t index; 4561953Sz.hong@f5.com nxt_mp_t *mp; 4571953Sz.hong@f5.com nxt_str_t *value; 4581953Sz.hong@f5.com nxt_int_t ret; 4591953Sz.hong@f5.com nxt_uint_t i; 4601953Sz.hong@f5.com nxt_var_sub_t *subs; 4611953Sz.hong@f5.com nxt_var_value_t *val; 4621563Svbart@nginx.com 4631954Sz.hong@f5.com if (nxt_var_is_const(var)) { 4641954Sz.hong@f5.com nxt_var_raw(var, str); 4651563Svbart@nginx.com return; 4661563Svbart@nginx.com } 4671563Svbart@nginx.com 4681563Svbart@nginx.com if (nxt_slow_path(query->failed)) { 4691563Svbart@nginx.com return; 4701563Svbart@nginx.com } 4711563Svbart@nginx.com 4721563Svbart@nginx.com mp = query->values.mem_pool; 4731953Sz.hong@f5.com subs = nxt_var_subs(var); 4741563Svbart@nginx.com value = query->spare; 4751563Svbart@nginx.com 4761563Svbart@nginx.com for (i = 0; i < var->vars; i++) { 4771563Svbart@nginx.com 4781563Svbart@nginx.com if (value == NULL) { 4791563Svbart@nginx.com value = nxt_mp_zget(mp, sizeof(nxt_str_t)); 4801563Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 4811563Svbart@nginx.com goto fail; 4821563Svbart@nginx.com } 4831563Svbart@nginx.com } 4841563Svbart@nginx.com 4851953Sz.hong@f5.com index = subs[i].index; 4861953Sz.hong@f5.com 4871953Sz.hong@f5.com ret = nxt_var_cache_add(&query->cache, index, value, mp); 4881563Svbart@nginx.com 4891563Svbart@nginx.com if (ret != NXT_OK) { 4901563Svbart@nginx.com if (nxt_slow_path(ret == NXT_ERROR)) { 4911563Svbart@nginx.com goto fail; 4921563Svbart@nginx.com } 4931563Svbart@nginx.com 4941563Svbart@nginx.com continue; /* NXT_DECLINED */ 4951563Svbart@nginx.com } 4961563Svbart@nginx.com 497*2124Sz.hong@f5.com ret = nxt_var_index[index](task, value, query->ctx); 498*2124Sz.hong@f5.com if (nxt_slow_path(ret != NXT_OK)) { 499*2124Sz.hong@f5.com goto fail; 500*2124Sz.hong@f5.com } 5011563Svbart@nginx.com 5021563Svbart@nginx.com value = NULL; 5031563Svbart@nginx.com } 5041563Svbart@nginx.com 5051563Svbart@nginx.com query->spare = value; 5061563Svbart@nginx.com 5071563Svbart@nginx.com val = nxt_array_add(&query->values); 5081563Svbart@nginx.com if (nxt_slow_path(val == NULL)) { 5091563Svbart@nginx.com goto fail; 5101563Svbart@nginx.com } 5111563Svbart@nginx.com 5121563Svbart@nginx.com val->var = var; 5131563Svbart@nginx.com val->value = str; 5141563Svbart@nginx.com 5151563Svbart@nginx.com return; 5161563Svbart@nginx.com 5171563Svbart@nginx.com fail: 5181563Svbart@nginx.com 5191563Svbart@nginx.com query->failed = 1; 5201563Svbart@nginx.com } 5211563Svbart@nginx.com 5221563Svbart@nginx.com 5231563Svbart@nginx.com void 5241563Svbart@nginx.com nxt_var_query_resolve(nxt_task_t *task, nxt_var_query_t *query, void *data, 5251563Svbart@nginx.com nxt_work_handler_t ready, nxt_work_handler_t error) 5261563Svbart@nginx.com { 5271563Svbart@nginx.com query->data = data; 5281563Svbart@nginx.com query->ready = ready; 5291563Svbart@nginx.com query->error = error; 5301563Svbart@nginx.com 5311563Svbart@nginx.com if (query->waiting == 0) { 5321563Svbart@nginx.com nxt_var_query_finish(task, query); 5331563Svbart@nginx.com } 5341563Svbart@nginx.com } 5351563Svbart@nginx.com 5361563Svbart@nginx.com 5371563Svbart@nginx.com void 5381563Svbart@nginx.com nxt_var_query_handle(nxt_task_t *task, nxt_var_query_t *query, 5391563Svbart@nginx.com nxt_bool_t failed) 5401563Svbart@nginx.com { 5411563Svbart@nginx.com query->failed |= failed; 5421563Svbart@nginx.com 5431563Svbart@nginx.com if (--query->waiting == 0) { 5441563Svbart@nginx.com nxt_var_query_finish(task, query); 5451563Svbart@nginx.com } 5461563Svbart@nginx.com } 5471563Svbart@nginx.com 5481563Svbart@nginx.com 5491563Svbart@nginx.com static void 5501563Svbart@nginx.com nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query) 5511563Svbart@nginx.com { 5521953Sz.hong@f5.com u_char *p, *src; 5531953Sz.hong@f5.com size_t length, last, next; 5541953Sz.hong@f5.com nxt_str_t *str, **part; 5551953Sz.hong@f5.com nxt_var_t *var; 5561953Sz.hong@f5.com nxt_uint_t i, j; 5571953Sz.hong@f5.com nxt_var_sub_t *subs; 5581953Sz.hong@f5.com nxt_var_value_t *val; 5591563Svbart@nginx.com 5601563Svbart@nginx.com if (query->failed) { 5611563Svbart@nginx.com goto done; 5621563Svbart@nginx.com } 5631563Svbart@nginx.com 5641563Svbart@nginx.com val = query->values.elts; 5651563Svbart@nginx.com 5661563Svbart@nginx.com for (i = 0; i < query->values.nelts; i++) { 5671563Svbart@nginx.com var = val[i].var; 5681563Svbart@nginx.com 5691953Sz.hong@f5.com subs = nxt_var_subs(var); 5701953Sz.hong@f5.com length = var->length; 5711563Svbart@nginx.com 5721563Svbart@nginx.com for (j = 0; j < var->vars; j++) { 5731953Sz.hong@f5.com str = nxt_var_cache_find(&query->cache, subs[j].index); 5741563Svbart@nginx.com 5751563Svbart@nginx.com nxt_assert(str != NULL); 5761563Svbart@nginx.com 5771563Svbart@nginx.com part = nxt_array_add(&query->parts); 5781563Svbart@nginx.com 5791563Svbart@nginx.com if (nxt_slow_path(part == NULL)) { 5801563Svbart@nginx.com query->failed = 1; 5811563Svbart@nginx.com goto done; 5821563Svbart@nginx.com } 5831563Svbart@nginx.com 5841563Svbart@nginx.com *part = str; 5851563Svbart@nginx.com 5861953Sz.hong@f5.com length += str->length - subs[j].length; 5871563Svbart@nginx.com } 5881563Svbart@nginx.com 5891959Sz.hong@f5.com p = nxt_mp_nget(query->values.mem_pool, length + var->strz); 5901563Svbart@nginx.com if (nxt_slow_path(p == NULL)) { 5911563Svbart@nginx.com query->failed = 1; 5921563Svbart@nginx.com goto done; 5931563Svbart@nginx.com } 5941563Svbart@nginx.com 5951563Svbart@nginx.com val[i].value->length = length; 5961563Svbart@nginx.com val[i].value->start = p; 5971563Svbart@nginx.com 5981563Svbart@nginx.com part = query->parts.elts; 5991953Sz.hong@f5.com src = nxt_var_raw_start(var); 6001563Svbart@nginx.com 6011953Sz.hong@f5.com last = 0; 6021563Svbart@nginx.com 6031563Svbart@nginx.com for (j = 0; j < var->vars; j++) { 6041953Sz.hong@f5.com next = subs[j].position; 6051563Svbart@nginx.com 6061953Sz.hong@f5.com if (next != last) { 6071953Sz.hong@f5.com p = nxt_cpymem(p, &src[last], next - last); 6081563Svbart@nginx.com } 6091563Svbart@nginx.com 6101563Svbart@nginx.com p = nxt_cpymem(p, part[j]->start, part[j]->length); 6111953Sz.hong@f5.com 6121953Sz.hong@f5.com last = next + subs[j].length; 6131563Svbart@nginx.com } 6141563Svbart@nginx.com 6151953Sz.hong@f5.com if (last != var->length) { 6161959Sz.hong@f5.com p = nxt_cpymem(p, &src[last], var->length - last); 6171959Sz.hong@f5.com } 6181959Sz.hong@f5.com 6191959Sz.hong@f5.com if (var->strz) { 6201959Sz.hong@f5.com *p = '\0'; 6211563Svbart@nginx.com } 6221563Svbart@nginx.com 6231563Svbart@nginx.com nxt_array_reset(&query->parts); 6241959Sz.hong@f5.com 6252052Sz.hong@f5.com nxt_debug(task, "var: \"%*s\" -> \"%V\"", var->length, src, 6262052Sz.hong@f5.com val[i].value); 6271563Svbart@nginx.com } 6281563Svbart@nginx.com 6291563Svbart@nginx.com done: 6301563Svbart@nginx.com 6311563Svbart@nginx.com nxt_work_queue_add(&task->thread->engine->fast_work_queue, 6321563Svbart@nginx.com query->failed ? query->error : query->ready, 6331563Svbart@nginx.com task, query->ctx, query->data); 6341563Svbart@nginx.com } 635