///< for talloc reasons.
} mltl_module_instance_t;
-/** This causes the module_list code to skip bootstrapping for thread-local modules
- */
-static int mltl_mlg_data_add(module_instance_t *mi)
-{
- mi->state |= MODULE_INSTANCE_BOOTSTRAPPED;
- return 0;
-}
-
static void mltl_mlg_data_del(module_instance_t *mi)
{
mltl_module_instance_t *mltl_mi = (mltl_module_instance_t *)talloc_get_type_abort(mi, module_instance_t);
*/
module_list_type_t const module_list_type_thread_local = {
.inst_size = sizeof(mltl_module_instance_t),
-
- .data_add = mltl_mlg_data_add,
.data_del = mltl_mlg_data_del,
.thread = {
}
};
+/** Print debugging information for a module
+ *
+ * @param[in] mi Module instance to print.
+ */
+void module_instance_debug(module_instance_t const *mi)
+{
+ FR_FAULT_LOG("%s (%p) {", mi->name, mi);
+ FR_FAULT_LOG(" type : %s", fr_table_str_by_value(dl_module_type_prefix, mi->module->type, "<invalid>"));
+ if (mi->parent) {
+ FR_FAULT_LOG(" parent : \"%s\" (%p)", mi->parent->name, mi->parent);
+ }
+ FR_FAULT_LOG(" bootstrapped : %s", mi->state & MODULE_INSTANCE_BOOTSTRAPPED ? "yes" : "no");
+ FR_FAULT_LOG(" instantiated : %s", mi->state & MODULE_INSTANCE_INSTANTIATED ? "yes" : "no");
+ FR_FAULT_LOG(" boot : %p", mi->boot);
+ FR_FAULT_LOG(" data : %p", mi->data);
+ FR_FAULT_LOG(" conf : %p", mi->conf);
+ FR_FAULT_LOG("}");
+}
+
+/** Print the contents of a module list
+ *
+ */
+void module_list_debug(module_list_t const *ml)
+{
+ module_instance_t const *inst;
+ fr_rb_iter_inorder_t iter;
+
+ FR_FAULT_LOG("Module list \"%s\" (%p) {", ml->name, ml);
+ FR_FAULT_LOG(" phase masked:");
+ FR_FAULT_LOG(" bootstrap : %s", ml->mask & MODULE_INSTANCE_BOOTSTRAPPED ? "yes" : "no");
+ FR_FAULT_LOG(" instantiate : %s", ml->mask & MODULE_INSTANCE_INSTANTIATED ? "yes" : "no");
+ FR_FAULT_LOG(" thread : %s", ml->mask & MODULE_INSTANCE_INSTANTIATED ? "yes" : "no");
+ FR_FAULT_LOG("}");
+ /*
+ * Modules are printed in the same order
+ * they would be bootstrapped or inserted
+ * into the tree.
+ */
+ for (inst = fr_rb_iter_init_inorder(&iter, ml->name_tree);
+ inst;
+ inst = fr_rb_iter_next_inorder(&iter)) {
+ module_instance_debug(inst);
+ }
+}
+
/** Protect module data
*
* @param[in] pool to protect
*/
int modules_instantiate(module_list_t const *ml)
{
- void *instance;
+ void *inst;
fr_rb_iter_inorder_t iter;
DEBUG2("#### Instantiating %s modules ####", ml->name);
- for (instance = fr_rb_iter_init_inorder(&iter, ml->name_tree);
- instance;
- instance = fr_rb_iter_next_inorder(&iter)) {
- module_instance_t *mi = talloc_get_type_abort(instance, module_instance_t);
+ for (inst = fr_rb_iter_init_inorder(&iter, ml->name_tree);
+ inst;
+ inst = fr_rb_iter_next_inorder(&iter)) {
+ module_instance_t *mi = talloc_get_type_abort(inst, module_instance_t);
if (module_instantiate(mi) < 0) return -1;
}
return 0;
}
+/** Should we bootstrap this module instance?
+ *
+ * @param[in] mi to check.
+ * @return
+ * - true if the module instance should be bootstrapped.
+ * - false if the module instance has already been bootstrapped.
+ */
+bool module_instance_skip_bootstrap(module_instance_t *mi)
+{
+ return ((mi->state | mi->ml->mask) & MODULE_INSTANCE_BOOTSTRAPPED);
+}
+
+/** Should we instantiate this module instance?
+ *
+ * @param[in] mi to check.
+ * @return
+ * - true if the module instance should be instantiated.
+ * - false if the module instance has already been instantiated.
+ */
+bool module_instance_skip_instantiate(module_instance_t *mi)
+{
+ return ((mi->state | mi->ml->mask) & MODULE_INSTANCE_INSTANTIATED);
+}
+
+/** Should we instantiate this module instance in a new thread?
+ *
+ * @param[in] mi to check.
+ * @return
+ * - true if the module instance should be instantiated in a new thread.
+ * - false if the module instance has already been instantiated in a new thread.
+ */
+bool module_instance_skip_thread_instantiate(module_instance_t *mi)
+{
+ return ((mi->state | mi->ml->mask) & MODULE_INSTANCE_NO_THREAD_INSTANTIATE);
+}
+
+/** Set a new bootstrap/instantiate state for a list
+ *
+ * @param[in] ml To set the state for.
+ * @param[in] mask New state.
+ */
+void module_list_mask_set(module_list_t *ml, module_instance_state_t mask)
+{
+ ml->mask = mask;
+}
+
/** Allocate a new module list
*
* This is used to instantiate and destroy modules in distinct phases
/** @name Module instance state
* @{
*/
- module_instance_state_t mask; //!< Prevent phases from being executed.
module_instance_state_t state; //!< What's been done with this module so far.
CONF_SECTION *conf; //!< Module's instance configuration.
/** @} */
uint64_t active_callers; //! number of active callers. i.e. number of current yields
};
-/** Should we bootstrap this module instance?
- *
- * @param[in] mi to check.
- * @return
- * - true if the module instance should be bootstrapped.
- * - false if the module instance has already been bootstrapped.
- */
-static inline bool module_instance_skip_bootstrap(module_instance_t *mi)
-{
- return ((mi->state | mi->mask) & MODULE_INSTANCE_BOOTSTRAPPED);
-}
-
-/** Should we instantiate this module instance?
- *
- * @param[in] mi to check.
- * @return
- * - true if the module instance should be instantiated.
- * - false if the module instance has already been instantiated.
- */
-static inline bool module_instance_skip_instantiate(module_instance_t *mi)
-{
- return ((mi->state | mi->mask) & MODULE_INSTANCE_INSTANTIATED);
-}
-
-/** Should we instantiate this module instance in a new thread?
- *
- * @param[in] mi to check.
- * @return
- * - true if the module instance should be instantiated in a new thread.
- * - false if the module instance has already been instantiated in a new thread.
- */
-static inline bool module_instance_skip_thread_instantiate(module_instance_t *mi)
-{
- return ((mi->state | mi->mask) & MODULE_INSTANCE_NO_THREAD_INSTANTIATE);
-}
-
/** Callback to retrieve thread-local data for a module
*
* @param[in] mi to add data to (use mi->ml for the module list).
* This allows modules to be instantiated and freed in phases,
* i.e. proto modules before rlm modules.
*/
-struct module_list_s {
- uint32_t last_number; //!< Last identifier assigned to a module instance.
+struct module_list_s
+{
char const *name; //!< Friendly list identifier.
+ module_instance_state_t mask; //!< Prevent phases from being executed.
+
+ uint32_t last_number; //!< Last identifier assigned to a module instance.
fr_rb_tree_t *name_tree; //!< Modules indexed by name.
fr_rb_tree_t *data_tree; //!< Modules indexed by data.
fr_heap_t *inst_heap; //!< Heap of module instances.
CONF_ITEM *ci, UNUSED conf_parser_t const *rule) CC_HINT(warn_unused_result);
/** @} */
+/** @name Debugging functions
+ *
+ * @{
+ */
+void module_instance_debug(module_instance_t const *mi) CC_HINT(nonnull);
+
+void module_list_debug(module_list_t const *ml) CC_HINT(nonnull);
+ /** @} */
+
/** @name Module and module thread lookup
*
* @{
extern module_list_type_t const module_list_type_thread_local; //!< Initialise a thread-local module, which is only used in a single thread.
/** @} */
+/** @name Control which phases are skipped (if any)
+ * @{
+ */
+bool module_instance_skip_bootstrap(module_instance_t *mi);
+
+bool module_instance_skip_instantiate(module_instance_t *mi);
+
+bool module_instance_skip_thread_instantiate(module_instance_t *mi);
+
+void module_list_mask_set(module_list_t *ml, module_instance_state_t mask);
+/** @} */
+
module_list_t *module_list_alloc(TALLOC_CTX *ctx, module_list_type_t const *type, char const *name)
CC_HINT(nonnull(2,3)) CC_HINT(warn_unused_result);