Mercurial > hg > nginx-quic
comparison src/http/ngx_http.c @ 2027:f321b59ae0e9
locations tree
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sat, 24 May 2008 14:14:13 +0000 |
parents | 638bbe2464f3 |
children | c036922f6f07 |
comparison
equal
deleted
inserted
replaced
2026:72db8932f782 | 2027:f321b59ae0e9 |
---|---|
25 ngx_http_listen_t *listen); | 25 ngx_http_listen_t *listen); |
26 static ngx_int_t ngx_http_add_names(ngx_conf_t *cf, | 26 static ngx_int_t ngx_http_add_names(ngx_conf_t *cf, |
27 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_in_addr_t *in_addr); | 27 ngx_http_core_srv_conf_t *cscf, ngx_http_conf_in_addr_t *in_addr); |
28 | 28 |
29 static char *ngx_http_merge_locations(ngx_conf_t *cf, | 29 static char *ngx_http_merge_locations(ngx_conf_t *cf, |
30 ngx_array_t *locations, void **loc_conf, ngx_http_module_t *module, | 30 ngx_queue_t *locations, void **loc_conf, ngx_http_module_t *module, |
31 ngx_uint_t ctx_index); | 31 ngx_uint_t ctx_index); |
32 static ngx_int_t ngx_http_init_locations(ngx_conf_t *cf, | |
33 ngx_http_core_srv_conf_t *cscf, ngx_http_core_loc_conf_t *pclcf); | |
34 static ngx_int_t ngx_http_init_static_location_trees(ngx_conf_t *cf, | |
35 ngx_http_core_loc_conf_t *pclcf); | |
36 static ngx_int_t ngx_http_cmp_locations(const ngx_queue_t *one, | |
37 const ngx_queue_t *two); | |
38 static ngx_int_t ngx_http_join_exact_locations(ngx_conf_t *cf, | |
39 ngx_queue_t *locations); | |
40 static void ngx_http_create_locations_list(ngx_queue_t *locations, | |
41 ngx_queue_t *q); | |
42 static ngx_http_location_tree_node_t * | |
43 ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations, | |
44 size_t prefix); | |
32 | 45 |
33 static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf, | 46 static ngx_int_t ngx_http_optimize_servers(ngx_conf_t *cf, |
34 ngx_http_core_main_conf_t *cmcf, ngx_array_t *in_ports); | 47 ngx_http_core_main_conf_t *cmcf, ngx_array_t *in_ports); |
35 static ngx_int_t ngx_http_cmp_conf_in_addrs(const void *one, const void *two); | 48 static ngx_int_t ngx_http_cmp_conf_in_addrs(const void *one, const void *two); |
36 static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one, | 49 static int ngx_libc_cdecl ngx_http_cmp_dns_wildcards(const void *one, |
89 ngx_uint_t mi, m, s; | 102 ngx_uint_t mi, m, s; |
90 ngx_conf_t pcf; | 103 ngx_conf_t pcf; |
91 ngx_array_t in_ports; | 104 ngx_array_t in_ports; |
92 ngx_http_module_t *module; | 105 ngx_http_module_t *module; |
93 ngx_http_conf_ctx_t *ctx; | 106 ngx_http_conf_ctx_t *ctx; |
107 ngx_http_core_loc_conf_t *clcf; | |
94 ngx_http_core_srv_conf_t **cscfp; | 108 ngx_http_core_srv_conf_t **cscfp; |
95 ngx_http_core_main_conf_t *cmcf; | 109 ngx_http_core_main_conf_t *cmcf; |
96 | 110 |
97 /* the main http context */ | 111 /* the main http context */ |
98 | 112 |
204 cf->module_type = NGX_HTTP_MODULE; | 218 cf->module_type = NGX_HTTP_MODULE; |
205 cf->cmd_type = NGX_HTTP_MAIN_CONF; | 219 cf->cmd_type = NGX_HTTP_MAIN_CONF; |
206 rv = ngx_conf_parse(cf, NULL); | 220 rv = ngx_conf_parse(cf, NULL); |
207 | 221 |
208 if (rv != NGX_CONF_OK) { | 222 if (rv != NGX_CONF_OK) { |
209 *cf = pcf; | 223 goto failed; |
210 return rv; | |
211 } | 224 } |
212 | 225 |
213 /* | 226 /* |
214 * init http{} main_conf's, merge the server{}s' srv_conf's | 227 * init http{} main_conf's, merge the server{}s' srv_conf's |
215 * and its location{}s' loc_conf's | 228 * and its location{}s' loc_conf's |
229 /* init http{} main_conf's */ | 242 /* init http{} main_conf's */ |
230 | 243 |
231 if (module->init_main_conf) { | 244 if (module->init_main_conf) { |
232 rv = module->init_main_conf(cf, ctx->main_conf[mi]); | 245 rv = module->init_main_conf(cf, ctx->main_conf[mi]); |
233 if (rv != NGX_CONF_OK) { | 246 if (rv != NGX_CONF_OK) { |
234 *cf = pcf; | 247 goto failed; |
235 return rv; | |
236 } | 248 } |
237 } | 249 } |
238 | 250 |
239 for (s = 0; s < cmcf->servers.nelts; s++) { | 251 for (s = 0; s < cmcf->servers.nelts; s++) { |
240 | 252 |
241 /* merge the server{}s' srv_conf's */ | 253 /* merge the server{}s' srv_conf's */ |
242 | 254 |
243 if (module->merge_srv_conf) { | 255 if (module->merge_srv_conf) { |
244 rv = module->merge_srv_conf(cf, | 256 rv = module->merge_srv_conf(cf, ctx->srv_conf[mi], |
245 ctx->srv_conf[mi], | |
246 cscfp[s]->ctx->srv_conf[mi]); | 257 cscfp[s]->ctx->srv_conf[mi]); |
247 if (rv != NGX_CONF_OK) { | 258 if (rv != NGX_CONF_OK) { |
248 *cf = pcf; | 259 goto failed; |
249 return rv; | |
250 } | 260 } |
251 } | 261 } |
252 | 262 |
253 if (module->merge_loc_conf) { | 263 if (module->merge_loc_conf) { |
254 | 264 |
255 /* merge the server{}'s loc_conf */ | 265 /* merge the server{}'s loc_conf */ |
256 | 266 |
257 rv = module->merge_loc_conf(cf, | 267 rv = module->merge_loc_conf(cf, ctx->loc_conf[mi], |
258 ctx->loc_conf[mi], | |
259 cscfp[s]->ctx->loc_conf[mi]); | 268 cscfp[s]->ctx->loc_conf[mi]); |
260 if (rv != NGX_CONF_OK) { | 269 if (rv != NGX_CONF_OK) { |
261 *cf = pcf; | 270 goto failed; |
262 return rv; | |
263 } | 271 } |
264 | 272 |
265 /* merge the locations{}' loc_conf's */ | 273 /* merge the locations{}' loc_conf's */ |
266 | 274 |
267 rv = ngx_http_merge_locations(cf, &cscfp[s]->locations, | 275 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index]; |
276 | |
277 rv = ngx_http_merge_locations(cf, clcf->locations, | |
268 cscfp[s]->ctx->loc_conf, | 278 cscfp[s]->ctx->loc_conf, |
269 module, mi); | 279 module, mi); |
270 if (rv != NGX_CONF_OK) { | 280 if (rv != NGX_CONF_OK) { |
271 *cf = pcf; | 281 goto failed; |
272 return rv; | |
273 } | 282 } |
274 } | 283 } |
284 } | |
285 } | |
286 | |
287 | |
288 /* create location trees */ | |
289 | |
290 for (s = 0; s < cmcf->servers.nelts; s++) { | |
291 | |
292 clcf = cscfp[s]->ctx->loc_conf[ngx_http_core_module.ctx_index]; | |
293 | |
294 if (ngx_http_init_locations(cf, cscfp[s], clcf) != NGX_OK) { | |
295 return NGX_CONF_ERROR; | |
296 } | |
297 | |
298 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) { | |
299 return NGX_CONF_ERROR; | |
275 } | 300 } |
276 } | 301 } |
277 | 302 |
278 | 303 |
279 if (ngx_http_init_phases(cf, cmcf) != NGX_OK) { | 304 if (ngx_http_init_phases(cf, cmcf) != NGX_OK) { |
335 if (ngx_http_optimize_servers(cf, cmcf, &in_ports) != NGX_OK) { | 360 if (ngx_http_optimize_servers(cf, cmcf, &in_ports) != NGX_OK) { |
336 return NGX_CONF_ERROR; | 361 return NGX_CONF_ERROR; |
337 } | 362 } |
338 | 363 |
339 return NGX_CONF_OK; | 364 return NGX_CONF_OK; |
365 | |
366 failed: | |
367 | |
368 *cf = pcf; | |
369 | |
370 return rv; | |
340 } | 371 } |
341 | 372 |
342 | 373 |
343 static ngx_int_t | 374 static ngx_int_t |
344 ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) | 375 ngx_http_init_phases(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf) |
539 ph++; | 570 ph++; |
540 } | 571 } |
541 } | 572 } |
542 | 573 |
543 return NGX_OK; | 574 return NGX_OK; |
575 } | |
576 | |
577 | |
578 static char * | |
579 ngx_http_merge_locations(ngx_conf_t *cf, ngx_queue_t *locations, | |
580 void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index) | |
581 { | |
582 char *rv; | |
583 ngx_queue_t *q; | |
584 ngx_http_core_loc_conf_t *clcf; | |
585 ngx_http_location_queue_t *lq; | |
586 | |
587 if (locations == NULL) { | |
588 return NGX_CONF_OK; | |
589 } | |
590 | |
591 for (q = ngx_queue_head(locations); | |
592 q != ngx_queue_sentinel(locations); | |
593 q = ngx_queue_next(q)) | |
594 { | |
595 lq = (ngx_http_location_queue_t *) q; | |
596 | |
597 clcf = lq->exact ? lq->exact : lq->inclusive; | |
598 | |
599 rv = module->merge_loc_conf(cf, loc_conf[ctx_index], | |
600 clcf->loc_conf[ctx_index]); | |
601 if (rv != NGX_CONF_OK) { | |
602 return rv; | |
603 } | |
604 | |
605 rv = ngx_http_merge_locations(cf, clcf->locations, clcf->loc_conf, | |
606 module, ctx_index); | |
607 if (rv != NGX_CONF_OK) { | |
608 return rv; | |
609 } | |
610 } | |
611 | |
612 return NGX_CONF_OK; | |
613 } | |
614 | |
615 | |
616 static ngx_int_t | |
617 ngx_http_init_locations(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf, | |
618 ngx_http_core_loc_conf_t *pclcf) | |
619 { | |
620 ngx_uint_t n; | |
621 ngx_queue_t *q, *locations, *named, tail; | |
622 ngx_http_core_loc_conf_t *clcf; | |
623 ngx_http_location_queue_t *lq; | |
624 ngx_http_core_loc_conf_t **clcfp; | |
625 #if (NGX_PCRE) | |
626 ngx_uint_t r; | |
627 ngx_queue_t *regex; | |
628 #endif | |
629 | |
630 locations = pclcf->locations; | |
631 | |
632 if (locations == NULL) { | |
633 return NGX_OK; | |
634 } | |
635 | |
636 ngx_queue_sort(locations, ngx_http_cmp_locations); | |
637 | |
638 named = NULL; | |
639 n = 0; | |
640 #if (NGX_PCRE) | |
641 regex = NULL; | |
642 r = 0; | |
643 #endif | |
644 | |
645 for (q = ngx_queue_head(locations); | |
646 q != ngx_queue_sentinel(locations); | |
647 q = ngx_queue_next(q)) | |
648 { | |
649 lq = (ngx_http_location_queue_t *) q; | |
650 | |
651 clcf = lq->exact ? lq->exact : lq->inclusive; | |
652 | |
653 if (ngx_http_init_locations(cf, NULL, clcf) != NGX_OK) { | |
654 return NGX_ERROR; | |
655 } | |
656 | |
657 #if (NGX_PCRE) | |
658 | |
659 if (clcf->regex) { | |
660 r++; | |
661 | |
662 if (regex == NULL) { | |
663 regex = q; | |
664 } | |
665 | |
666 continue; | |
667 } | |
668 | |
669 #endif | |
670 | |
671 if (clcf->named) { | |
672 n++; | |
673 | |
674 if (named == NULL) { | |
675 named = q; | |
676 } | |
677 | |
678 continue; | |
679 } | |
680 | |
681 if (clcf->noname) { | |
682 break; | |
683 } | |
684 } | |
685 | |
686 if (q != ngx_queue_sentinel(locations)) { | |
687 ngx_queue_split(locations, q, &tail); | |
688 } | |
689 | |
690 if (named) { | |
691 clcfp = ngx_palloc(cf->pool, | |
692 (n + 1) * sizeof(ngx_http_core_loc_conf_t **)); | |
693 if (clcfp == NULL) { | |
694 return NGX_ERROR; | |
695 } | |
696 | |
697 cscf->named_locations = clcfp; | |
698 | |
699 for (q = named; | |
700 q != ngx_queue_sentinel(locations); | |
701 q = ngx_queue_next(q)) | |
702 { | |
703 lq = (ngx_http_location_queue_t *) q; | |
704 | |
705 *(clcfp++) = lq->exact; | |
706 } | |
707 | |
708 *clcfp = NULL; | |
709 | |
710 ngx_queue_split(locations, named, &tail); | |
711 } | |
712 | |
713 #if (NGX_PCRE) | |
714 | |
715 if (regex) { | |
716 | |
717 clcfp = ngx_palloc(cf->pool, | |
718 (r + 1) * sizeof(ngx_http_core_loc_conf_t **)); | |
719 if (clcfp == NULL) { | |
720 return NGX_ERROR; | |
721 } | |
722 | |
723 pclcf->regex_locations = clcfp; | |
724 | |
725 for (q = regex; | |
726 q != ngx_queue_sentinel(locations); | |
727 q = ngx_queue_next(q)) | |
728 { | |
729 lq = (ngx_http_location_queue_t *) q; | |
730 | |
731 *(clcfp++) = lq->exact; | |
732 } | |
733 | |
734 *clcfp = NULL; | |
735 | |
736 ngx_queue_split(locations, regex, &tail); | |
737 } | |
738 | |
739 #endif | |
740 | |
741 return NGX_OK; | |
742 } | |
743 | |
744 | |
745 static ngx_int_t | |
746 ngx_http_init_static_location_trees(ngx_conf_t *cf, | |
747 ngx_http_core_loc_conf_t *pclcf) | |
748 { | |
749 ngx_queue_t *q, *locations; | |
750 ngx_http_core_loc_conf_t *clcf; | |
751 ngx_http_location_queue_t *lq; | |
752 | |
753 locations = pclcf->locations; | |
754 | |
755 if (locations == NULL) { | |
756 return NGX_OK; | |
757 } | |
758 | |
759 if (ngx_queue_empty(locations)) { | |
760 return NGX_OK; | |
761 } | |
762 | |
763 for (q = ngx_queue_head(locations); | |
764 q != ngx_queue_sentinel(locations); | |
765 q = ngx_queue_next(q)) | |
766 { | |
767 lq = (ngx_http_location_queue_t *) q; | |
768 | |
769 clcf = lq->exact ? lq->exact : lq->inclusive; | |
770 | |
771 if (ngx_http_init_static_location_trees(cf, clcf) != NGX_OK) { | |
772 return NGX_ERROR; | |
773 } | |
774 } | |
775 | |
776 if (ngx_http_join_exact_locations(cf, locations) != NGX_OK) { | |
777 return NGX_ERROR; | |
778 } | |
779 | |
780 ngx_http_create_locations_list(locations, ngx_queue_head(locations)); | |
781 | |
782 pclcf->static_locations = ngx_http_create_locations_tree(cf, locations, 0); | |
783 if (pclcf->static_locations == NULL) { | |
784 return NGX_ERROR; | |
785 } | |
786 | |
787 return NGX_OK; | |
788 } | |
789 | |
790 | |
791 ngx_int_t | |
792 ngx_http_add_location(ngx_conf_t *cf, ngx_queue_t **locations, | |
793 ngx_http_core_loc_conf_t *clcf) | |
794 { | |
795 ngx_http_location_queue_t *lq; | |
796 | |
797 if (*locations == NULL) { | |
798 *locations = ngx_palloc(cf->temp_pool, | |
799 sizeof(ngx_http_location_queue_t)); | |
800 if (*locations == NULL) { | |
801 return NGX_ERROR; | |
802 } | |
803 | |
804 ngx_queue_init(*locations); | |
805 } | |
806 | |
807 lq = ngx_palloc(cf->temp_pool, sizeof(ngx_http_location_queue_t)); | |
808 if (lq == NULL) { | |
809 return NGX_ERROR; | |
810 } | |
811 | |
812 if (clcf->exact_match | |
813 #if (NGX_PCRE) | |
814 || clcf->regex | |
815 #endif | |
816 || clcf->named || clcf->noname) | |
817 { | |
818 lq->exact = clcf; | |
819 lq->inclusive = NULL; | |
820 | |
821 } else { | |
822 lq->exact = NULL; | |
823 lq->inclusive = clcf; | |
824 } | |
825 | |
826 lq->name = &clcf->name; | |
827 lq->file_name = cf->conf_file->file.name.data; | |
828 lq->line = cf->conf_file->line; | |
829 | |
830 ngx_queue_init(&lq->list); | |
831 | |
832 ngx_queue_insert_tail(*locations, &lq->queue); | |
833 | |
834 return NGX_OK; | |
835 } | |
836 | |
837 | |
838 static ngx_int_t | |
839 ngx_http_cmp_locations(const ngx_queue_t *one, const ngx_queue_t *two) | |
840 { | |
841 ngx_int_t rc; | |
842 ngx_http_core_loc_conf_t *first, *second; | |
843 ngx_http_location_queue_t *lq1, *lq2; | |
844 | |
845 lq1 = (ngx_http_location_queue_t *) one; | |
846 lq2 = (ngx_http_location_queue_t *) two; | |
847 | |
848 first = lq1->exact ? lq1->exact : lq1->inclusive; | |
849 second = lq2->exact ? lq2->exact : lq2->inclusive; | |
850 | |
851 if (first->noname && !second->noname) { | |
852 /* shift no named locations to the end */ | |
853 return 1; | |
854 } | |
855 | |
856 if (!first->noname && second->noname) { | |
857 /* shift no named locations to the end */ | |
858 return -1; | |
859 } | |
860 | |
861 if (first->noname || second->noname) { | |
862 /* do not sort no named locations */ | |
863 return 0; | |
864 } | |
865 | |
866 if (first->named && !second->named) { | |
867 /* shift named locations to the end */ | |
868 return 1; | |
869 } | |
870 | |
871 if (!first->named && second->named) { | |
872 /* shift named locations to the end */ | |
873 return -1; | |
874 } | |
875 | |
876 if (first->named && second->named) { | |
877 return ngx_strcmp(first->name.data, second->name.data); | |
878 } | |
879 | |
880 #if (NGX_PCRE) | |
881 | |
882 if (first->regex && !second->regex) { | |
883 /* shift the regex matches to the end */ | |
884 return 1; | |
885 } | |
886 | |
887 if (!first->regex && second->regex) { | |
888 /* shift the regex matches to the end */ | |
889 return -1; | |
890 } | |
891 | |
892 if (first->regex || second->regex) { | |
893 /* do not sort the regex matches */ | |
894 return 0; | |
895 } | |
896 | |
897 #endif | |
898 | |
899 rc = ngx_strcmp(first->name.data, second->name.data); | |
900 | |
901 if (rc == 0 && !first->exact_match && second->exact_match) { | |
902 /* an exact match must be before the same inclusive one */ | |
903 return 1; | |
904 } | |
905 | |
906 return rc; | |
907 } | |
908 | |
909 | |
910 static ngx_int_t | |
911 ngx_http_join_exact_locations(ngx_conf_t *cf, ngx_queue_t *locations) | |
912 { | |
913 ngx_queue_t *q, *x; | |
914 ngx_http_location_queue_t *lq, *lx; | |
915 | |
916 q = ngx_queue_head(locations); | |
917 | |
918 while (q != ngx_queue_last(locations)) { | |
919 | |
920 x = ngx_queue_next(q); | |
921 | |
922 lq = (ngx_http_location_queue_t *) q; | |
923 lx = (ngx_http_location_queue_t *) x; | |
924 | |
925 if (ngx_strcmp(lq->name->data, lx->name->data) == 0) { | |
926 | |
927 if ((lq->exact && lx->exact) || (lq->inclusive && lx->inclusive)) { | |
928 ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
929 "duplicate location \"%V\" in %s:%ui", | |
930 lx->name, lx->file_name, lx->line); | |
931 | |
932 return NGX_ERROR; | |
933 } | |
934 | |
935 lq->inclusive = lx->inclusive; | |
936 | |
937 ngx_queue_remove(x); | |
938 | |
939 continue; | |
940 } | |
941 | |
942 q = ngx_queue_next(q); | |
943 } | |
944 | |
945 return NGX_OK; | |
946 } | |
947 | |
948 | |
949 static void | |
950 ngx_http_create_locations_list(ngx_queue_t *locations, ngx_queue_t *q) | |
951 { | |
952 u_char *name; | |
953 size_t len; | |
954 ngx_queue_t *x, tail; | |
955 ngx_http_location_queue_t *lq, *lx; | |
956 | |
957 if (q == ngx_queue_last(locations)) { | |
958 return; | |
959 } | |
960 | |
961 lq = (ngx_http_location_queue_t *) q; | |
962 | |
963 if (lq->inclusive == NULL) { | |
964 ngx_http_create_locations_list(locations, ngx_queue_next(q)); | |
965 return; | |
966 } | |
967 | |
968 len = lq->name->len; | |
969 name = lq->name->data; | |
970 | |
971 for (x = ngx_queue_next(q); | |
972 x != ngx_queue_sentinel(locations); | |
973 x = ngx_queue_next(x)) | |
974 { | |
975 lx = (ngx_http_location_queue_t *) x; | |
976 | |
977 if (len > lx->name->len | |
978 || (ngx_strncmp(name, lx->name->data, len) != 0)) | |
979 { | |
980 break; | |
981 } | |
982 } | |
983 | |
984 q = ngx_queue_next(q); | |
985 | |
986 if (q == x) { | |
987 ngx_http_create_locations_list(locations, x); | |
988 return; | |
989 } | |
990 | |
991 ngx_queue_split(locations, q, &tail); | |
992 ngx_queue_add(&lq->list, &tail); | |
993 | |
994 if (x == ngx_queue_sentinel(locations)) { | |
995 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list)); | |
996 return; | |
997 } | |
998 | |
999 ngx_queue_split(&lq->list, x, &tail); | |
1000 ngx_queue_add(locations, &tail); | |
1001 | |
1002 ngx_http_create_locations_list(&lq->list, ngx_queue_head(&lq->list)); | |
1003 | |
1004 ngx_http_create_locations_list(locations, x); | |
1005 } | |
1006 | |
1007 | |
1008 /* | |
1009 * to keep cache locality for left leaf nodes, allocate nodes in following | |
1010 * order: node, left subtree, right subtree, inclusive subtree | |
1011 */ | |
1012 | |
1013 static ngx_http_location_tree_node_t * | |
1014 ngx_http_create_locations_tree(ngx_conf_t *cf, ngx_queue_t *locations, | |
1015 size_t prefix) | |
1016 { | |
1017 size_t len; | |
1018 ngx_queue_t *q, tail; | |
1019 ngx_http_location_queue_t *lq; | |
1020 ngx_http_location_tree_node_t *node; | |
1021 | |
1022 q = ngx_queue_middle(locations); | |
1023 | |
1024 lq = (ngx_http_location_queue_t *) q; | |
1025 len = lq->name->len - prefix; | |
1026 | |
1027 node = ngx_pcalloc(cf->pool, | |
1028 offsetof(ngx_http_location_tree_node_t, name) + len); | |
1029 if (node == NULL) { | |
1030 return NULL; | |
1031 } | |
1032 | |
1033 node->exact = lq->exact; | |
1034 node->inclusive = lq->inclusive; | |
1035 | |
1036 node->auto_redirect = (u_char) ((lq->exact && lq->exact->auto_redirect) | |
1037 || (lq->inclusive && lq->inclusive->auto_redirect)); | |
1038 | |
1039 node->len = (u_char) len; | |
1040 ngx_memcpy(node->name, &lq->name->data[prefix], len); | |
1041 | |
1042 ngx_queue_split(locations, q, &tail); | |
1043 | |
1044 if (ngx_queue_empty(locations)) { | |
1045 /* | |
1046 * ngx_queue_split() insures that if left part is empty, | |
1047 * then right one is empty too | |
1048 */ | |
1049 goto inclusive; | |
1050 } | |
1051 | |
1052 node->left = ngx_http_create_locations_tree(cf, locations, prefix); | |
1053 if (node->left == NULL) { | |
1054 return NULL; | |
1055 } | |
1056 | |
1057 ngx_queue_remove(q); | |
1058 | |
1059 if (ngx_queue_empty(&tail)) { | |
1060 goto inclusive; | |
1061 } | |
1062 | |
1063 node->right = ngx_http_create_locations_tree(cf, &tail, prefix); | |
1064 if (node->right == NULL) { | |
1065 return NULL; | |
1066 } | |
1067 | |
1068 inclusive: | |
1069 | |
1070 if (ngx_queue_empty(&lq->list)) { | |
1071 return node; | |
1072 } | |
1073 | |
1074 node->tree = ngx_http_create_locations_tree(cf, &lq->list, prefix + len); | |
1075 if (node->tree == NULL) { | |
1076 return NULL; | |
1077 } | |
1078 | |
1079 return node; | |
544 } | 1080 } |
545 | 1081 |
546 | 1082 |
547 static ngx_int_t | 1083 static ngx_int_t |
548 ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers, | 1084 ngx_http_init_server_lists(ngx_conf_t *cf, ngx_array_t *servers, |
754 | 1290 |
755 return NGX_OK; | 1291 return NGX_OK; |
756 } | 1292 } |
757 | 1293 |
758 | 1294 |
759 static char * | |
760 ngx_http_merge_locations(ngx_conf_t *cf, ngx_array_t *locations, | |
761 void **loc_conf, ngx_http_module_t *module, ngx_uint_t ctx_index) | |
762 { | |
763 char *rv; | |
764 ngx_uint_t i; | |
765 ngx_http_core_loc_conf_t **clcfp; | |
766 | |
767 clcfp = locations->elts; | |
768 | |
769 for (i = 0; i < locations->nelts; i++) { | |
770 rv = module->merge_loc_conf(cf, loc_conf[ctx_index], | |
771 clcfp[i]->loc_conf[ctx_index]); | |
772 if (rv != NGX_CONF_OK) { | |
773 return rv; | |
774 } | |
775 | |
776 if (clcfp[i]->locations == NULL) { | |
777 continue; | |
778 } | |
779 | |
780 rv = ngx_http_merge_locations(cf, clcfp[i]->locations, | |
781 clcfp[i]->loc_conf, module, ctx_index); | |
782 if (rv != NGX_CONF_OK) { | |
783 return rv; | |
784 } | |
785 } | |
786 | |
787 return NGX_CONF_OK; | |
788 } | |
789 | |
790 | |
791 static ngx_int_t | 1295 static ngx_int_t |
792 ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, | 1296 ngx_http_optimize_servers(ngx_conf_t *cf, ngx_http_core_main_conf_t *cmcf, |
793 ngx_array_t *in_ports) | 1297 ngx_array_t *in_ports) |
794 { | 1298 { |
795 ngx_int_t rc; | 1299 ngx_int_t rc; |