1*1563Svbart@nginx.com 2*1563Svbart@nginx.com /* 3*1563Svbart@nginx.com * Copyright (C) NGINX, Inc. 4*1563Svbart@nginx.com */ 5*1563Svbart@nginx.com 6*1563Svbart@nginx.com #include <nxt_main.h> 7*1563Svbart@nginx.com 8*1563Svbart@nginx.com 9*1563Svbart@nginx.com struct nxt_var_s { 10*1563Svbart@nginx.com size_t plain; 11*1563Svbart@nginx.com nxt_uint_t vars; 12*1563Svbart@nginx.com u_char data[]; 13*1563Svbart@nginx.com 14*1563Svbart@nginx.com /* 15*1563Svbart@nginx.com uint32_t indexes[vars]; 16*1563Svbart@nginx.com size_t positions[vars]; 17*1563Svbart@nginx.com u_char chars[plain]; 18*1563Svbart@nginx.com */ 19*1563Svbart@nginx.com }; 20*1563Svbart@nginx.com 21*1563Svbart@nginx.com 22*1563Svbart@nginx.com typedef struct { 23*1563Svbart@nginx.com nxt_var_t *var; 24*1563Svbart@nginx.com nxt_str_t *value; 25*1563Svbart@nginx.com } nxt_var_value_t; 26*1563Svbart@nginx.com 27*1563Svbart@nginx.com 28*1563Svbart@nginx.com struct nxt_var_query_s { 29*1563Svbart@nginx.com nxt_array_t values; /* of nxt_var_value_t */ 30*1563Svbart@nginx.com nxt_array_t parts; /* of nxt_str_t * */ 31*1563Svbart@nginx.com 32*1563Svbart@nginx.com nxt_lvlhsh_t cache; 33*1563Svbart@nginx.com 34*1563Svbart@nginx.com nxt_str_t *spare; 35*1563Svbart@nginx.com nxt_uint_t waiting; 36*1563Svbart@nginx.com nxt_uint_t failed; /* 1 bit */ 37*1563Svbart@nginx.com 38*1563Svbart@nginx.com void *ctx; 39*1563Svbart@nginx.com void *data; 40*1563Svbart@nginx.com 41*1563Svbart@nginx.com nxt_work_handler_t ready; 42*1563Svbart@nginx.com nxt_work_handler_t error; 43*1563Svbart@nginx.com }; 44*1563Svbart@nginx.com 45*1563Svbart@nginx.com 46*1563Svbart@nginx.com #define nxt_var_indexes(var) ((uint32_t *) (var)->data) 47*1563Svbart@nginx.com 48*1563Svbart@nginx.com #define nxt_var_positions(var) \ 49*1563Svbart@nginx.com ((size_t *) ((var)->data + (var)->vars * sizeof(uint32_t))) 50*1563Svbart@nginx.com 51*1563Svbart@nginx.com #define nxt_var_plain_start(var) \ 52*1563Svbart@nginx.com ((var)->data + (var)->vars * (sizeof(uint32_t) + sizeof(size_t))) 53*1563Svbart@nginx.com 54*1563Svbart@nginx.com 55*1563Svbart@nginx.com static nxt_int_t nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data); 56*1563Svbart@nginx.com static nxt_var_decl_t *nxt_var_hash_find(nxt_str_t *name); 57*1563Svbart@nginx.com 58*1563Svbart@nginx.com static nxt_int_t nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data); 59*1563Svbart@nginx.com static nxt_str_t *nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index); 60*1563Svbart@nginx.com static nxt_int_t nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, 61*1563Svbart@nginx.com nxt_str_t *value, nxt_mp_t *mp); 62*1563Svbart@nginx.com 63*1563Svbart@nginx.com static u_char *nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, 64*1563Svbart@nginx.com nxt_bool_t *is_var); 65*1563Svbart@nginx.com 66*1563Svbart@nginx.com static void nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query); 67*1563Svbart@nginx.com 68*1563Svbart@nginx.com 69*1563Svbart@nginx.com static const nxt_lvlhsh_proto_t nxt_var_hash_proto nxt_aligned(64) = { 70*1563Svbart@nginx.com NXT_LVLHSH_DEFAULT, 71*1563Svbart@nginx.com nxt_var_hash_test, 72*1563Svbart@nginx.com nxt_lvlhsh_alloc, 73*1563Svbart@nginx.com nxt_lvlhsh_free, 74*1563Svbart@nginx.com }; 75*1563Svbart@nginx.com 76*1563Svbart@nginx.com static const nxt_lvlhsh_proto_t nxt_var_cache_proto nxt_aligned(64) = { 77*1563Svbart@nginx.com NXT_LVLHSH_DEFAULT, 78*1563Svbart@nginx.com nxt_var_cache_test, 79*1563Svbart@nginx.com nxt_mp_lvlhsh_alloc, 80*1563Svbart@nginx.com nxt_mp_lvlhsh_free, 81*1563Svbart@nginx.com }; 82*1563Svbart@nginx.com 83*1563Svbart@nginx.com 84*1563Svbart@nginx.com static nxt_lvlhsh_t nxt_var_hash; 85*1563Svbart@nginx.com static uint32_t nxt_var_count; 86*1563Svbart@nginx.com 87*1563Svbart@nginx.com static nxt_var_handler_t *nxt_var_index; 88*1563Svbart@nginx.com 89*1563Svbart@nginx.com 90*1563Svbart@nginx.com static nxt_int_t 91*1563Svbart@nginx.com nxt_var_hash_test(nxt_lvlhsh_query_t *lhq, void *data) 92*1563Svbart@nginx.com { 93*1563Svbart@nginx.com nxt_var_decl_t *decl; 94*1563Svbart@nginx.com 95*1563Svbart@nginx.com decl = data; 96*1563Svbart@nginx.com 97*1563Svbart@nginx.com return nxt_strstr_eq(&lhq->key, &decl->name) ? NXT_OK : NXT_DECLINED; 98*1563Svbart@nginx.com } 99*1563Svbart@nginx.com 100*1563Svbart@nginx.com 101*1563Svbart@nginx.com static nxt_var_decl_t * 102*1563Svbart@nginx.com nxt_var_hash_find(nxt_str_t *name) 103*1563Svbart@nginx.com { 104*1563Svbart@nginx.com nxt_lvlhsh_query_t lhq; 105*1563Svbart@nginx.com 106*1563Svbart@nginx.com lhq.key_hash = nxt_djb_hash(name->start, name->length); 107*1563Svbart@nginx.com lhq.key = *name; 108*1563Svbart@nginx.com lhq.proto = &nxt_var_hash_proto; 109*1563Svbart@nginx.com 110*1563Svbart@nginx.com if (nxt_lvlhsh_find(&nxt_var_hash, &lhq) != NXT_OK) { 111*1563Svbart@nginx.com return NULL; 112*1563Svbart@nginx.com } 113*1563Svbart@nginx.com 114*1563Svbart@nginx.com return lhq.value; 115*1563Svbart@nginx.com } 116*1563Svbart@nginx.com 117*1563Svbart@nginx.com 118*1563Svbart@nginx.com static nxt_int_t 119*1563Svbart@nginx.com nxt_var_cache_test(nxt_lvlhsh_query_t *lhq, void *data) 120*1563Svbart@nginx.com { 121*1563Svbart@nginx.com return NXT_OK; 122*1563Svbart@nginx.com } 123*1563Svbart@nginx.com 124*1563Svbart@nginx.com 125*1563Svbart@nginx.com static nxt_str_t * 126*1563Svbart@nginx.com nxt_var_cache_find(nxt_lvlhsh_t *lh, uint32_t index) 127*1563Svbart@nginx.com { 128*1563Svbart@nginx.com nxt_lvlhsh_query_t lhq; 129*1563Svbart@nginx.com 130*1563Svbart@nginx.com lhq.key_hash = nxt_murmur_hash2_uint32(&index); 131*1563Svbart@nginx.com lhq.key.length = sizeof(uint32_t); 132*1563Svbart@nginx.com lhq.key.start = (u_char *) &index; 133*1563Svbart@nginx.com lhq.proto = &nxt_var_cache_proto; 134*1563Svbart@nginx.com 135*1563Svbart@nginx.com if (nxt_lvlhsh_find(lh, &lhq) != NXT_OK) { 136*1563Svbart@nginx.com return NULL; 137*1563Svbart@nginx.com } 138*1563Svbart@nginx.com 139*1563Svbart@nginx.com return lhq.value; 140*1563Svbart@nginx.com } 141*1563Svbart@nginx.com 142*1563Svbart@nginx.com 143*1563Svbart@nginx.com static nxt_int_t 144*1563Svbart@nginx.com nxt_var_cache_add(nxt_lvlhsh_t *lh, uint32_t index, nxt_str_t *value, 145*1563Svbart@nginx.com nxt_mp_t *mp) 146*1563Svbart@nginx.com { 147*1563Svbart@nginx.com nxt_lvlhsh_query_t lhq; 148*1563Svbart@nginx.com 149*1563Svbart@nginx.com lhq.key_hash = nxt_murmur_hash2_uint32(&index); 150*1563Svbart@nginx.com lhq.replace = 0; 151*1563Svbart@nginx.com lhq.key.length = sizeof(uint32_t); 152*1563Svbart@nginx.com lhq.key.start = (u_char *) &index; 153*1563Svbart@nginx.com lhq.value = value; 154*1563Svbart@nginx.com lhq.proto = &nxt_var_cache_proto; 155*1563Svbart@nginx.com lhq.pool = mp; 156*1563Svbart@nginx.com 157*1563Svbart@nginx.com return nxt_lvlhsh_insert(lh, &lhq); 158*1563Svbart@nginx.com } 159*1563Svbart@nginx.com 160*1563Svbart@nginx.com 161*1563Svbart@nginx.com nxt_int_t 162*1563Svbart@nginx.com nxt_var_register(nxt_var_decl_t *decl, size_t n) 163*1563Svbart@nginx.com { 164*1563Svbart@nginx.com nxt_uint_t i; 165*1563Svbart@nginx.com nxt_lvlhsh_query_t lhq; 166*1563Svbart@nginx.com 167*1563Svbart@nginx.com lhq.replace = 0; 168*1563Svbart@nginx.com lhq.proto = &nxt_var_hash_proto; 169*1563Svbart@nginx.com 170*1563Svbart@nginx.com for (i = 0; i < n; i++) { 171*1563Svbart@nginx.com lhq.key = decl[i].name; 172*1563Svbart@nginx.com lhq.key_hash = nxt_djb_hash(lhq.key.start, lhq.key.length); 173*1563Svbart@nginx.com lhq.value = &decl[i]; 174*1563Svbart@nginx.com 175*1563Svbart@nginx.com if (nxt_slow_path(nxt_lvlhsh_insert(&nxt_var_hash, &lhq) != NXT_OK)) { 176*1563Svbart@nginx.com return NXT_ERROR; 177*1563Svbart@nginx.com } 178*1563Svbart@nginx.com } 179*1563Svbart@nginx.com 180*1563Svbart@nginx.com nxt_var_count += n; 181*1563Svbart@nginx.com 182*1563Svbart@nginx.com return NXT_OK; 183*1563Svbart@nginx.com } 184*1563Svbart@nginx.com 185*1563Svbart@nginx.com 186*1563Svbart@nginx.com nxt_int_t 187*1563Svbart@nginx.com nxt_var_index_init(void) 188*1563Svbart@nginx.com { 189*1563Svbart@nginx.com nxt_uint_t i; 190*1563Svbart@nginx.com nxt_var_decl_t *decl; 191*1563Svbart@nginx.com nxt_var_handler_t *index; 192*1563Svbart@nginx.com nxt_lvlhsh_each_t lhe; 193*1563Svbart@nginx.com 194*1563Svbart@nginx.com index = nxt_memalign(64, nxt_var_count * sizeof(nxt_var_handler_t)); 195*1563Svbart@nginx.com if (index == NULL) { 196*1563Svbart@nginx.com return NXT_ERROR; 197*1563Svbart@nginx.com } 198*1563Svbart@nginx.com 199*1563Svbart@nginx.com nxt_lvlhsh_each_init(&lhe, &nxt_var_hash_proto); 200*1563Svbart@nginx.com 201*1563Svbart@nginx.com for (i = 0; i < nxt_var_count; i++) { 202*1563Svbart@nginx.com decl = nxt_lvlhsh_each(&nxt_var_hash, &lhe); 203*1563Svbart@nginx.com decl->index = i; 204*1563Svbart@nginx.com index[i] = decl->handler; 205*1563Svbart@nginx.com } 206*1563Svbart@nginx.com 207*1563Svbart@nginx.com nxt_var_index = index; 208*1563Svbart@nginx.com 209*1563Svbart@nginx.com return NXT_OK; 210*1563Svbart@nginx.com } 211*1563Svbart@nginx.com 212*1563Svbart@nginx.com 213*1563Svbart@nginx.com nxt_var_t * 214*1563Svbart@nginx.com nxt_var_compile(nxt_str_t *str, nxt_mp_t *mp) 215*1563Svbart@nginx.com { 216*1563Svbart@nginx.com u_char *p, *end, *plain_pos; 217*1563Svbart@nginx.com size_t plain, size, *positions; 218*1563Svbart@nginx.com uint32_t *indexes; 219*1563Svbart@nginx.com nxt_var_t *var; 220*1563Svbart@nginx.com nxt_str_t part; 221*1563Svbart@nginx.com nxt_uint_t n; 222*1563Svbart@nginx.com nxt_bool_t is_var; 223*1563Svbart@nginx.com nxt_var_decl_t *decl; 224*1563Svbart@nginx.com 225*1563Svbart@nginx.com plain = 0; 226*1563Svbart@nginx.com n = 0; 227*1563Svbart@nginx.com 228*1563Svbart@nginx.com p = str->start; 229*1563Svbart@nginx.com end = p + str->length; 230*1563Svbart@nginx.com 231*1563Svbart@nginx.com while (p < end) { 232*1563Svbart@nginx.com p = nxt_var_next_part(p, end - p, &part, &is_var); 233*1563Svbart@nginx.com 234*1563Svbart@nginx.com if (nxt_slow_path(p == NULL)) { 235*1563Svbart@nginx.com return NULL; 236*1563Svbart@nginx.com } 237*1563Svbart@nginx.com 238*1563Svbart@nginx.com if (is_var) { 239*1563Svbart@nginx.com n++; 240*1563Svbart@nginx.com 241*1563Svbart@nginx.com } else { 242*1563Svbart@nginx.com plain += part.length; 243*1563Svbart@nginx.com } 244*1563Svbart@nginx.com } 245*1563Svbart@nginx.com 246*1563Svbart@nginx.com size = sizeof(nxt_var_t) 247*1563Svbart@nginx.com + n * (sizeof(nxt_var_handler_t) + sizeof (size_t)) 248*1563Svbart@nginx.com + plain; 249*1563Svbart@nginx.com 250*1563Svbart@nginx.com var = nxt_mp_get(mp, size); 251*1563Svbart@nginx.com if (nxt_slow_path(var == NULL)) { 252*1563Svbart@nginx.com return NULL; 253*1563Svbart@nginx.com } 254*1563Svbart@nginx.com 255*1563Svbart@nginx.com var->plain = plain; 256*1563Svbart@nginx.com var->vars = n; 257*1563Svbart@nginx.com 258*1563Svbart@nginx.com indexes = nxt_var_indexes(var); 259*1563Svbart@nginx.com positions = nxt_var_positions(var); 260*1563Svbart@nginx.com plain_pos = nxt_var_plain_start(var); 261*1563Svbart@nginx.com 262*1563Svbart@nginx.com plain = 0; 263*1563Svbart@nginx.com n = 0; 264*1563Svbart@nginx.com 265*1563Svbart@nginx.com p = str->start; 266*1563Svbart@nginx.com 267*1563Svbart@nginx.com while (p < end) { 268*1563Svbart@nginx.com p = nxt_var_next_part(p, end - p, &part, &is_var); 269*1563Svbart@nginx.com 270*1563Svbart@nginx.com if (is_var) { 271*1563Svbart@nginx.com decl = nxt_var_hash_find(&part); 272*1563Svbart@nginx.com 273*1563Svbart@nginx.com if (nxt_slow_path(decl == NULL)) { 274*1563Svbart@nginx.com return NULL; 275*1563Svbart@nginx.com } 276*1563Svbart@nginx.com 277*1563Svbart@nginx.com indexes[n] = decl->index; 278*1563Svbart@nginx.com positions[n] = plain; 279*1563Svbart@nginx.com 280*1563Svbart@nginx.com n++; 281*1563Svbart@nginx.com 282*1563Svbart@nginx.com } else { 283*1563Svbart@nginx.com plain_pos = nxt_cpymem(plain_pos, part.start, part.length); 284*1563Svbart@nginx.com plain += part.length; 285*1563Svbart@nginx.com } 286*1563Svbart@nginx.com } 287*1563Svbart@nginx.com 288*1563Svbart@nginx.com return var; 289*1563Svbart@nginx.com } 290*1563Svbart@nginx.com 291*1563Svbart@nginx.com 292*1563Svbart@nginx.com nxt_int_t 293*1563Svbart@nginx.com nxt_var_test(nxt_str_t *str, u_char *error) 294*1563Svbart@nginx.com { 295*1563Svbart@nginx.com u_char *p, *end, *next; 296*1563Svbart@nginx.com nxt_str_t part; 297*1563Svbart@nginx.com nxt_bool_t is_var; 298*1563Svbart@nginx.com nxt_var_decl_t *decl; 299*1563Svbart@nginx.com 300*1563Svbart@nginx.com p = str->start; 301*1563Svbart@nginx.com end = p + str->length; 302*1563Svbart@nginx.com 303*1563Svbart@nginx.com while (p < end) { 304*1563Svbart@nginx.com next = nxt_var_next_part(p, end - p, &part, &is_var); 305*1563Svbart@nginx.com 306*1563Svbart@nginx.com if (next == NULL) { 307*1563Svbart@nginx.com nxt_sprintf(error, error + NXT_MAX_ERROR_STR, 308*1563Svbart@nginx.com "Invalid variable at position %uz%Z", p - str->start); 309*1563Svbart@nginx.com 310*1563Svbart@nginx.com return NXT_ERROR; 311*1563Svbart@nginx.com } 312*1563Svbart@nginx.com 313*1563Svbart@nginx.com if (is_var) { 314*1563Svbart@nginx.com decl = nxt_var_hash_find(&part); 315*1563Svbart@nginx.com 316*1563Svbart@nginx.com if (decl == NULL) { 317*1563Svbart@nginx.com nxt_sprintf(error, error + NXT_MAX_ERROR_STR, 318*1563Svbart@nginx.com "Unknown variable \"%V\"%Z", &part); 319*1563Svbart@nginx.com 320*1563Svbart@nginx.com return NXT_ERROR; 321*1563Svbart@nginx.com } 322*1563Svbart@nginx.com } 323*1563Svbart@nginx.com 324*1563Svbart@nginx.com p = next; 325*1563Svbart@nginx.com } 326*1563Svbart@nginx.com 327*1563Svbart@nginx.com return NXT_OK; 328*1563Svbart@nginx.com } 329*1563Svbart@nginx.com 330*1563Svbart@nginx.com 331*1563Svbart@nginx.com static u_char * 332*1563Svbart@nginx.com nxt_var_next_part(u_char *start, size_t length, nxt_str_t *part, 333*1563Svbart@nginx.com nxt_bool_t *is_var) 334*1563Svbart@nginx.com { 335*1563Svbart@nginx.com u_char *p, *end, ch, c; 336*1563Svbart@nginx.com nxt_bool_t bracket; 337*1563Svbart@nginx.com 338*1563Svbart@nginx.com end = start + length; 339*1563Svbart@nginx.com 340*1563Svbart@nginx.com p = nxt_memchr(start, '$', length); 341*1563Svbart@nginx.com 342*1563Svbart@nginx.com if (p == start) { 343*1563Svbart@nginx.com *is_var = 1; 344*1563Svbart@nginx.com 345*1563Svbart@nginx.com p++; 346*1563Svbart@nginx.com 347*1563Svbart@nginx.com if (p == end) { 348*1563Svbart@nginx.com return NULL; 349*1563Svbart@nginx.com } 350*1563Svbart@nginx.com 351*1563Svbart@nginx.com if (*p == '{') { 352*1563Svbart@nginx.com bracket = 1; 353*1563Svbart@nginx.com 354*1563Svbart@nginx.com if (end - p < 2) { 355*1563Svbart@nginx.com return NULL; 356*1563Svbart@nginx.com } 357*1563Svbart@nginx.com 358*1563Svbart@nginx.com p++; 359*1563Svbart@nginx.com 360*1563Svbart@nginx.com } else { 361*1563Svbart@nginx.com bracket = 0; 362*1563Svbart@nginx.com } 363*1563Svbart@nginx.com 364*1563Svbart@nginx.com start = p; 365*1563Svbart@nginx.com 366*1563Svbart@nginx.com for ( ;; ) { 367*1563Svbart@nginx.com ch = *p; 368*1563Svbart@nginx.com 369*1563Svbart@nginx.com c = (u_char) (ch | 0x20); 370*1563Svbart@nginx.com if ((c < 'a' || c > 'z') && ch != '_') { 371*1563Svbart@nginx.com 372*1563Svbart@nginx.com if (bracket && ch != '}') { 373*1563Svbart@nginx.com return NULL; 374*1563Svbart@nginx.com } 375*1563Svbart@nginx.com 376*1563Svbart@nginx.com break; 377*1563Svbart@nginx.com } 378*1563Svbart@nginx.com 379*1563Svbart@nginx.com p++; 380*1563Svbart@nginx.com 381*1563Svbart@nginx.com if (p == end) { 382*1563Svbart@nginx.com if (bracket) { 383*1563Svbart@nginx.com return NULL; 384*1563Svbart@nginx.com } 385*1563Svbart@nginx.com 386*1563Svbart@nginx.com break; 387*1563Svbart@nginx.com } 388*1563Svbart@nginx.com } 389*1563Svbart@nginx.com 390*1563Svbart@nginx.com length = p - start; 391*1563Svbart@nginx.com end = p + bracket; 392*1563Svbart@nginx.com 393*1563Svbart@nginx.com } else { 394*1563Svbart@nginx.com *is_var = 0; 395*1563Svbart@nginx.com 396*1563Svbart@nginx.com if (p != NULL) { 397*1563Svbart@nginx.com length = p - start; 398*1563Svbart@nginx.com end = p; 399*1563Svbart@nginx.com } 400*1563Svbart@nginx.com } 401*1563Svbart@nginx.com 402*1563Svbart@nginx.com part->length = length; 403*1563Svbart@nginx.com part->start = start; 404*1563Svbart@nginx.com 405*1563Svbart@nginx.com return end; 406*1563Svbart@nginx.com } 407*1563Svbart@nginx.com 408*1563Svbart@nginx.com 409*1563Svbart@nginx.com nxt_int_t 410*1563Svbart@nginx.com nxt_var_query_init(nxt_var_query_t **query_p, void *ctx, nxt_mp_t *mp) 411*1563Svbart@nginx.com { 412*1563Svbart@nginx.com nxt_var_query_t *query; 413*1563Svbart@nginx.com 414*1563Svbart@nginx.com query = *query_p; 415*1563Svbart@nginx.com 416*1563Svbart@nginx.com if (*query_p == NULL) { 417*1563Svbart@nginx.com query = nxt_mp_zget(mp, sizeof(nxt_var_query_t)); 418*1563Svbart@nginx.com if (nxt_slow_path(query == NULL)) { 419*1563Svbart@nginx.com return NXT_ERROR; 420*1563Svbart@nginx.com } 421*1563Svbart@nginx.com 422*1563Svbart@nginx.com nxt_array_init(&query->values, mp, sizeof(nxt_var_value_t)); 423*1563Svbart@nginx.com nxt_array_init(&query->parts, mp, sizeof(nxt_str_t *)); 424*1563Svbart@nginx.com 425*1563Svbart@nginx.com } else { 426*1563Svbart@nginx.com nxt_array_reset(&query->values); 427*1563Svbart@nginx.com } 428*1563Svbart@nginx.com 429*1563Svbart@nginx.com query->ctx = ctx; 430*1563Svbart@nginx.com 431*1563Svbart@nginx.com *query_p = query; 432*1563Svbart@nginx.com 433*1563Svbart@nginx.com return NXT_OK; 434*1563Svbart@nginx.com } 435*1563Svbart@nginx.com 436*1563Svbart@nginx.com 437*1563Svbart@nginx.com void 438*1563Svbart@nginx.com nxt_var_query(nxt_task_t *task, nxt_var_query_t *query, nxt_var_t *var, 439*1563Svbart@nginx.com nxt_str_t *str) 440*1563Svbart@nginx.com { 441*1563Svbart@nginx.com uint32_t *indexes; 442*1563Svbart@nginx.com nxt_mp_t *mp; 443*1563Svbart@nginx.com nxt_str_t *value; 444*1563Svbart@nginx.com nxt_int_t ret; 445*1563Svbart@nginx.com nxt_uint_t i; 446*1563Svbart@nginx.com nxt_var_value_t *val; 447*1563Svbart@nginx.com 448*1563Svbart@nginx.com if (var->vars == 0) { 449*1563Svbart@nginx.com str->length = var->plain; 450*1563Svbart@nginx.com str->start = nxt_var_plain_start(var); 451*1563Svbart@nginx.com return; 452*1563Svbart@nginx.com } 453*1563Svbart@nginx.com 454*1563Svbart@nginx.com if (nxt_slow_path(query->failed)) { 455*1563Svbart@nginx.com return; 456*1563Svbart@nginx.com } 457*1563Svbart@nginx.com 458*1563Svbart@nginx.com mp = query->values.mem_pool; 459*1563Svbart@nginx.com indexes = nxt_var_indexes(var); 460*1563Svbart@nginx.com value = query->spare; 461*1563Svbart@nginx.com 462*1563Svbart@nginx.com for (i = 0; i < var->vars; i++) { 463*1563Svbart@nginx.com 464*1563Svbart@nginx.com if (value == NULL) { 465*1563Svbart@nginx.com value = nxt_mp_zget(mp, sizeof(nxt_str_t)); 466*1563Svbart@nginx.com if (nxt_slow_path(value == NULL)) { 467*1563Svbart@nginx.com goto fail; 468*1563Svbart@nginx.com } 469*1563Svbart@nginx.com } 470*1563Svbart@nginx.com 471*1563Svbart@nginx.com ret = nxt_var_cache_add(&query->cache, indexes[i], value, mp); 472*1563Svbart@nginx.com 473*1563Svbart@nginx.com if (ret != NXT_OK) { 474*1563Svbart@nginx.com if (nxt_slow_path(ret == NXT_ERROR)) { 475*1563Svbart@nginx.com goto fail; 476*1563Svbart@nginx.com } 477*1563Svbart@nginx.com 478*1563Svbart@nginx.com continue; /* NXT_DECLINED */ 479*1563Svbart@nginx.com } 480*1563Svbart@nginx.com 481*1563Svbart@nginx.com ret = nxt_var_index[indexes[i]](task, query, value, query->ctx); 482*1563Svbart@nginx.com 483*1563Svbart@nginx.com value = NULL; 484*1563Svbart@nginx.com 485*1563Svbart@nginx.com if (ret != NXT_OK) { 486*1563Svbart@nginx.com if (nxt_slow_path(ret != NXT_AGAIN)) { 487*1563Svbart@nginx.com goto fail; 488*1563Svbart@nginx.com } 489*1563Svbart@nginx.com 490*1563Svbart@nginx.com query->waiting++; 491*1563Svbart@nginx.com } 492*1563Svbart@nginx.com } 493*1563Svbart@nginx.com 494*1563Svbart@nginx.com query->spare = value; 495*1563Svbart@nginx.com 496*1563Svbart@nginx.com val = nxt_array_add(&query->values); 497*1563Svbart@nginx.com if (nxt_slow_path(val == NULL)) { 498*1563Svbart@nginx.com goto fail; 499*1563Svbart@nginx.com } 500*1563Svbart@nginx.com 501*1563Svbart@nginx.com val->var = var; 502*1563Svbart@nginx.com val->value = str; 503*1563Svbart@nginx.com 504*1563Svbart@nginx.com return; 505*1563Svbart@nginx.com 506*1563Svbart@nginx.com fail: 507*1563Svbart@nginx.com 508*1563Svbart@nginx.com query->failed = 1; 509*1563Svbart@nginx.com } 510*1563Svbart@nginx.com 511*1563Svbart@nginx.com 512*1563Svbart@nginx.com void 513*1563Svbart@nginx.com nxt_var_query_resolve(nxt_task_t *task, nxt_var_query_t *query, void *data, 514*1563Svbart@nginx.com nxt_work_handler_t ready, nxt_work_handler_t error) 515*1563Svbart@nginx.com { 516*1563Svbart@nginx.com query->data = data; 517*1563Svbart@nginx.com query->ready = ready; 518*1563Svbart@nginx.com query->error = error; 519*1563Svbart@nginx.com 520*1563Svbart@nginx.com if (query->waiting == 0) { 521*1563Svbart@nginx.com nxt_var_query_finish(task, query); 522*1563Svbart@nginx.com } 523*1563Svbart@nginx.com } 524*1563Svbart@nginx.com 525*1563Svbart@nginx.com 526*1563Svbart@nginx.com void 527*1563Svbart@nginx.com nxt_var_query_handle(nxt_task_t *task, nxt_var_query_t *query, 528*1563Svbart@nginx.com nxt_bool_t failed) 529*1563Svbart@nginx.com { 530*1563Svbart@nginx.com query->failed |= failed; 531*1563Svbart@nginx.com 532*1563Svbart@nginx.com if (--query->waiting == 0) { 533*1563Svbart@nginx.com nxt_var_query_finish(task, query); 534*1563Svbart@nginx.com } 535*1563Svbart@nginx.com } 536*1563Svbart@nginx.com 537*1563Svbart@nginx.com 538*1563Svbart@nginx.com static void 539*1563Svbart@nginx.com nxt_var_query_finish(nxt_task_t *task, nxt_var_query_t *query) 540*1563Svbart@nginx.com { 541*1563Svbart@nginx.com u_char *p, *src; 542*1563Svbart@nginx.com size_t length, plain, next, *positions; 543*1563Svbart@nginx.com uint32_t *indexes; 544*1563Svbart@nginx.com nxt_str_t *str, **part; 545*1563Svbart@nginx.com nxt_var_t *var; 546*1563Svbart@nginx.com nxt_uint_t i, j; 547*1563Svbart@nginx.com nxt_var_value_t *val; 548*1563Svbart@nginx.com 549*1563Svbart@nginx.com if (query->failed) { 550*1563Svbart@nginx.com goto done; 551*1563Svbart@nginx.com } 552*1563Svbart@nginx.com 553*1563Svbart@nginx.com val = query->values.elts; 554*1563Svbart@nginx.com 555*1563Svbart@nginx.com for (i = 0; i < query->values.nelts; i++) { 556*1563Svbart@nginx.com var = val[i].var; 557*1563Svbart@nginx.com 558*1563Svbart@nginx.com length = var->plain; 559*1563Svbart@nginx.com indexes = nxt_var_indexes(var); 560*1563Svbart@nginx.com 561*1563Svbart@nginx.com for (j = 0; j < var->vars; j++) { 562*1563Svbart@nginx.com str = nxt_var_cache_find(&query->cache, indexes[j]); 563*1563Svbart@nginx.com 564*1563Svbart@nginx.com nxt_assert(str != NULL); 565*1563Svbart@nginx.com 566*1563Svbart@nginx.com part = nxt_array_add(&query->parts); 567*1563Svbart@nginx.com 568*1563Svbart@nginx.com if (nxt_slow_path(part == NULL)) { 569*1563Svbart@nginx.com query->failed = 1; 570*1563Svbart@nginx.com goto done; 571*1563Svbart@nginx.com } 572*1563Svbart@nginx.com 573*1563Svbart@nginx.com *part = str; 574*1563Svbart@nginx.com 575*1563Svbart@nginx.com length += str->length; 576*1563Svbart@nginx.com } 577*1563Svbart@nginx.com 578*1563Svbart@nginx.com p = nxt_mp_nget(query->values.mem_pool, length); 579*1563Svbart@nginx.com if (nxt_slow_path(p == NULL)) { 580*1563Svbart@nginx.com query->failed = 1; 581*1563Svbart@nginx.com goto done; 582*1563Svbart@nginx.com } 583*1563Svbart@nginx.com 584*1563Svbart@nginx.com val[i].value->length = length; 585*1563Svbart@nginx.com val[i].value->start = p; 586*1563Svbart@nginx.com 587*1563Svbart@nginx.com part = query->parts.elts; 588*1563Svbart@nginx.com positions = nxt_var_positions(var); 589*1563Svbart@nginx.com src = nxt_var_plain_start(var); 590*1563Svbart@nginx.com 591*1563Svbart@nginx.com plain = 0; 592*1563Svbart@nginx.com 593*1563Svbart@nginx.com for (j = 0; j < var->vars; j++) { 594*1563Svbart@nginx.com next = positions[j]; 595*1563Svbart@nginx.com 596*1563Svbart@nginx.com if (next != plain) { 597*1563Svbart@nginx.com p = nxt_cpymem(p, &src[plain], next - plain); 598*1563Svbart@nginx.com plain = next; 599*1563Svbart@nginx.com } 600*1563Svbart@nginx.com 601*1563Svbart@nginx.com p = nxt_cpymem(p, part[j]->start, part[j]->length); 602*1563Svbart@nginx.com } 603*1563Svbart@nginx.com 604*1563Svbart@nginx.com if (plain != var->plain) { 605*1563Svbart@nginx.com nxt_memcpy(p, &src[plain], var->plain - plain); 606*1563Svbart@nginx.com } 607*1563Svbart@nginx.com 608*1563Svbart@nginx.com nxt_array_reset(&query->parts); 609*1563Svbart@nginx.com } 610*1563Svbart@nginx.com 611*1563Svbart@nginx.com done: 612*1563Svbart@nginx.com 613*1563Svbart@nginx.com nxt_work_queue_add(&task->thread->engine->fast_work_queue, 614*1563Svbart@nginx.com query->failed ? query->error : query->ready, 615*1563Svbart@nginx.com task, query->ctx, query->data); 616*1563Svbart@nginx.com } 617