src/core/ngx_module.c - nginx source code

Global variables defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Maxim Dounin
  4. * Copyright (C) Nginx, Inc.
  5. */


  6. #include <ngx_config.h>
  7. #include <ngx_core.h>


  8. #define NGX_MAX_DYNAMIC_MODULES  128


  9. static ngx_uint_t ngx_module_index(ngx_cycle_t *cycle);
  10. static ngx_uint_t ngx_module_ctx_index(ngx_cycle_t *cycle, ngx_uint_t type,
  11.     ngx_uint_t index);


  12. ngx_uint_t         ngx_max_module;
  13. static ngx_uint_t  ngx_modules_n;


  14. ngx_int_t
  15. ngx_preinit_modules(void)
  16. {
  17.     ngx_uint_t  i;

  18.     for (i = 0; ngx_modules[i]; i++) {
  19.         ngx_modules[i]->index = i;
  20.         ngx_modules[i]->name = ngx_module_names[i];
  21.     }

  22.     ngx_modules_n = i;
  23.     ngx_max_module = ngx_modules_n + NGX_MAX_DYNAMIC_MODULES;

  24.     return NGX_OK;
  25. }


  26. ngx_int_t
  27. ngx_cycle_modules(ngx_cycle_t *cycle)
  28. {
  29.     /*
  30.      * create a list of modules to be used for this cycle,
  31.      * copy static modules to it
  32.      */

  33.     cycle->modules = ngx_pcalloc(cycle->pool, (ngx_max_module + 1)
  34.                                               * sizeof(ngx_module_t *));
  35.     if (cycle->modules == NULL) {
  36.         return NGX_ERROR;
  37.     }

  38.     ngx_memcpy(cycle->modules, ngx_modules,
  39.                ngx_modules_n * sizeof(ngx_module_t *));

  40.     cycle->modules_n = ngx_modules_n;

  41.     return NGX_OK;
  42. }


  43. ngx_int_t
  44. ngx_init_modules(ngx_cycle_t *cycle)
  45. {
  46.     ngx_uint_t  i;

  47.     for (i = 0; cycle->modules[i]; i++) {
  48.         if (cycle->modules[i]->init_module) {
  49.             if (cycle->modules[i]->init_module(cycle) != NGX_OK) {
  50.                 return NGX_ERROR;
  51.             }
  52.         }
  53.     }

  54.     return NGX_OK;
  55. }


  56. ngx_int_t
  57. ngx_count_modules(ngx_cycle_t *cycle, ngx_uint_t type)
  58. {
  59.     ngx_uint_t     i, next, max;
  60.     ngx_module_t  *module;

  61.     next = 0;
  62.     max = 0;

  63.     /* count appropriate modules, set up their indices */

  64.     for (i = 0; cycle->modules[i]; i++) {
  65.         module = cycle->modules[i];

  66.         if (module->type != type) {
  67.             continue;
  68.         }

  69.         if (module->ctx_index != NGX_MODULE_UNSET_INDEX) {

  70.             /* if ctx_index was assigned, preserve it */

  71.             if (module->ctx_index > max) {
  72.                 max = module->ctx_index;
  73.             }

  74.             if (module->ctx_index == next) {
  75.                 next++;
  76.             }

  77.             continue;
  78.         }

  79.         /* search for some free index */

  80.         module->ctx_index = ngx_module_ctx_index(cycle, type, next);

  81.         if (module->ctx_index > max) {
  82.             max = module->ctx_index;
  83.         }

  84.         next = module->ctx_index + 1;
  85.     }

  86.     /*
  87.      * make sure the number returned is big enough for previous
  88.      * cycle as well, else there will be problems if the number
  89.      * will be stored in a global variable (as it's used to be)
  90.      * and we'll have to roll back to the previous cycle
  91.      */

  92.     if (cycle->old_cycle && cycle->old_cycle->modules) {

  93.         for (i = 0; cycle->old_cycle->modules[i]; i++) {
  94.             module = cycle->old_cycle->modules[i];

  95.             if (module->type != type) {
  96.                 continue;
  97.             }

  98.             if (module->ctx_index > max) {
  99.                 max = module->ctx_index;
  100.             }
  101.         }
  102.     }

  103.     /* prevent loading of additional modules */

  104.     cycle->modules_used = 1;

  105.     return max + 1;
  106. }


  107. ngx_int_t
  108. ngx_add_module(ngx_conf_t *cf, ngx_str_t *file, ngx_module_t *module,
  109.     char **order)
  110. {
  111.     void               *rv;
  112.     ngx_uint_t          i, m, before;
  113.     ngx_core_module_t  *core_module;

  114.     if (cf->cycle->modules_n >= ngx_max_module) {
  115.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  116.                            "too many modules loaded");
  117.         return NGX_ERROR;
  118.     }

  119.     if (module->version != nginx_version) {
  120.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  121.                            "module \"%V\" version %ui instead of %ui",
  122.                            file, module->version, (ngx_uint_t) nginx_version);
  123.         return NGX_ERROR;
  124.     }

  125.     if (ngx_strcmp(module->signature, NGX_MODULE_SIGNATURE) != 0) {
  126.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  127.                            "module \"%V\" is not binary compatible",
  128.                            file);
  129.         return NGX_ERROR;
  130.     }

  131.     for (m = 0; cf->cycle->modules[m]; m++) {
  132.         if (ngx_strcmp(cf->cycle->modules[m]->name, module->name) == 0) {
  133.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  134.                                "module \"%s\" is already loaded",
  135.                                module->name);
  136.             return NGX_ERROR;
  137.         }
  138.     }

  139.     /*
  140.      * if the module wasn't previously loaded, assign an index
  141.      */

  142.     if (module->index == NGX_MODULE_UNSET_INDEX) {
  143.         module->index = ngx_module_index(cf->cycle);

  144.         if (module->index >= ngx_max_module) {
  145.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  146.                                "too many modules loaded");
  147.             return NGX_ERROR;
  148.         }
  149.     }

  150.     /*
  151.      * put the module into the cycle->modules array
  152.      */

  153.     before = cf->cycle->modules_n;

  154.     if (order) {
  155.         for (i = 0; order[i]; i++) {
  156.             if (ngx_strcmp(order[i], module->name) == 0) {
  157.                 i++;
  158.                 break;
  159.             }
  160.         }

  161.         for ( /* void */ ; order[i]; i++) {

  162. #if 0
  163.             ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0,
  164.                            "module: %s before %s",
  165.                            module->name, order[i]);
  166. #endif

  167.             for (m = 0; m < before; m++) {
  168.                 if (ngx_strcmp(cf->cycle->modules[m]->name, order[i]) == 0) {

  169.                     ngx_log_debug3(NGX_LOG_DEBUG_CORE, cf->log, 0,
  170.                                    "module: %s before %s:%i",
  171.                                    module->name, order[i], m);

  172.                     before = m;
  173.                     break;
  174.                 }
  175.             }
  176.         }
  177.     }

  178.     /* put the module before modules[before] */

  179.     if (before != cf->cycle->modules_n) {
  180.         ngx_memmove(&cf->cycle->modules[before + 1],
  181.                     &cf->cycle->modules[before],
  182.                     (cf->cycle->modules_n - before) * sizeof(ngx_module_t *));
  183.     }

  184.     cf->cycle->modules[before] = module;
  185.     cf->cycle->modules_n++;

  186.     if (module->type == NGX_CORE_MODULE) {

  187.         /*
  188.          * we are smart enough to initialize core modules;
  189.          * other modules are expected to be loaded before
  190.          * initialization - e.g., http modules must be loaded
  191.          * before http{} block
  192.          */

  193.         core_module = module->ctx;

  194.         if (core_module->create_conf) {
  195.             rv = core_module->create_conf(cf->cycle);
  196.             if (rv == NULL) {
  197.                 return NGX_ERROR;
  198.             }

  199.             cf->cycle->conf_ctx[module->index] = rv;
  200.         }
  201.     }

  202.     return NGX_OK;
  203. }


  204. static ngx_uint_t
  205. ngx_module_index(ngx_cycle_t *cycle)
  206. {
  207.     ngx_uint_t     i, index;
  208.     ngx_module_t  *module;

  209.     index = 0;

  210. again:

  211.     /* find an unused index */

  212.     for (i = 0; cycle->modules[i]; i++) {
  213.         module = cycle->modules[i];

  214.         if (module->index == index) {
  215.             index++;
  216.             goto again;
  217.         }
  218.     }

  219.     /* check previous cycle */

  220.     if (cycle->old_cycle && cycle->old_cycle->modules) {

  221.         for (i = 0; cycle->old_cycle->modules[i]; i++) {
  222.             module = cycle->old_cycle->modules[i];

  223.             if (module->index == index) {
  224.                 index++;
  225.                 goto again;
  226.             }
  227.         }
  228.     }

  229.     return index;
  230. }


  231. static ngx_uint_t
  232. ngx_module_ctx_index(ngx_cycle_t *cycle, ngx_uint_t type, ngx_uint_t index)
  233. {
  234.     ngx_uint_t     i;
  235.     ngx_module_t  *module;

  236. again:

  237.     /* find an unused ctx_index */

  238.     for (i = 0; cycle->modules[i]; i++) {
  239.         module = cycle->modules[i];

  240.         if (module->type != type) {
  241.             continue;
  242.         }

  243.         if (module->ctx_index == index) {
  244.             index++;
  245.             goto again;
  246.         }
  247.     }

  248.     /* check previous cycle */

  249.     if (cycle->old_cycle && cycle->old_cycle->modules) {

  250.         for (i = 0; cycle->old_cycle->modules[i]; i++) {
  251.             module = cycle->old_cycle->modules[i];

  252.             if (module->type != type) {
  253.                 continue;
  254.             }

  255.             if (module->ctx_index == index) {
  256.                 index++;
  257.                 goto again;
  258.             }
  259.         }
  260.     }

  261.     return index;
  262. }