comparison src/core/ngx_module.c @ 6383:85dea406e18f

Dynamic modules. The auto/module script is extended to understand ngx_module_link=DYNAMIC. When set, it links the module as a shared object rather than statically into nginx binary. The module can later be loaded using the "load_module" directive. New auto/module parameter ngx_module_order allows to define module loading order in complex cases. By default the order is set based on ngx_module_type. 3rd party modules can be compiled dynamically using the --add-dynamic-module configure option, which will preset ngx_module_link to "DYNAMIC" before calling the module config script. Win32 support is rudimentary, and only works when using MinGW gcc (which is able to handle exports/imports automatically). In collaboration with Ruslan Ermilov.
author Maxim Dounin <mdounin@mdounin.ru>
date Thu, 04 Feb 2016 20:25:29 +0300
parents cf5e822cf470
children 5fe617f38222
comparison
equal deleted inserted replaced
6382:392959224560 6383:85dea406e18f
8 8
9 #include <ngx_config.h> 9 #include <ngx_config.h>
10 #include <ngx_core.h> 10 #include <ngx_core.h>
11 11
12 12
13 ngx_uint_t ngx_max_module; 13 #define NGX_MAX_DYNAMIC_MODULES 128
14
15
16 static ngx_uint_t ngx_module_index(ngx_cycle_t *cycle);
17 static ngx_uint_t ngx_module_ctx_index(ngx_cycle_t *cycle, ngx_uint_t type,
18 ngx_uint_t index);
19
20
21 ngx_uint_t ngx_max_module;
22 static ngx_uint_t ngx_modules_n;
14 23
15 24
16 ngx_int_t 25 ngx_int_t
17 ngx_preinit_modules() 26 ngx_preinit_modules()
18 { 27 {
19 ngx_uint_t i; 28 ngx_uint_t i;
20 29
21 ngx_max_module = 0; 30 ngx_max_module = 0;
22 for (i = 0; ngx_modules[i]; i++) { 31 for (i = 0; ngx_modules[i]; i++) {
23 ngx_modules[i]->index = ngx_max_module++; 32 ngx_modules[i]->index = i;
24 } 33 ngx_modules[i]->name = ngx_module_names[i];
34 }
35
36 ngx_modules_n = i;
37 ngx_max_module = ngx_modules_n + NGX_MAX_DYNAMIC_MODULES;
38
39 return NGX_OK;
40 }
41
42
43 ngx_int_t
44 ngx_cycle_modules(ngx_cycle_t *cycle)
45 {
46 /*
47 * create a list of modules to be used for this cycle,
48 * copy static modules to it
49 */
50
51 cycle->modules = ngx_pcalloc(cycle->pool, (ngx_max_module + 1)
52 * sizeof(ngx_module_t *));
53 if (cycle->modules == NULL) {
54 return NGX_ERROR;
55 }
56
57 ngx_memcpy(cycle->modules, ngx_modules,
58 ngx_modules_n * sizeof(ngx_module_t *));
59
60 cycle->modules_n = ngx_modules_n;
25 61
26 return NGX_OK; 62 return NGX_OK;
27 } 63 }
28 64
29 65
45 81
46 82
47 ngx_int_t 83 ngx_int_t
48 ngx_count_modules(ngx_cycle_t *cycle, ngx_uint_t type) 84 ngx_count_modules(ngx_cycle_t *cycle, ngx_uint_t type)
49 { 85 {
50 ngx_uint_t i, max; 86 ngx_uint_t i, next, max;
51 87 ngx_module_t *module;
88
89 next = 0;
52 max = 0; 90 max = 0;
53 91
54 /* count appropriate modules, set up their indices */ 92 /* count appropriate modules, set up their indices */
55 93
56 for (i = 0; cycle->modules[i]; i++) { 94 for (i = 0; cycle->modules[i]; i++) {
57 if (cycle->modules[i]->type != type) { 95 module = cycle->modules[i];
96
97 if (module->type != type) {
58 continue; 98 continue;
59 } 99 }
60 100
61 cycle->modules[i]->ctx_index = max++; 101 if (module->ctx_index != NGX_MODULE_UNSET_INDEX) {
62 } 102
63 103 /* if ctx_index was assigned, preserve it */
64 return max; 104
65 } 105 if (module->ctx_index > max) {
106 max = module->ctx_index;
107 }
108
109 if (module->ctx_index == next) {
110 next++;
111 }
112
113 continue;
114 }
115
116 /* search for some free index */
117
118 module->ctx_index = ngx_module_ctx_index(cycle, type, next);
119
120 if (module->ctx_index > max) {
121 max = module->ctx_index;
122 }
123
124 next = module->ctx_index + 1;
125 }
126
127 /*
128 * make sure the number returned is big enough for previous
129 * cycle as well, else there will be problems if the number
130 * will be stored in a global variable (as it's used to be)
131 * and we'll have to roll back to the previous cycle
132 */
133
134 if (cycle->old_cycle && cycle->old_cycle->modules) {
135
136 for (i = 0; cycle->old_cycle->modules[i]; i++) {
137 module = cycle->old_cycle->modules[i];
138
139 if (module->type != type) {
140 continue;
141 }
142
143 if (module->ctx_index > max) {
144 max = module->ctx_index;
145 }
146 }
147 }
148
149 /* prevent loading of additional modules */
150
151 cycle->modules_used = 1;
152
153 return max + 1;
154 }
155
156
157 ngx_int_t
158 ngx_add_module(ngx_conf_t *cf, ngx_str_t *file, ngx_module_t *module,
159 char **order)
160 {
161 void *rv;
162 ngx_uint_t i, m, before;
163 ngx_core_module_t *core_module;
164
165 if (cf->cycle->modules_n >= ngx_max_module) {
166 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
167 "too many modules loaded");
168 return NGX_ERROR;
169 }
170
171 if (module->version != nginx_version) {
172 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
173 "module \"%V\" version %ui instead of %ui",
174 file, module->version, nginx_version);
175 return NGX_ERROR;
176 }
177
178 if (ngx_strcmp(module->signature, NGX_MODULE_SIGNATURE) != 0) {
179 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
180 "module \"%V\" is not binary compatible",
181 file);
182 return NGX_ERROR;
183 }
184
185 for (m = 0; cf->cycle->modules[m]; m++) {
186 if (ngx_strcmp(cf->cycle->modules[m]->name, module->name) == 0) {
187 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
188 "module \"%s\" is already loaded",
189 module->name);
190 return NGX_ERROR;
191 }
192 }
193
194 /*
195 * if the module wasn't previously loaded, assign an index
196 */
197
198 if (module->index == NGX_MODULE_UNSET_INDEX) {
199 module->index = ngx_module_index(cf->cycle);
200
201 if (module->index >= ngx_max_module) {
202 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
203 "too many modules loaded");
204 return NGX_ERROR;
205 }
206 }
207
208 /*
209 * put the module into the cycle->modules array
210 */
211
212 before = cf->cycle->modules_n;
213
214 if (order) {
215 for (i = 0; order[i]; i++) {
216 if (ngx_strcmp(order[i], module->name) == 0) {
217 i++;
218 break;
219 }
220 }
221
222 for ( /* void */ ; order[i]; i++) {
223
224 #if 0
225 ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0,
226 "module: %s before %s",
227 module->name, order[i]);
228 #endif
229
230 for (m = 0; m < before; m++) {
231 if (ngx_strcmp(cf->cycle->modules[m]->name, order[i]) == 0) {
232
233 ngx_log_debug3(NGX_LOG_DEBUG_CORE, cf->log, 0,
234 "module: %s before %s:%i",
235 module->name, order[i], m);
236
237 before = m;
238 break;
239 }
240 }
241 }
242 }
243
244 /* put the module before modules[before] */
245
246 if (before != cf->cycle->modules_n) {
247 ngx_memmove(&cf->cycle->modules[before + 1],
248 &cf->cycle->modules[before],
249 (cf->cycle->modules_n - before) * sizeof(ngx_module_t *));
250 }
251
252 cf->cycle->modules[before] = module;
253 cf->cycle->modules_n++;
254
255 if (module->type == NGX_CORE_MODULE) {
256
257 /*
258 * we are smart enough to initialize core modules;
259 * other modules are expected to be loaded before
260 * initialization - e.g., http modules must be loaded
261 * before http{} block
262 */
263
264 core_module = module->ctx;
265
266 if (core_module->create_conf) {
267 rv = core_module->create_conf(cf->cycle);
268 if (rv == NULL) {
269 return NGX_ERROR;
270 }
271
272 cf->cycle->conf_ctx[module->index] = rv;
273 }
274 }
275
276 return NGX_OK;
277 }
278
279
280 static ngx_uint_t
281 ngx_module_index(ngx_cycle_t *cycle)
282 {
283 ngx_uint_t i, index;
284 ngx_module_t *module;
285
286 index = 0;
287
288 again:
289
290 /* find an unused index */
291
292 for (i = 0; cycle->modules[i]; i++) {
293 module = cycle->modules[i];
294
295 if (module->index == index) {
296 index++;
297 goto again;
298 }
299 }
300
301 /* check previous cycle */
302
303 if (cycle->old_cycle && cycle->old_cycle->modules) {
304
305 for (i = 0; cycle->old_cycle->modules[i]; i++) {
306 module = cycle->old_cycle->modules[i];
307
308 if (module->index == index) {
309 index++;
310 goto again;
311 }
312 }
313 }
314
315 return index;
316 }
317
318
319 static ngx_uint_t
320 ngx_module_ctx_index(ngx_cycle_t *cycle, ngx_uint_t type, ngx_uint_t index)
321 {
322 ngx_uint_t i;
323 ngx_module_t *module;
324
325 again:
326
327 /* find an unused ctx_index */
328
329 for (i = 0; cycle->modules[i]; i++) {
330 module = cycle->modules[i];
331
332 if (module->type != type) {
333 continue;
334 }
335
336 if (module->ctx_index == index) {
337 index++;
338 goto again;
339 }
340 }
341
342 /* check previous cycle */
343
344 if (cycle->old_cycle && cycle->old_cycle->modules) {
345
346 for (i = 0; cycle->old_cycle->modules[i]; i++) {
347 module = cycle->old_cycle->modules[i];
348
349 if (module->type != type) {
350 continue;
351 }
352
353 if (module->ctx_index == index) {
354 index++;
355 goto again;
356 }
357 }
358 }
359
360 return index;
361 }