~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/core/ngx_hash.c

Version: ~ [ nginx-0.6.26 ] ~ [ nginx-0.5.35 ] ~ [ nginx-0.5.20 ] ~ [ nginx-0.5.19 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  */
  5 
  6 
  7 #include <ngx_config.h>
  8 #include <ngx_core.h>
  9 
 10 
 11 void *
 12 ngx_hash_find(ngx_hash_t *hash, ngx_uint_t key, u_char *name, size_t len)
 13 {
 14     ngx_uint_t       i;
 15     ngx_hash_elt_t  *elt;
 16 
 17 #if 0
 18     ngx_str_t  line;
 19 
 20     line.len = len;
 21     line.data = name;
 22     ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "hf:\"%V\"", &line);
 23 #endif
 24 
 25     elt = hash->buckets[key % hash->size];
 26 
 27     if (elt == NULL) {
 28         return NULL;
 29     }
 30 
 31     while (elt->value) {
 32         if (len != (size_t) elt->len) {
 33             goto next;
 34         }
 35 
 36         for (i = 0; i < len; i++) {
 37             if (name[i] != elt->name[i]) {
 38                 goto next;
 39             }
 40         }
 41 
 42         return elt->value;
 43 
 44     next:
 45 
 46         elt = (ngx_hash_elt_t *) ngx_align_ptr(&elt->name[0] + elt->len,
 47                                                sizeof(void *));
 48         continue;
 49     }
 50 
 51     return NULL;
 52 }
 53 
 54 
 55 void *
 56 ngx_hash_find_wc_head(ngx_hash_wildcard_t *hwc, u_char *name, size_t len)
 57 {
 58     void        *value;
 59     ngx_uint_t   i, n, key;
 60 
 61 #if 0
 62     ngx_str_t  line;
 63 
 64     line.len = len;
 65     line.data = name;
 66     ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "wch:\"%V\"", &line);
 67 #endif
 68 
 69     n = len;
 70 
 71     while (n) {
 72         if (name[n - 1] == '.') {
 73             break;
 74         }
 75 
 76         n--;
 77     }
 78 
 79     key = 0;
 80 
 81     for (i = n; i < len; i++) {
 82         key = ngx_hash(key, name[i]);
 83     }
 84 
 85 #if 0
 86     ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "key:\"%ui\"", key);
 87 #endif
 88 
 89     value = ngx_hash_find(&hwc->hash, key, &name[n], len - n);
 90 
 91     if (value) {
 92 
 93         /*
 94          * the 2 low bits of value have the special meaning:
 95          *     00 - value is data pointer,
 96          *     01 - value is pointer to wildcard hash allowing
 97          *          "*.example.com" only,
 98          *     11 - value is pointer to wildcard hash allowing
 99          *          both "example.com" and "*.example.com".
100          */
101 
102         if ((uintptr_t) value & 1) {
103 
104             hwc = (ngx_hash_wildcard_t *) ((uintptr_t) value & (uintptr_t) ~3);
105 
106             if (n == 0) {
107                 if ((uintptr_t) value & 2) {
108                     return hwc->value;
109 
110                 } else {
111                     return NULL;
112                 }
113             }
114 
115             value = ngx_hash_find_wc_head(hwc, name, n - 1);
116 
117             if (value) {
118                 return value;
119             }
120 
121             return hwc->value;
122         }
123 
124         return value;
125     }
126 
127     return hwc->value;
128 }
129 
130 
131 void *
132 ngx_hash_find_wc_tail(ngx_hash_wildcard_t *hwc, u_char *name, size_t len)
133 {
134     void        *value;
135     ngx_uint_t   i, key;
136 
137 #if 0
138     ngx_str_t  line;
139 
140     line.len = len;
141     line.data = name;
142     ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "wct:\"%V\"", &line);
143 #endif
144 
145     key = 0;
146 
147     for (i = 0; i < len; i++) {
148         if (name[i] == '.') {
149             break;
150         }
151 
152         key = ngx_hash(key, name[i]);
153     }
154 
155     if (i == len) {
156         return NULL;
157     }
158 
159 #if 0
160     ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "key:\"%ui\"", key);
161 #endif
162 
163     value = ngx_hash_find(&hwc->hash, key, name, i);
164 
165     if (value) {
166 
167         /*
168          * the 2 low bits of value have the special meaning:
169          *     00 - value is data pointer,
170          *     01 - value is pointer to wildcard hash allowing "example.*".
171          */
172 
173         if ((uintptr_t) value & 1) {
174 
175             i++;
176 
177             hwc = (ngx_hash_wildcard_t *) ((uintptr_t) value & (uintptr_t) ~3);
178 
179             value = ngx_hash_find_wc_tail(hwc, &name[i], len - i);
180 
181             if (value) {
182                 return value;
183             }
184 
185             return hwc->value;
186         }
187 
188         return value;
189     }
190 
191     return hwc->value;
192 }
193 
194 
195 void *
196 ngx_hash_find_combined(ngx_hash_combined_t *hash, ngx_uint_t key, u_char *name,
197     size_t len)
198 {
199     void  *value;
200 
201     if (hash->hash.buckets) {
202         value = ngx_hash_find(&hash->hash, key, name, len);
203 
204         if (value) {
205             return value;
206         }
207     }
208 
209     if (hash->wc_head && hash->wc_head->hash.buckets) {
210         value = ngx_hash_find_wc_head(hash->wc_head, name, len);
211 
212         if (value) {
213             return value;
214         }
215     }
216 
217     if (hash->wc_tail && hash->wc_tail->hash.buckets) {
218         value = ngx_hash_find_wc_tail(hash->wc_tail, name, len);
219 
220         if (value) {
221             return value;
222         }
223     }
224 
225     return NULL;
226 }
227 
228 
229 #define NGX_HASH_ELT_SIZE(name)                                               \
230     (sizeof(void *) + ngx_align((name)->key.len + 1, sizeof(void *)))
231 
232 ngx_int_t
233 ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
234 {
235     u_char          *elts;
236     size_t           len;
237     u_short         *test;
238     ngx_uint_t       i, n, key, size, start, bucket_size;
239     ngx_hash_elt_t  *elt, **buckets;
240 
241     for (n = 0; n < nelts; n++) {
242         if (names[n].key.len >= 255) {
243             ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
244                           "the \"%V\" value to hash is to long: %uz bytes, "
245                           "the maximum length can be 255 bytes only",
246                           &names[n].key, names[n].key.len);
247             return NGX_ERROR;
248         }
249 
250         if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *))
251         {
252             ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
253                           "could not build the %s, you should "
254                           "increase %s_bucket_size: %i",
255                           hinit->name, hinit->name, hinit->bucket_size);
256             return NGX_ERROR;
257         }
258     }
259 
260     test = ngx_alloc(hinit->max_size * sizeof(u_short), hinit->pool->log);
261     if (test == NULL) {
262         return NGX_ERROR;
263     }
264 
265     bucket_size = hinit->bucket_size - sizeof(void *);
266 
267     start = nelts / (bucket_size / (2 * sizeof(void *)));
268     start = start ? start : 1;
269 
270     if (hinit->max_size > 10000 && hinit->max_size / nelts < 100) {
271         start = hinit->max_size - 1000;
272     }
273 
274     for (size = start; size < hinit->max_size; size++) {
275 
276         ngx_memzero(test, size * sizeof(u_short));
277 
278         for (n = 0; n < nelts; n++) {
279             if (names[n].key.data == NULL) {
280                 continue;
281             }
282 
283             key = names[n].key_hash % size;
284             test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
285 
286 #if 0
287             ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
288                           "%ui: %ui %ui \"%V\"",
289                           size, key, test[key], &names[n].key);
290 #endif
291 
292             if (test[key] > (u_short) bucket_size) {
293                 goto next;
294             }
295         }
296 
297         goto found;
298 
299     next:
300 
301         continue;
302     }
303 
304     ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
305                   "could not build the %s, you should increase "
306                   "either %s_max_size: %i or %s_bucket_size: %i",
307                   hinit->name, hinit->name, hinit->max_size,
308                   hinit->name, hinit->bucket_size);
309 
310     ngx_free(test);
311 
312     return NGX_ERROR;
313 
314 found:
315 
316     for (i = 0; i < size; i++) {
317         test[i] = sizeof(void *);
318     }
319 
320     for (n = 0; n < nelts; n++) {
321         if (names[n].key.data == NULL) {
322             continue;
323         }
324 
325         key = names[n].key_hash % size;
326         test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
327     }
328 
329     len = 0;
330 
331     for (i = 0; i < size; i++) {
332         if (test[i] == sizeof(void *)) {
333             continue;
334         }
335 
336         test[i] = (u_short) (ngx_align(test[i], ngx_cacheline_size));
337 
338         len += test[i];
339     }
340 
341     if (hinit->hash == NULL) {
342         hinit->hash = ngx_pcalloc(hinit->pool, sizeof(ngx_hash_wildcard_t)
343                                              + size * sizeof(ngx_hash_elt_t *));
344         if (hinit->hash == NULL) {
345             ngx_free(test);
346             return NGX_ERROR;
347         }
348 
349         buckets = (ngx_hash_elt_t **)
350                       ((u_char *) hinit->hash + sizeof(ngx_hash_wildcard_t));
351 
352     } else {
353         buckets = ngx_pcalloc(hinit->pool, size * sizeof(ngx_hash_elt_t *));
354         if (buckets == NULL) {
355             ngx_free(test);
356             return NGX_ERROR;
357         }
358     }
359 
360     elts = ngx_palloc(hinit->pool, len + ngx_cacheline_size);
361     if (elts == NULL) {
362         ngx_free(test);
363         return NGX_ERROR;
364     }
365 
366     elts = ngx_align_ptr(elts, ngx_cacheline_size);
367 
368     for (i = 0; i < size; i++) {
369         if (test[i] == sizeof(void *)) {
370             continue;
371         }
372 
373         buckets[i] = (ngx_hash_elt_t *) elts;
374         elts += test[i];
375 
376     }
377 
378     for (i = 0; i < size; i++) {
379         test[i] = 0;
380     }
381 
382     for (n = 0; n < nelts; n++) {
383         if (names[n].key.data == NULL) {
384             continue;
385         }
386 
387         key = names[n].key_hash % size;
388         elt = (ngx_hash_elt_t *) ((u_char *) buckets[key] + test[key]);
389 
390         elt->value = names[n].value;
391         elt->len = (u_char) names[n].key.len;
392 
393         for (i = 0; i < names[n].key.len; i++) {
394             elt->name[i] = ngx_tolower(names[n].key.data[i]);
395         }
396 
397         test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
398     }
399 
400     for (i = 0; i < size; i++) {
401         if (buckets[i] == NULL) {
402             continue;
403         }
404 
405         elt = (ngx_hash_elt_t *) ((u_char *) buckets[i] + test[i]);
406 
407         elt->value = NULL;
408     }
409 
410     ngx_free(test);
411 
412     hinit->hash->buckets = buckets;
413     hinit->hash->size = size;
414 
415 #if 0
416 
417     for (i = 0; i < size; i++) {
418         ngx_str_t   val;
419         ngx_uint_t  key;
420 
421         elt = buckets[i];
422 
423         if (elt == NULL) {
424             ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
425                           "%ui: NULL", i);
426             continue;
427         }
428 
429         while (elt->value) {
430             val.len = elt->len;
431             val.data = &elt->name[0];
432 
433             key = hinit->key(val.data, val.len);
434 
435             ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
436                           "%ui: %p \"%V\" %ui", i, elt, &val, key);
437 
438             elt = (ngx_hash_elt_t *) ngx_align_ptr(&elt->name[0] + elt->len,
439                                                    sizeof(void *));
440         }
441     }
442 
443 #endif
444 
445     return NGX_OK;
446 }
447 
448 
449 ngx_int_t
450 ngx_hash_wildcard_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names,
451     ngx_uint_t nelts)
452 {
453     size_t                len, dot_len;
454     ngx_uint_t            i, n, dot;
455     ngx_array_t           curr_names, next_names;
456     ngx_hash_key_t       *name, *next_name;
457     ngx_hash_init_t       h;
458     ngx_hash_wildcard_t  *wdc;
459 
460     if (ngx_array_init(&curr_names, hinit->temp_pool, nelts,
461                        sizeof(ngx_hash_key_t))
462         != NGX_OK)
463     {
464         return NGX_ERROR;
465     }
466 
467     if (ngx_array_init(&next_names, hinit->temp_pool, nelts,
468                        sizeof(ngx_hash_key_t))
469         != NGX_OK)
470     {
471         return NGX_ERROR;
472     }
473 
474     for (n = 0; n < nelts; n = i) {
475 
476 #if 0
477         ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
478                       "wc0: \"%V\"", &names[n].key);
479 #endif
480 
481         dot = 0;
482 
483         for (len = 0; len < names[n].key.len; len++) {
484             if (names[n].key.data[len] == '.') {
485                 dot = 1;
486                 break;
487             }
488         }
489 
490         name = ngx_array_push(&curr_names);
491         if (name == NULL) {
492             return NGX_ERROR;
493         }
494 
495         name->key.len = len;
496         name->key.data = names[n].key.data;
497         name->key_hash = hinit->key(name->key.data, name->key.len);
498         name->value = names[n].value;
499 
500 #if 0
501         ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
502                       "wc1: \"%V\" %ui", &name->key, dot);
503 #endif
504 
505         dot_len = len + 1;
506 
507         if (dot) {
508             len++;
509         }
510 
511         next_names.nelts = 0;
512 
513         if (names[n].key.len != len) {
514             next_name = ngx_array_push(&next_names);
515             if (next_name == NULL) {
516                 return NGX_ERROR;
517             }
518 
519             next_name->key.len = names[n].key.len - len;
520             next_name->key.data = names[n].key.data + len;
521             next_name->key_hash= 0;
522             next_name->value = names[n].value;
523 
524 #if 0
525             ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
526                           "wc2: \"%V\"", &next_name->key);
527 #endif
528         }
529 
530         for (i = n + 1; i < nelts; i++) {
531             if (ngx_strncmp(names[n].key.data, names[i].key.data, len) != 0) {
532                 break;
533             }
534 
535             if (!dot
536                 && names[i].key.len > len
537                 && names[i].key.data[len] != '.')
538             {
539                 break;
540             }
541 
542             next_name = ngx_array_push(&next_names);
543             if (next_name == NULL) {
544                 return NGX_ERROR;
545             }
546 
547             next_name->key.len = names[i].key.len - dot_len;
548             next_name->key.data = names[i].key.data + dot_len;
549             next_name->key_hash= 0;
550             next_name->value = names[i].value;
551 
552 #if 0
553             ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
554                           "wc3: \"%V\"", &next_name->key);
555 #endif
556         }
557 
558         if (next_names.nelts) {
559 
560             h = *hinit;
561             h.hash = NULL;
562 
563             if (ngx_hash_wildcard_init(&h, (ngx_hash_key_t *) next_names.elts,
564                                        next_names.nelts)
565                 != NGX_OK)
566             {
567                 return NGX_ERROR;
568             }
569 
570             wdc = (ngx_hash_wildcard_t *) h.hash;
571 
572             if (names[n].key.len == len) {
573                 wdc->value = names[n].value;
574 #if 0
575                 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
576                               "wdc: \"%V\"", wdc->value);
577 #endif
578             }
579 
580             name->value = (void *) ((uintptr_t) wdc | (dot ? 1 : 3));
581         }
582     }
583 
584     if (ngx_hash_init(hinit, (ngx_hash_key_t *) curr_names.elts,
585                       curr_names.nelts)
586         != NGX_OK)
587     {
588         return NGX_ERROR;
589     }
590 
591     return NGX_OK;
592 }
593 
594 
595 ngx_uint_t
596 ngx_hash_key(u_char *data, size_t len)
597 {
598     ngx_uint_t  i, key;
599 
600     key = 0;
601 
602     for (i = 0; i < len; i++) {
603         key = ngx_hash(key, data[i]);
604     }
605 
606     return key;
607 }
608 
609 
610 ngx_uint_t
611 ngx_hash_key_lc(u_char *data, size_t len)
612 {
613     ngx_uint_t  i, key;
614 
615     key = 0;
616 
617     for (i = 0; i < len; i++) {
618         key = ngx_hash(key, ngx_tolower(data[i]));
619     }
620 
621     return key;
622 }
623 
624 
625 ngx_int_t
626 ngx_hash_keys_array_init(ngx_hash_keys_arrays_t *ha, ngx_uint_t type)
627 {
628     ngx_uint_t  asize;
629 
630     if (type == NGX_HASH_SMALL) {
631         asize = 4;
632         ha->hsize = 107;
633 
634     } else {
635         asize = NGX_HASH_LARGE_ASIZE;
636         ha->hsize = NGX_HASH_LARGE_HSIZE;
637     }
638 
639     if (ngx_array_init(&ha->keys, ha->temp_pool, asize, sizeof(ngx_hash_key_t))
640         != NGX_OK)
641     {
642         return NGX_ERROR;
643     }
644 
645     if (ngx_array_init(&ha->dns_wc_head, ha->temp_pool, asize,
646                        sizeof(ngx_hash_key_t))
647         != NGX_OK)
648     {
649         return NGX_ERROR;
650     }
651 
652     if (ngx_array_init(&ha->dns_wc_tail, ha->temp_pool, asize,
653                        sizeof(ngx_hash_key_t))
654         != NGX_OK)
655     {
656         return NGX_ERROR;
657     }
658 
659     ha->keys_hash = ngx_pcalloc(ha->temp_pool, sizeof(ngx_array_t) * ha->hsize);
660     if (ha->keys_hash == NULL) {
661         return NGX_ERROR;
662     }
663 
664     ha->dns_wc_head_hash = ngx_pcalloc(ha->temp_pool,
665                                        sizeof(ngx_array_t) * ha->hsize);
666     if (ha->dns_wc_head_hash == NULL) {
667         return NGX_ERROR;
668     }
669 
670     ha->dns_wc_tail_hash = ngx_pcalloc(ha->temp_pool,
671                                        sizeof(ngx_array_t) * ha->hsize);
672     if (ha->dns_wc_tail_hash == NULL) {
673         return NGX_ERROR;
674     }
675 
676     return NGX_OK;
677 }
678 
679 
680 ngx_int_t
681 ngx_hash_add_key(ngx_hash_keys_arrays_t *ha, ngx_str_t *key, void *value,
682     ngx_uint_t flags)
683 {
684     size_t           len;
685     u_char          *p;
686     ngx_str_t       *name;
687     ngx_uint_t       i, k, n, skip, last;
688     ngx_array_t     *keys, *hwc;
689     ngx_hash_key_t  *hk;
690 
691     last = key->len;
692 
693     if (flags & NGX_HASH_WILDCARD_KEY) {
694 
695         /*
696          * supported wildcards:
697          *     "*.example.com", ".example.com", and "www.example.*"
698          */
699 
700         n = 0;
701 
702         for (i = 0; i < key->len; i++) {
703 
704             if (key->data[i] == '*') {
705                 if (++n > 1) {
706                     return NGX_DECLINED;
707                 }
708             }
709 
710             if (key->data[i] == '.' && key->data[i + 1] == '.') {
711                 return NGX_DECLINED;
712             }
713         }
714 
715         if (key->len > 1 && key->data[0] == '.') {
716             skip = 1;
717             goto wildcard;
718         }
719 
720         if (key->len > 2) {
721 
722             if (key->data[0] == '*' && key->data[1] == '.') {
723                 skip = 2;
724                 goto wildcard;
725             }
726 
727             if (key->data[i - 2] == '.' && key->data[i - 1] == '*') {
728                 skip = 0;
729                 last -= 2;
730                 goto wildcard;
731             }
732         }
733 
734         if (n) {
735             return NGX_DECLINED;
736         }
737     }
738 
739     /* exact hash */
740 
741     k = 0;
742 
743     for (i = 0; i < last; i++) {
744         if (!(flags & NGX_HASH_READONLY_KEY)) {
745             key->data[i] = ngx_tolower(key->data[i]);
746         }
747         k = ngx_hash(k, key->data[i]);
748     }
749 
750     k %= ha->hsize;
751 
752     /* check conflicts in exact hash */
753 
754     name = ha->keys_hash[k].elts;
755 
756     if (name) {
757         for (i = 0; i < ha->keys_hash[k].nelts; i++) {
758             if (last != name[i].len) {
759                 continue;
760             }
761 
762             if (ngx_strncmp(key->data, name[i].data, last) == 0) {
763                 return NGX_BUSY;
764             }
765         }
766 
767     } else {
768         if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4,
769                            sizeof(ngx_str_t))
770             != NGX_OK)
771         {
772             return NGX_ERROR;
773         }
774     }
775 
776     name = ngx_array_push(&ha->keys_hash[k]);
777     if (name == NULL) {
778         return NGX_ERROR;
779     }
780 
781     *name = *key;
782 
783     hk = ngx_array_push(&ha->keys);
784     if (hk == NULL) {
785         return NGX_ERROR;
786     }
787 
788     hk->key = *key;
789     hk->key_hash = ngx_hash_key(key->data, last);
790     hk->value = value;
791 
792     return NGX_OK;
793 
794 
795 wildcard:
796 
797     /* wildcard hash */
798 
799     k = 0;
800 
801     for (i = skip; i < last; i++) {
802         key->data[i] = ngx_tolower(key->data[i]);
803         k = ngx_hash(k, key->data[i]);
804     }
805 
806     k %= ha->hsize;
807 
808     if (skip == 1) {
809 
810         /* check conflicts in exact hash for ".example.com" */
811 
812         name = ha->keys_hash[k].elts;
813 
814         if (name) {
815             len = last - skip;
816 
817             for (i = 0; i < ha->keys_hash[k].nelts; i++) {
818                 if (len != name[i].len) {
819                     continue;
820                 }
821 
822                 if (ngx_strncmp(&key->data[1], name[i].data, len) == 0) {
823                     return NGX_BUSY;
824                 }
825             }
826 
827         } else {
828             if (ngx_array_init(&ha->keys_hash[k], ha->temp_pool, 4,
829                                sizeof(ngx_str_t))
830                 != NGX_OK)
831             {
832                 return NGX_ERROR;
833             }
834         }
835 
836         name = ngx_array_push(&ha->keys_hash[k]);
837         if (name == NULL) {
838             return NGX_ERROR;
839         }
840 
841         name->len = last - 1;
842         name->data = ngx_palloc(ha->temp_pool, name->len);
843         if (name->data == NULL) {
844             return NGX_ERROR;
845         }
846 
847         ngx_memcpy(name->data, &key->data[1], name->len);
848     }
849 
850 
851     if (skip) {
852 
853         /*
854          * convert "*.example.com" to "com.example.\0"
855          *      and ".example.com" to "com.example\0"
856          */
857 
858         p = ngx_palloc(ha->temp_pool, last);
859         if (p == NULL) {
860             return NGX_ERROR;
861         }
862 
863         len = 0;
864         n = 0;
865 
866         for (i = last - 1; i; i--) {
867             if (key->data[i] == '.') {
868                 ngx_memcpy(&p[n], &key->data[i + 1], len);
869                 n += len;
870                 p[n++] = '.';
871                 len = 0;
872                 continue;
873             }
874 
875             len++;
876         }
877 
878         if (len) {
879             ngx_memcpy(&p[n], &key->data[1], len);
880             n += len;
881         }
882 
883         p[n] = '\0';
884 
885         hwc = &ha->dns_wc_head;
886         keys = &ha->dns_wc_head_hash[k];
887 
888     } else {
889 
890         /* convert "www.example.*" to "www.example\0" */
891 
892         last++;
893 
894         p = ngx_palloc(ha->temp_pool, last);
895         if (p == NULL) {
896             return NGX_ERROR;
897         }
898 
899         ngx_cpystrn(p, key->data, last);
900 
901         hwc = &ha->dns_wc_tail;
902         keys = &ha->dns_wc_tail_hash[k];
903     }
904 
905 
906     hk = ngx_array_push(hwc);
907     if (hk == NULL) {
908         return NGX_ERROR;
909     }
910 
911     hk->key.len = last - 1;
912     hk->key.data = p;
913     hk->key_hash = 0;
914     hk->value = value;
915 
916 
917     /* check conflicts in wildcard hash */
918 
919     name = keys->elts;
920 
921     if (name) {
922         len = last - skip;
923 
924         for (i = 0; i < keys->nelts; i++) {
925             if (len != name[i].len) {
926                 continue;
927             }
928 
929             if (ngx_strncmp(key->data + skip, name[i].data, len) == 0) {
930                 return NGX_BUSY;
931             }
932         }
933 
934     } else {
935         if (ngx_array_init(keys, ha->temp_pool, 4, sizeof(ngx_str_t)) != NGX_OK)
936         {
937             return NGX_ERROR;
938         }
939     }
940 
941     name = ngx_array_push(keys);
942     if (name == NULL) {
943         return NGX_ERROR;
944     }
945 
946     name->len = last - skip;
947     name->data = ngx_palloc(ha->temp_pool, name->len);
948     if (name->data == NULL) {
949         return NGX_ERROR;
950     }
951 
952     ngx_memcpy(name->data, key->data + skip, name->len);
953 
954     return NGX_OK;
955 }
956 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.