From 20c77e55901ccd790c592e7d761589ceb2614140 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sat, 6 Mar 2021 17:01:25 -0600 Subject: [PATCH] Progress: controller program. Continue working on the thread support. There are considerable redesigns being implemented. The code is currently in an inconsistent state. --- level_3/controller/c/controller.c | 28 +- level_3/controller/c/controller.h | 4 +- level_3/controller/c/private-common.c | 299 +++++++- level_3/controller/c/private-common.h | 1054 +++++++++++++++++++---------- level_3/controller/c/private-controller.c | 581 ++++++++-------- level_3/controller/c/private-controller.h | 28 +- level_3/controller/c/private-entry.c | 279 ++++---- level_3/controller/c/private-entry.h | 21 +- level_3/controller/c/private-rule.c | 641 ++++++++++-------- level_3/controller/c/private-rule.h | 91 +-- level_3/controller/c/private-thread.c | 247 +++---- level_3/controller/c/private-thread.h | 26 +- 12 files changed, 1992 insertions(+), 1307 deletions(-) diff --git a/level_3/controller/c/controller.c b/level_3/controller/c/controller.c index 026be34..3125899 100644 --- a/level_3/controller/c/controller.c +++ b/level_3/controller/c/controller.c @@ -145,15 +145,12 @@ extern "C" { } controller_setting_t setting = controller_setting_t_initialize; - controller_cache_t cache = controller_cache_t_initialize; - controller_mutex_t mutex = controller_mutex_t_initialize; - controller_thread_t thread = controller_macro_thread_t_initialize(&cache, &cache.action, data, &mutex, &setting, &cache.stack); f_string_static_t entry_name = f_string_static_t_initialize; if (data->remaining.used) { entry_name.string = arguments.argv[data->remaining.array[0]]; - entry_name.used = strnlen(entry_name.string, f_console_length_size); + entry_name.used = strnlen(entry_name.string, f_console_parameter_size); entry_name.size = entry_name.used; } else { @@ -206,7 +203,7 @@ extern "C" { else if (data->parameters[controller_parameter_pid].locations.used) { const f_array_length_t location = data->parameters[controller_parameter_pid].values.array[data->parameters[controller_parameter_pid].values.used - 1]; - if (strnlen(arguments.argv[location], f_console_length_size)) { + if (strnlen(arguments.argv[location], f_console_parameter_size)) { status = fll_path_canonical(arguments.argv[location], &setting.path_pid); if (F_status_is_error(status)) { @@ -257,7 +254,7 @@ extern "C" { else if (data->parameters[controller_parameter_control].locations.used) { const f_array_length_t location = data->parameters[controller_parameter_control].values.array[data->parameters[controller_parameter_control].values.used - 1]; - if (strnlen(arguments.argv[location], f_console_length_size)) { + if (strnlen(arguments.argv[location], f_console_parameter_size)) { status = fll_path_canonical(arguments.argv[location], &setting.path_control); if (F_status_is_error(status)) { @@ -319,7 +316,7 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = controller_thread_main(entry_name, &cache, &thread); + status = controller_thread_main(entry_name, data, &setting); } // ensure a newline is always put at the end of the program execution, unless in quiet mode. @@ -332,12 +329,7 @@ extern "C" { f_signal_close(&data->signal); controller_file_pid_delete(*data, setting.path_pid); - - controller_macro_setting_t_delete_simple(setting) - controller_macro_cache_t_delete_simple(cache) - controller_macro_mutex_t_delete_simple(mutex) - controller_macro_thread_t_delete_simple(thread) - + controller_setting_delete_simple(&setting); controller_delete_data(data); if (status == F_child || status == F_signal) { @@ -355,13 +347,13 @@ extern "C" { #ifndef _di_controller_delete_data_ f_status_t controller_delete_data(controller_data_t *data) { - for (f_string_length_t i = 0; i < controller_total_parameters; i++) { - f_macro_string_lengths_t_delete_simple(data->parameters[i].locations); - f_macro_string_lengths_t_delete_simple(data->parameters[i].locations_sub); - f_macro_string_lengths_t_delete_simple(data->parameters[i].values); + for (f_array_length_t i = 0; i < controller_total_parameters; i++) { + f_macro_array_lengths_t_delete_simple(data->parameters[i].locations); + f_macro_array_lengths_t_delete_simple(data->parameters[i].locations_sub); + f_macro_array_lengths_t_delete_simple(data->parameters[i].values); } // for - f_macro_string_lengths_t_delete_simple(data->remaining); + f_macro_array_lengths_t_delete_simple(data->remaining); f_macro_color_context_t_delete_simple(data->context); return F_none; diff --git a/level_3/controller/c/controller.h b/level_3/controller/c/controller.h index 7721222..789070b 100644 --- a/level_3/controller/c/controller.h +++ b/level_3/controller/c/controller.h @@ -166,7 +166,7 @@ extern "C" { typedef struct { f_console_parameter_t parameters[controller_total_parameters]; - f_string_lengths_t remaining; + f_array_lengths_t remaining; bool process_pipe; f_file_t output; @@ -184,7 +184,7 @@ extern "C" { #define controller_data_t_initialize \ { \ controller_console_parameter_t_initialize, \ - f_string_lengths_t_initialize, \ + f_array_lengths_t_initialize, \ F_false, \ f_macro_file_t_initialize2(f_type_output, f_type_descriptor_output, f_file_flag_write_only), \ fll_error_print_t_initialize, \ diff --git a/level_3/controller/c/private-common.c b/level_3/controller/c/private-common.c index 7488944..bd3c4d6 100644 --- a/level_3/controller/c/private-common.c +++ b/level_3/controller/c/private-common.c @@ -5,11 +5,21 @@ extern "C" { #endif +#ifndef _di_controller_asynchronous_delete_simple_ + void controller_asynchronous_delete_simple(controller_asynchronous_t *asynchronous) { + + f_macro_array_lengths_t_delete_simple(asynchronous->stack) + + controller_cache_delete_simple(&asynchronous->cache); + controller_rule_delete_simple(&asynchronous->rule); + } +#endif // _di_controller_asynchronous_delete_simple_ + #ifndef _di_controller_asynchronouss_increase_ f_status_t controller_asynchronouss_increase(controller_asynchronouss_t *asynchronouss) { if (asynchronouss->used + 1 > asynchronouss->size) { - f_array_length_t size = asynchronouss->used + controller_thread_asynchronous_allocation_step; + f_array_length_t size = asynchronouss->used + controller_default_allocation_step; if (size > f_array_length_t_size) { if (asynchronouss->used + 1 > f_array_length_t_size) { @@ -32,7 +42,7 @@ extern "C" { f_status_t status = F_none; for (f_array_length_t i = length; i < asynchronouss->size; ++i) { - controller_macro_asynchronous_t_delete_simple(asynchronouss->array[i]); + controller_asynchronous_delete_simple(&asynchronouss->array[i]); } // for status = f_memory_resize(asynchronouss->size, length, sizeof(controller_asynchronous_t), (void **) & asynchronouss->array); @@ -49,13 +59,238 @@ extern "C" { } #endif // _di_controller_asynchronouss_resize_ +#ifndef _di_controller_cache_action_delete_simple_ + void controller_cache_action_delete_simple(controller_cache_action_t *cache) { + + f_string_dynamic_resize(0, &cache->name_action); + f_string_dynamic_resize(0, &cache->name_file); + f_string_dynamic_resize(0, &cache->name_item); + f_string_dynamic_resize(0, &cache->generic); + f_string_dynamic_resize(0, &cache->name_action); + } +#endif // _di_controller_cache_action_delete_simple_ + +#ifndef _di_controller_cache_delete_simple_ + void controller_cache_delete_simple(controller_cache_t *cache) { + + f_macro_array_lengths_t_delete_simple(cache->ats) + f_macro_array_lengths_t_delete_simple(cache->stack) + f_macro_fss_delimits_t_delete_simple(cache->delimits) + + f_string_dynamic_resize(0, &cache->buffer_file); + f_string_dynamic_resize(0, &cache->buffer_item); + f_string_dynamic_resize(0, &cache->buffer_path); + + f_string_ranges_resize(0, &cache->comments); + f_string_ranges_resize(0, &cache->content_action); + f_string_ranges_resize(0, &cache->object_actions); + f_string_ranges_resize(0, &cache->object_items); + + f_string_rangess_resize(0, &cache->content_actions); + f_string_rangess_resize(0, &cache->content_items); + + controller_cache_action_delete_simple(&cache->action); + } +#endif // _di_controller_cache_delete_simple_ + +#ifndef _di_controller_entry_action_delete_simple_ + void controller_entry_action_delete_simple(controller_entry_action_t *action) { + + f_string_dynamics_resize(0, &action->parameters); + } +#endif // _di_controller_entry_action_delete_simple_ + +#ifndef _di_controller_entry_actions_delete_simple_ + void controller_entry_actions_delete_simple(controller_entry_actions_t *actions) { + + actions->used = actions->size; + + while (actions->used) { + controller_entry_action_delete_simple(&actions->array[--actions->used]); + } // while + + f_memory_delete(actions->size, sizeof(controller_entry_action_t), (void **) & actions->array); + actions->size = 0; + } +#endif // _di_controller_entry_actions_delete_simple_ + +#ifndef _di_controller_entry_item_delete_simple_ + void controller_entry_item_delete_simple(controller_entry_item_t *item) { + + f_string_dynamic_resize(0, &item->name); + } +#endif // _di_controller_entry_item_delete_simple_ + +#ifndef _di_controller_entry_items_delete_simple_ + void controller_entry_items_delete_simple(controller_entry_items_t *items) { + + items->used = items->size; + + while (items->used) { + controller_entry_item_delete_simple(&items->array[--items->used]); + } // while + + f_memory_delete(items->size, sizeof(controller_entry_item_t), (void **) & items->array); + items->size = 0; + } +#endif // _di_controller_entry_items_delete_simple_ + +#ifndef _di_controller_error_print_locked_ + void controller_error_print_locked(const fll_error_print_t error, const f_status_t status, const f_string_t function, const bool fallback, controller_thread_t *thread) { + + if (error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&thread->mutex.print); + + fll_error_print(error, status, function, fallback); + + f_thread_mutex_unlock(&thread->mutex.print); + } + } +#endif // _di_controller_error_print_locked_ + +#ifndef _di_controller_process_delete_simple_ + void controller_process_delete_simple(controller_process_t *process) { + + f_string_dynamic_resize(0, &process->id); + f_thread_mutex_delete(&process->lock); + f_thread_condition_delete(&process->wait); + } +#endif // _di_controller_process_delete_simple_ + +#ifndef _di_controller_processs_delete_simple_ + void controller_processs_delete_simple(controller_processs_t *processs) { + + controller_processs_resize(0, processs); + } +#endif // _di_controller_processs_delete_simple_ + +#ifndef _di_controller_processs_increase_ + f_status_t controller_processs_increase(controller_processs_t *processs) { + + if (processs->used + 1 > processs->size) { + f_array_length_t size = processs->used + controller_default_allocation_step; + + if (size > f_array_length_t_size) { + if (processs->used + 1 > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + size = f_array_length_t_size; + } + + return controller_processs_resize(size, processs); + } + + return F_data_not; + } +#endif // _di_controller_processs_increase_ + +#ifndef _di_controller_processs_resize_ + f_status_t controller_processs_resize(const f_array_length_t length, controller_processs_t *processs) { + + f_status_t status = F_none; + + for (f_array_length_t i = length; i < processs->size; ++i) { + controller_process_delete_simple(&processs->array[i]); + } // for + + status = f_memory_resize(processs->size, length, sizeof(controller_process_t), (void **) & processs->array); + + if (F_status_is_error_not(status)) { + processs->size = length; + + if (processs->used > processs->size) { + processs->used = length; + } + } + + return status; + } +#endif // _di_controller_processs_resize_ + +#ifndef _di_controller_rule_action_delete_simple_ + void controller_rule_action_delete_simple(controller_rule_action_t *action) { + + f_string_dynamics_resize(0, &action->parameters); + } +#endif // _di_controller_rule_action_delete_simple_ + +#ifndef _di_controller_rule_actions_delete_simple_ + void controller_rule_actions_delete_simple(controller_rule_actions_t *actions) { + + actions->used = actions->size; + + while (actions->used) { + controller_rule_action_delete_simple(&actions->array[--actions->used]); + } // while + + f_memory_delete(actions->size, sizeof(controller_rule_action_t), (void **) & actions->array); + actions->size = 0; + } +#endif // _di_controller_rule_actions_delete_simple_ + +#ifndef _di_controller_rule_delete_simple_ + void controller_rule_delete_simple(controller_rule_t *rule) { + + f_macro_thread_mutex_t_delete_simple(rule->lock) + f_macro_thread_condition_t_delete_simple(rule->wait) + f_macro_string_maps_t_delete_simple(rule->define) + f_macro_string_maps_t_delete_simple(rule->parameter) + f_macro_string_dynamics_t_delete_simple(rule->environment) + f_macro_string_dynamics_t_delete_simple(rule->need) + f_macro_string_dynamics_t_delete_simple(rule->want) + f_macro_string_dynamics_t_delete_simple(rule->wish) + f_macro_int32s_t_delete_simple(rule->affinity) + f_macro_control_group_t_delete_simple(rule->control_group) + f_macro_int32s_t_delete_simple(rule->groups) + f_macro_limit_sets_t_delete_simple(rule->limits) + + f_string_dynamic_resize(0, &rule->id); + f_string_dynamic_resize(0, &rule->name); + f_string_dynamic_resize(0, &rule->path); + f_string_dynamic_resize(0, &rule->script); + + f_capability_delete(&rule->capability); + + controller_rule_items_delete_simple(&rule->items); + } +#endif // _di_controller_rule_delete_simple_ + +#ifndef _di_controller_rule_item_delete_simple_ + void controller_rule_item_delete_simple(controller_rule_item_t *item) { + + f_string_dynamic_resize(0, item->actions); + } +#endif // _di_controller_rule_item_delete_simple_ + +#ifndef _di_controller_rule_items_delete_simple_ + void controller_rule_items_delete_simple(controller_rule_items_t *items) { + + items->used = items->size; + + while (items->used) { + controller_rule_item_delete_simple(&items->array[--items->used]); + } // while + + f_memory_delete(items->size, sizeof(controller_rule_item_t), (void **) & items->array); + items->size = 0; + } +#endif // _di_controller_rule_items_delete_simple_ + +#ifndef _di_controller_rules_delete_simple_ + void controller_rules_delete_simple(controller_rules_t *rules) { + + controller_rules_resize(0, rules); + } +#endif // _di_controller_rules_delete_simple_ + #ifndef _di_controller_rules_increase_ f_status_t controller_rules_increase(controller_rules_t *rules) { if (rules->used + 1 > rules->size) { f_array_length_t size = rules->used + controller_default_allocation_step; - if (size > f_string_length_t_size) { + if (size > f_array_length_t_size) { if (rules->used + 1 > f_array_length_t_size) { return F_status_set_error(F_array_too_large); } @@ -63,31 +298,59 @@ extern "C" { size = f_array_length_t_size; } - const f_status_t status = f_memory_resize(rules->size, size, sizeof(controller_rule_t), (void **) & rules->array); - - if (F_status_is_error_not(status)) { - rules->size = size; - } - - return status; + return controller_rules_resize(size, rules); } - return F_none; + return F_data_not; } #endif // _di_controller_rules_increase_ -#ifndef _di_controller_error_print_locked_ - void controller_error_print_locked(const fll_error_print_t error, const f_status_t status, const f_string_t function, const bool fallback, controller_thread_t *thread) { +#ifndef _di_controller_rules_resize_ + f_status_t controller_rules_resize(const f_array_length_t length, controller_rules_t *rules) { - if (error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&thread->mutex->print); + f_status_t status = F_none; - fll_error_print(error, status, function, fallback); + for (f_array_length_t i = length; i < rules->size; ++i) { + controller_rule_delete_simple(&rules->array[i]); + } // for - f_thread_mutex_unlock(&thread->mutex->print); + status = f_memory_resize(rules->size, length, sizeof(controller_rule_t), (void **) & rules->array); + + if (F_status_is_error_not(status)) { + rules->size = length; + + if (rules->used > rules->size) { + rules->used = length; + } } + + return status; } -#endif // _di_controller_error_print_locked_ +#endif // _di_controller_rules_resize_ + +#ifndef _di_controller_setting_delete_simple_ + void controller_setting_delete_simple(controller_setting_t *setting) { + + f_string_dynamic_resize(0, &setting->path_control); + f_string_dynamic_resize(0, &setting->path_pid); + f_string_dynamic_resize(0, &setting->path_setting); + + controller_entry_items_delete_simple(&setting->entry.items); + controller_rules_delete_simple(&setting->rules); + } +#endif // _di_controller_setting_delete_simple_ + +#ifndef _di_controller_thread_delete_simple_ + void controller_thread_delete_simple(controller_thread_t *thread) { + + f_thread_mutex_unlock(&thread->mutex.asynchronous); + f_thread_mutex_unlock(&thread->mutex.print); + f_thread_mutex_unlock(&thread->mutex.process); + f_thread_mutex_unlock(&thread->mutex.rule); + + controller_asynchronouss_resize(0, &thread->asynchronouss); + } +#endif // _di_controller_thread_delete_simple_ #ifdef __cplusplus } // extern "C" diff --git a/level_3/controller/c/private-common.h b/level_3/controller/c/private-common.h index 2215a9c..c284b48 100644 --- a/level_3/controller/c/private-common.h +++ b/level_3/controller/c/private-common.h @@ -295,27 +295,49 @@ extern "C" { }; #endif // _di_controller_resource_limit_t_ +#ifndef _di_controller_execute_set_t_ + typedef struct { + fl_execute_parameter_t parameter; + fl_execute_as_t as; + } controller_execute_set_t; + + #define controller_execute_set_t_initialize { \ + fl_execute_parameter_t_initialize, \ + fl_execute_as_t_initialize \ + } + + #define controller_macro_execute_set_t_initialize(option, environment, signals, data, as) { \ + fl_macro_execute_parameter_t_initialize(option, environment, signals, data), \ + as \ + } + + #define controller_macro_execute_set_t_clear(set) \ + fl_macro_execute_parameter_t_clear(set.parameter) \ + fl_macro_execute_as_t_clear(set.as) +#endif // _di_controller_execute_set_t_ + +/** + * A structure for sharing mutexes globally between different threads. + * + * The asynchronous lock is intended to lock any activity on the asynchronouss structure. + * The print lock is intended to lock any activity printing to stdout/stderr. + * The process lock is intended to lock any activity on the processs structure. + * The rule lock is intended to lock any activity on the rules structure. + */ #ifndef _di_controller_mutex_t_ typedef struct { f_thread_mutex_t asynchronous; - f_thread_mutex_t cache; f_thread_mutex_t print; + f_thread_mutex_t process; f_thread_mutex_t rule; } controller_mutex_t; - #define controller_mutex_t_initialize \ - { \ - f_thread_mutex_t_initialize, \ - f_thread_mutex_t_initialize, \ - f_thread_mutex_t_initialize, \ - f_thread_mutex_t_initialize, \ - } - - #define controller_macro_mutex_t_delete_simple(mutex) \ - f_thread_mutex_delete(&mutex.asynchronous); \ - f_thread_mutex_delete(&mutex.cache); \ - f_thread_mutex_delete(&mutex.print); \ - f_thread_mutex_delete(&mutex.rule); + #define controller_mutex_t_initialize { \ + f_thread_mutex_t_initialize, \ + f_thread_mutex_t_initialize, \ + f_thread_mutex_t_initialize, \ + f_thread_mutex_t_initialize \ + } #endif // _di_controller_mutex_t_ #ifndef _di_controller_rule_action_t_ @@ -348,24 +370,24 @@ extern "C" { typedef struct { uint8_t type; - - f_string_length_t line; - + f_array_length_t line; f_status_t status; f_string_dynamics_t parameters; } controller_rule_action_t; - #define controller_rule_action_t_initialize \ - { \ - 0, \ - 0, \ - F_known_not, \ - f_string_dynamics_t_initialize, \ - } - - #define controller_macro_rule_action_t_delete_simple(action) \ - f_macro_string_dynamics_t_delete_simple(action.parameters); + #define controller_rule_action_t_initialize { \ + 0, \ + 0, \ + F_known_not, \ + f_string_dynamics_t_initialize, \ + } + + #define controller_macro_rule_action_t_clear(rule) \ + type = 0; \ + line = 0; \ + status = F_known_not; \ + f_macro_string_dynamics_t_clear(rule.parameters) #endif // _di_controller_rule_action_t_ #ifndef _di_controller_rule_actions_t_ @@ -376,21 +398,16 @@ extern "C" { f_array_length_t used; } controller_rule_actions_t; - #define controller_rule_actions_t_initialize \ - { \ - 0, \ - 0, \ - 0, \ - } + #define controller_rule_actions_t_initialize { \ + 0, \ + 0, \ + 0, \ + } - #define controller_macro_rule_actions_t_delete_simple(actions) \ - actions.used = actions.size; \ - while (actions.used) { \ - actions.used--; \ - controller_macro_rule_action_t_delete_simple(actions.array[actions.used]); \ - } \ - f_memory_delete(actions.size, sizeof(controller_rule_action_t), (void **) & actions.array); \ - actions.size = 0; + #define controller_macro_rule_actions_t_clear(actions) \ + actions.array = 0; \ + actions.size = 0; \ + actions.used = 0; #endif // _di_controller_rule_actions_t_ #ifndef _di_controller_rule_item_t_ @@ -403,7 +420,7 @@ extern "C" { typedef struct { uint8_t type; - f_string_length_t line; + f_array_length_t line; controller_rule_actions_t actions; } controller_rule_item_t; @@ -415,8 +432,10 @@ extern "C" { controller_rule_actions_t_initialize, \ } - #define controller_macro_rule_item_t_delete_simple(item) \ - controller_macro_rule_actions_t_delete_simple(item.actions) + #define controller_macro_rule_item_t_clear(item) \ + item.type = 0; \ + item.line = 0; \ + controller_macro_rule_actions_t_clear(item.actions); #endif // _di_controller_rule_item_t_ #ifndef _di_controller_rule_items_t_ @@ -427,21 +446,16 @@ extern "C" { f_array_length_t used; } controller_rule_items_t; - #define controller_rule_items_initialize \ - { \ - 0, \ - 0, \ - 0, \ - } + #define controller_rule_items_initialize { \ + 0, \ + 0, \ + 0, \ + } - #define controller_macro_rule_items_t_delete_simple(items) \ - items.used = items.size; \ - while (items.used) { \ - items.used--; \ - controller_macro_rule_item_t_delete_simple(items.array[items.used]); \ - } \ - f_memory_delete(items.size, sizeof(controller_rule_item_t), (void **) & items.array); \ - items.size = 0; + #define controller_macro_rule_items_t_clear(items) \ + items.array = 0; \ + items.size = 0; \ + items.used = 0; #endif // _di_controller_rule_items_t_ #ifndef _di_controller_rule_t_ @@ -479,11 +493,6 @@ extern "C" { #define controller_rule_has_user 0x10 typedef struct { - f_status_t status; - - f_thread_mutex_t lock; - f_thread_condition_t wait; - f_number_unsigned_t timeout_kill; f_number_unsigned_t timeout_start; f_number_unsigned_t timeout_stop; @@ -518,56 +527,60 @@ extern "C" { controller_rule_items_t items; } controller_rule_t; - #define controller_rule_t_initialize \ - { \ - F_known_not, \ - f_thread_mutex_t_initialize, \ - f_thread_condition_t_initialize, \ - 0, \ - 0, \ - 0, \ - 0, \ - 0, \ - 0, \ - f_time_spec_t_initialize, \ - f_string_dynamic_t_initialize, \ - f_string_dynamic_t_initialize, \ - f_string_dynamic_t_initialize, \ - f_string_dynamic_t_initialize, \ - f_string_maps_t_initialize, \ - f_string_maps_t_initialize, \ - f_string_dynamics_t_initialize, \ - f_string_dynamics_t_initialize, \ - f_string_dynamics_t_initialize, \ - f_string_dynamics_t_initialize, \ - f_int32s_t_initialize, \ - f_capability_t_initialize, \ - f_control_group_t_initialize, \ - f_int32s_t_initialize, \ - f_limit_sets_t_initialize, \ - f_execute_scheduler_t_initialize, \ - controller_rule_items_initialize, \ - } - - #define controller_macro_rule_t_delete_simple(rule) \ - f_macro_thread_mutex_t_delete_simple(rule.lock) \ - f_macro_thread_condition_t_delete_simple(rule.wait) \ - f_macro_string_dynamic_t_delete_simple(rule.id) \ - f_macro_string_dynamic_t_delete_simple(rule.name) \ - f_macro_string_dynamic_t_delete_simple(rule.path) \ - f_macro_string_dynamic_t_delete_simple(rule.script) \ - f_macro_string_maps_t_delete_simple(rule.define) \ - f_macro_string_maps_t_delete_simple(rule.parameter) \ - f_macro_string_dynamics_t_delete_simple(rule.environment) \ - f_macro_string_dynamics_t_delete_simple(rule.need) \ - f_macro_string_dynamics_t_delete_simple(rule.want) \ - f_macro_string_dynamics_t_delete_simple(rule.wish) \ - f_macro_int32s_t_delete_simple(rule.affinity) \ - f_capability_delete(&rule.capability); \ - f_macro_control_group_t_delete_simple(rule.control_group) \ - f_macro_int32s_t_delete_simple(rule.groups) \ - f_macro_limit_sets_t_delete_simple(rule.limits) \ - controller_macro_rule_items_t_delete_simple(rule.items) + #define controller_rule_t_initialize { \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + f_time_spec_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_maps_t_initialize, \ + f_string_maps_t_initialize, \ + f_string_dynamics_t_initialize, \ + f_string_dynamics_t_initialize, \ + f_string_dynamics_t_initialize, \ + f_string_dynamics_t_initialize, \ + f_int32s_t_initialize, \ + f_capability_t_initialize, \ + f_control_group_t_initialize, \ + f_int32s_t_initialize, \ + f_limit_sets_t_initialize, \ + f_execute_scheduler_t_initialize, \ + controller_rule_items_initialize, \ + } + + #define controller_macro_rule_t_clear(rule) \ + rule.timeout_kill = 0; \ + rule.timeout_start = 0; \ + rule.timeout_stop = 0; \ + rule.has = 0; \ + rule.nice = 0; \ + rule.user = 0; \ + rule.group = 0; \ + f_macro_time_spec_t_clear(rule.timestamp) \ + f_macro_string_dynamic_t_clear(rule.id) \ + f_macro_string_dynamic_t_clear(rule.name) \ + f_macro_string_dynamic_t_clear(rule.path) \ + f_macro_string_dynamic_t_clear(rule.script) \ + f_macro_string_maps_t_clear(rule.define) \ + f_macro_string_maps_t_clear(rule.parameter) \ + f_macro_string_dynamics_t_clear(rule.environment) \ + f_macro_string_dynamics_t_clear(rule.need) \ + f_macro_string_dynamics_t_clear(rule.want) \ + f_macro_string_dynamics_t_clear(rule.wish) \ + f_macro_int32s_t_clear(rule.affinity) \ + f_macro_capability_t_clear(rule.capability) \ + f_macro_control_group_t_clear(rule.control_group) \ + f_macro_int32s_t_clear(rule.groups) \ + f_macro_limit_sets_t_clear(rule.limits) \ + f_macro_execute_scheduler_t_clear(rule.scheduler) \ + controller_macro_rule_items_t_clear(rule.items) #endif // _di_controller_rule_t_ #ifndef _di_controller_rules_t_ @@ -578,23 +591,67 @@ extern "C" { f_array_length_t used; } controller_rules_t; - #define controller_rules_t_initialize \ - { \ - 0, \ - 0, \ - 0, \ - } + #define controller_rules_t_initialize { \ + 0, \ + 0, \ + 0, \ + } - #define controller_macro_rules_t_delete_simple(rules) \ - rules.used = rules.size; \ - while (rules.used) { \ - rules.used--; \ - controller_macro_rule_t_delete_simple(rules.array[rules.used]); \ - } \ - f_memory_delete(rules.size, sizeof(controller_rule_t), (void **) & rules.array); \ - rules.size = 0; + #define controller_macro_rules_t_clear(rules) \ + rules.array = 0; \ + rules.size = 0; \ + rules.used = 0; #endif // _di_controller_rules_t_ +/** + * Store controller process information for some rule. + * + * This refers to "process" as in the processing of a rule and does not refer to "process" as in a CPU process. + * + * This holds the success/failure rate and any associated locks. + * This operates based on the rule id string (such as "network/ntpdate"). + */ +#ifndef _di_controller_process_t_ + typedef struct { + f_status_t status; + f_string_dynamic_t id; + + f_thread_mutex_t lock; + f_thread_condition_t wait; + } controller_process_t; + + #define controller_process_t_initialize { \ + F_known_not, \ + f_string_dynamic_t_initialize \ + f_thread_mutex_t_initialize, \ + f_thread_condition_t_initialize, \ + } + + #define controller_macro_process_t_clear(process) \ + process.status = F_known_not; \ + f_macro_string_dynamic_t_clear(process.id) +#endif // _di_controller_process_t_ + +#ifndef _di_controller_processs_t_ + typedef struct { + controller_process_t *array; + + f_array_length_t size; + f_array_length_t used; + } controller_processs_t; + + #define controller_processs_t_initialize { \ + 0, \ + 0, \ + 0, \ + } + + #define controller_macro_processs_t_clear(process) \ + process.array = 0; \ + process.size = 0; \ + process.used = 0; +#endif // _di_controller_processs_t_ + #ifndef _di_controller_entry_action_t_ enum { controller_entry_action_type_consider = 1, @@ -617,7 +674,7 @@ extern "C" { uint8_t type; uint8_t code; - f_string_length_t line; + f_array_length_t line; f_number_unsigned_t number; f_status_t status; @@ -625,18 +682,22 @@ extern "C" { f_string_dynamics_t parameters; } controller_entry_action_t; - #define controller_entry_action_t_initialize \ - { \ - 0, \ - 0, \ - 0, \ - 0, \ - F_known_not, \ - f_string_dynamics_t_initialize, \ - } - - #define controller_macro_entry_action_t_delete_simple(action) \ - f_macro_string_dynamics_t_delete_simple(action.parameters); + #define controller_entry_action_t_initialize { \ + 0, \ + 0, \ + 0, \ + 0, \ + F_known_not, \ + f_string_dynamics_t_initialize, \ + } + + #define controller_macro_entry_action_t_clear(action) \ + action.type = 0; \ + action.code = 0; \ + action.line = 0; \ + action.number = 0; \ + action.status = F_known_not; \ + f_macro_string_dynamics_t_clear(action.parameters) #endif // _di_controller_entry_action_t_ #ifndef _di_controller_entry_actions_t_ @@ -647,28 +708,23 @@ extern "C" { f_array_length_t used; } controller_entry_actions_t; - #define controller_entry_actions_t_initialize \ - { \ - 0, \ - 0, \ - 0, \ - } + #define controller_entry_actions_t_initialize { \ + 0, \ + 0, \ + 0, \ + } - #define controller_macro_entry_actions_t_delete_simple(actions) \ - actions.used = actions.size; \ - while (actions.used) { \ - actions.used--; \ - controller_macro_entry_action_t_delete_simple(actions.array[actions.used]); \ - } \ - f_memory_resize(actions.size, 0, sizeof(controller_entry_action_t), (void **) & actions.array); \ - actions.size = 0; + #define controller_macro_entry_actions_t_clear(actions) \ + actions.array = 0; \ + actions.size = 0; \ + actions.used = 0; #endif // _di_controller_entry_actions_t_ #ifndef _di_controller_entry_item_t_ typedef struct { - f_string_length_t line; - + f_array_length_t line; f_string_dynamic_t name; + controller_entry_actions_t actions; } controller_entry_item_t; @@ -679,9 +735,10 @@ extern "C" { controller_entry_actions_t_initialize, \ } - #define controller_macro_entry_item_t_delete_simple(item) \ - f_macro_string_dynamic_t_delete_simple(item.name); \ - controller_macro_entry_actions_t_delete_simple(item.actions) + #define controller_macro_entry_item_t_clear(item) \ + item.line = 0; \ + f_macro_string_dynamic_t_clear(item.name) \ + controller_macro_entry_actions_t_clear(item.actions) #endif // _di_controller_entry_item_t_ #ifndef _di_controller_entry_items_t_ @@ -692,37 +749,33 @@ extern "C" { f_array_length_t used; } controller_entry_items_t; - #define controller_entry_items_t_initialize \ - { \ - 0, \ - 0, \ - 0, \ - } + #define controller_entry_items_t_initialize { \ + 0, \ + 0, \ + 0, \ + } - #define controller_macro_entry_items_t_delete_simple(items) \ - items.used = items.size; \ - while (items.used) { \ - items.used--; \ - controller_macro_entry_item_t_delete_simple(items.array[items.used]); \ - } \ - f_memory_delete(items.size, sizeof(controller_entry_item_t), (void **) & items.array); \ - items.size = 0; + #define controller_macro_entry_items_t_clear(items) \ + items.array = 0; \ + items.size = 0; \ + items.used = 0; #endif // _di_controller_entry_items_t_ #ifndef _di_controller_entry_t_ typedef struct { f_status_t status; + controller_entry_items_t items; } controller_entry_t; - #define controller_entry_t_initialize \ - { \ - F_known_not, \ - controller_entry_items_t_initialize, \ - } + #define controller_entry_t_initialize { \ + F_known_not, \ + controller_entry_items_t_initialize, \ + } - #define controller_macro_entry_t_delete_simple(entry) \ - controller_macro_entry_items_t_delete_simple(entry.items) + #define controller_macro_entry_t_clear(entry) \ + entry.status = F_known_not; \ + controller_macro_entry_items_t_clear(entry.items) #endif // _di_controller_entry_t_ #ifndef _di_controller_setting_t @@ -755,35 +808,42 @@ extern "C" { controller_rules_t rules; } controller_setting_t; - #define controller_setting_t_initialize \ - { \ - F_false, \ - 0, \ - 0, \ - 3, \ - 3, \ - 3, \ - F_false, \ - 0, \ - f_string_dynamic_t_initialize, \ - f_string_dynamic_t_initialize, \ - f_string_dynamic_t_initialize, \ - controller_entry_t_initialize, \ - controller_rules_t_initialize, \ - } - - #define controller_macro_setting_t_delete_simple(setting) \ - f_macro_string_dynamic_t_delete_simple(setting.path_control) \ - f_macro_string_dynamic_t_delete_simple(setting.path_pid) \ - f_macro_string_dynamic_t_delete_simple(setting.path_setting) \ - controller_macro_entry_t_delete_simple(setting.entry) \ - controller_macro_rules_t_delete_simple(setting.rules) + #define controller_setting_t_initialize { \ + F_false, \ + 0, \ + 0, \ + 3, \ + 3, \ + 3, \ + F_false, \ + 0, \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + controller_entry_t_initialize, \ + controller_rules_t_initialize, \ + } + + #define controller_macro_setting_t_clear(setting) \ + setting.interruptable = F_false; \ + setting.ready = 0; \ + setting.signal = 0; \ + setting.timeout_kill = 3; \ + setting.timeout_start = 3; \ + setting.timeout_stop = 3; \ + setting.failsafe_enabled = F_false; \ + setting.failsafe_rule_id = 0; \ + f_macro_string_dynamic_t_clear(entry.path_control) \ + f_macro_string_dynamic_t_clear(entry.path_pid) \ + f_macro_string_dynamic_t_clear(entry.path_setting) \ + controller_macro_entry_t_clear(entry.entry) \ + controller_macro_rules_t_clear(entry.setting) #endif // _di_controller_setting_t #ifndef _di_controller_cache_action_t_ typedef struct { - f_string_length_t line_action; - f_string_length_t line_item; + f_array_length_t line_action; + f_array_length_t line_item; f_string_dynamic_t name_action; f_string_dynamic_t name_file; @@ -792,29 +852,22 @@ extern "C" { f_string_dynamic_t generic; } controller_cache_action_t; - #define controller_cache_action_t_initialize \ - { \ - 0, \ - 0, \ - f_string_dynamic_t_initialize, \ - f_string_dynamic_t_initialize, \ - f_string_dynamic_t_initialize, \ - f_string_dynamic_t_initialize, \ - } + #define controller_cache_action_t_initialize { \ + 0, \ + 0, \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + } #define controller_macro_cache_action_t_clear(cache) \ cache.line_action = 0; \ cache.line_item = 0; \ - cache.name_action.used = 0; \ - cache.name_file.used = 0; \ - cache.name_item.used = 0; \ - cache.generic.used = 0; - - #define controller_macro_cache_action_t_delete_simple(cache) \ - f_macro_string_dynamic_t_delete_simple(cache.name_action) \ - f_macro_string_dynamic_t_delete_simple(cache.name_file) \ - f_macro_string_dynamic_t_delete_simple(cache.name_item) \ - f_macro_string_dynamic_t_delete_simple(cache.generic) + f_macro_string_dynamic_t_clear(cache.name_action) \ + f_macro_string_dynamic_t_clear(cache.name_file) \ + f_macro_string_dynamic_t_clear(cache.name_item) \ + f_macro_string_dynamic_t_clear(cache.generic) #endif // _di_controller_cache_action_t_ #ifndef _di_controller_cache_t_ @@ -842,39 +895,41 @@ extern "C" { controller_cache_action_t action; } controller_cache_t; - #define controller_cache_t_initialize \ - { \ - f_time_spec_t_initialize, \ - f_string_range_t_initialize, \ - f_array_lengths_t_initialize, \ - f_array_lengths_t_initialize, \ - f_fss_comments_t_initialize, \ - f_fss_delimits_t_initialize, \ - f_fss_content_t_initialize, \ - f_fss_contents_t_initialize, \ - f_fss_contents_t_initialize, \ - f_fss_objects_t_initialize, \ - f_fss_objects_t_initialize, \ - f_string_dynamic_t_initialize, \ - f_string_dynamic_t_initialize, \ - f_string_dynamic_t_initialize, \ - controller_cache_action_t_initialize, \ - } - - #define controller_macro_cache_t_delete_simple(cache) \ - f_macro_array_lengths_t_delete_simple(cache.ats) \ - f_macro_array_lengths_t_delete_simple(cache.stack) \ - f_macro_fss_comments_t_delete_simple(cache.comments) \ - f_macro_fss_delimits_t_delete_simple(cache.delimits) \ - f_macro_fss_content_t_delete_simple(cache.content_action) \ - f_macro_fss_contents_t_delete_simple(cache.content_actions) \ - f_macro_fss_contents_t_delete_simple(cache.content_items) \ - f_macro_fss_objects_t_delete_simple(cache.object_actions) \ - f_macro_fss_objects_t_delete_simple(cache.object_items) \ - f_macro_string_dynamic_t_delete_simple(cache.buffer_file) \ - f_macro_string_dynamic_t_delete_simple(cache.buffer_item) \ - f_macro_string_dynamic_t_delete_simple(cache.buffer_path) \ - controller_macro_cache_action_t_delete_simple(cache.action) + #define controller_cache_t_initialize { \ + f_time_spec_t_initialize, \ + f_string_range_t_initialize, \ + f_array_lengths_t_initialize, \ + f_array_lengths_t_initialize, \ + f_fss_comments_t_initialize, \ + f_fss_delimits_t_initialize, \ + f_fss_content_t_initialize, \ + f_fss_contents_t_initialize, \ + f_fss_contents_t_initialize, \ + f_fss_objects_t_initialize, \ + f_fss_objects_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + f_string_dynamic_t_initialize, \ + controller_cache_action_t_initialize, \ + } + + #define controller_macro_cache_t_clear(cache) \ + f_macro_time_spec_t_clear(cache.timestamp) \ + f_macro_string_range_t_clear(cache.range_action) \ + cache.ats = 0; \ + cache.stack = 0; \ + f_macro_time_spec_t_clear(cache.timestamp) \ + f_macro_fss_comments_t_clear(cache.comments) \ + f_macro_fss_delimits_t_clear(cache.delimits) \ + f_macro_fss_content_t_clear(cache.content_action) \ + f_macro_fss_contents_t_clear(cache.content_actions) \ + f_macro_fss_contents_t_clear(cache.content_items) \ + f_macro_fss_objects_t_clear(cache.object_actions) \ + f_macro_fss_objects_t_clear(cache.object_items) \ + f_macro_string_dynamic_t_clear(cache.buffer_file) \ + f_macro_string_dynamic_t_clear(cache.buffer_item) \ + f_macro_string_dynamic_t_clear(cache.buffer_path) \ + controller_macro_cache_action_t_clear(cache.action) #endif // _di_controller_cache_t_ #ifndef _di_controller_asynchronous_t_ @@ -894,12 +949,23 @@ extern "C" { uint8_t options; pid_t child; - void *thread; f_array_lengths_t stack; - controller_cache_action_t cache; + controller_cache_t cache; + controller_rule_t rule; } controller_asynchronous_t; - #define controller_asynchronous_t_initialize { f_thread_id_t_initialize, f_thread_mutex_t_initialize, 0, 0, 0, 0, 0, 0, f_array_lengths_t_initialize, controller_cache_action_t_initialize } + #define controller_asynchronous_t_initialize { \ + f_thread_id_t_initialize, \ + f_thread_mutex_t_initialize, \ + 0, \ + 0, \ + 0, \ + 0, \ + 0, \ + f_array_lengths_t_initialize, \ + controller_cache_t_initialize, \ + controller_rule_t_initialize \ + } #define controller_macro_asynchronous_t_clear(asynchronous) \ f_macro_thread_id_t_clear(asynchronous.id) \ @@ -908,114 +974,127 @@ extern "C" { asynchronous.action = 0; \ asynchronous.options = 0; \ asynchronous.child = 0; \ - asynchronous.thread = 0; \ f_macro_array_lengths_t_clear(asynchronous.stack) \ - controller_macro_cache_action_t_clear(asynchronous.cache) - - #define controller_macro_asynchronous_t_delete_simple(asynchronous) \ - controller_macro_cache_action_t_delete_simple(asynchronous.cache) \ - f_macro_array_lengths_t_delete_simple(asynchronous.stack) + controller_macro_cache_t_clear(asynchronous.cache) \ + controller_macro_rule_t_clear(asynchronous.rule) #endif // _di_controller_asynchronous_t_ #ifndef _di_controller_asynchronouss_t_ typedef struct { - bool enabled; - controller_asynchronous_t *array; f_array_length_t size; f_array_length_t used; } controller_asynchronouss_t; - #define controller_asynchronouss_t_initialize \ - { \ - F_true, \ - 0, \ - 0, \ - 0, \ - } + #define controller_asynchronouss_t_initialize { \ + 0, \ + 0, \ + 0, \ + } - #define controller_macro_asynchronouss_t_delete_simple(asynchronouss) \ - asynchronouss.used = asynchronouss.size; \ - while (asynchronouss.used) { \ - asynchronouss.used--; \ - controller_macro_asynchronous_t_delete_simple(asynchronouss.array[asynchronouss.used]) \ - } \ - f_memory_delete(asynchronouss.size, sizeof(controller_asynchronous_t), (void **) & asynchronouss.array); \ - asynchronouss.size = 0; + #define controller_macro_asynchronouss_t_clear(asynchronouss) \ + asynchronouss.array = 0; \ + asynchronouss.size = 0; \ + asynchronouss.used = 0; #endif // _di_controller_asynchronouss_t_ #ifndef _di_controller_thread_t_ - #define controller_thread_cache_cleanup_interval_long 3600 // 1 hour in seconds. - #define controller_thread_cache_cleanup_interval_short 180 // 3 minutes in seconds. - #define controller_thread_asynchronous_allocation_step 16 // Total number of asynchronous threads increase by. - #define controller_thread_asynchronous_total 65535 // Total number of asynchronous threads allowed at any one time. - typedef struct { - controller_cache_t *cache_main; - controller_cache_action_t *cache_action; - controller_data_t *data; - controller_mutex_t *mutex; - controller_setting_t *setting; - f_array_lengths_t *stack; + bool enabled; + + f_thread_id_t id_cleanup; + f_thread_id_t id_control; + f_thread_id_t id_rule; + f_thread_id_t id_signal; + + controller_mutex_t mutex; controller_asynchronouss_t asynchronouss; } controller_thread_t; - #define controller_thread_t_initialize { 0, 0, 0, 0, 0, 0, controller_asynchronouss_t_initialize } - - #define controller_macro_thread_t_initialize(cache_main, cache_action, data, mutex, setting, stack) { cache_main, cache_action, data, mutex, setting, stack, controller_asynchronouss_t_initialize } + #define controller_thread_t_initialize { \ + F_true, \ + f_thread_id_t_initialize, \ + f_thread_id_t_initialize, \ + f_thread_id_t_initialize, \ + f_thread_id_t_initialize, \ + controller_mutex_t_initialize, \ + controller_asynchronouss_t_initialize \ + } + + #define controller_macro_thread_t_initialize(mutex, asynchronouss) { \ + F_true, \ + f_thread_id_t_initialize, \ + f_thread_id_t_initialize, \ + f_thread_id_t_initialize, \ + f_thread_id_t_initialize. \ + mutex, \ + asynchronouss \ + } #define controller_macro_thread_t_clear(thread) \ - thread.cache_main = 0; \ - thread.cache_action = 0; \ - thread.data = 0; \ - thread.mutex = 0; \ - thread.setting = 0; \ - thread.stack = 0; \ - thread.asynchronouss.used = 0; - - #define controller_macro_thread_t_delete_simple(thread) \ - controller_asynchronouss_resize(0, &thread.asynchronouss); -#endif // _di_controller_thread_t_ - -#ifndef _di_controller_execute_set_t_ - typedef struct { - fl_execute_parameter_t parameter; - fl_execute_as_t as; - } controller_execute_set_t; + thread.enabled = F_true; \ + f_macro_thread_id_t_clear(thread.id_cleanup); \ + f_macro_thread_id_t_clear(thread.id_control); \ + f_macro_thread_id_t_clear(thread.id_rule); \ + f_macro_thread_id_t_clear(thread.id_signal); \ + controller_macro_mutex_t_clear(thread.mutex), \ + controller_macro_asynchronouss_t_clear(thread.asynchronouss) +#endif // _di_controller_data_common_t_ + +#ifndef _di_controller_thread_data_t_ + // @todo relocate these under a different ifdef block. + #define controller_thread_cache_cleanup_interval_long 3600 // 1 hour in seconds. + #define controller_thread_cache_cleanup_interval_short 180 // 3 minutes in seconds. - #define controller_execute_set_t_initialize { fl_execute_parameter_t_initialize, fl_execute_as_t_initialize } + // @fixme these aren't used? consider removing or updating. + #define controller_thread_asynchronous_allocation_step 16 // Total number of asynchronous threads increase by. + #define controller_thread_asynchronous_max 65535 // Total number of asynchronous threads allowed at any one time. - #define controller_macro_execute_set_t_initialize(option, environment, signals, data, as) { fl_macro_execute_parameter_t_initialize(option, environment, signals, data), as } + typedef struct { + f_array_length_t id; - #define controller_macro_execute_set_t_clear(set) \ - fl_macro_execute_parameter_t_clear(set.parameter) \ - fl_macro_execute_as_t_clear(set.as) -#endif // _di_controller_execute_set_t_ + controller_data_t *data; + controller_setting_t *setting; + controller_processs_t *processs; + controller_thread_t *thread; + } controller_thread_data_t; + + #define controller_thread_data_t_initialize { 0, 0, 0, 0, 0 } + + #define controller_macro_thread_data_t_initialize(id, data, setting, processs, thread) { \ + id, \ + data, \ + setting, \ + processs, \ + thread \ + } + + #define controller_macro_thread_data_t_clear(thread_data) \ + thread_data.id = 0; \ + thread_data.data = 0; \ + thread_data.setting = 0; \ + thread_data.processs = 0; \ + thread_data.thread = 0; +#endif // _di_controller_thread_data_t_ /** - * Resize the asynchronouss array to a larger size. - * - * This will resize making the string larger based on the given length. - * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). - * If already set to the maximum buffer size, then the resize will fail. + * Fully deallocate all memory for the given asynchronous without caring about return status. * - * @param amount - * A positive number representing how much to increase the size by. - * @param asynchronouss - * The asynchronous array to resize. + * @param asynchronous + * The asynchronous to deallocate. * - * @return - * F_none on success. - * F_data_not on success, but there is no reason to increase size (used + amount <= size). + * @see f_macro_array_lengths_t_delete_simple() * - * F_memory_not (with error bit) on out of memory. - * F_parameter (with error bit) if a parameter is invalid. - * F_array_too_large (with error bit) if the new array length is too large. + * @see controller_cache_delete_simple() + * @see controller_rule_delete_simple() */ +#ifndef _di_controller_asynchronous_delete_simple_ + extern void controller_asynchronous_delete_simple(controller_asynchronous_t *asynchronous) f_gcc_attribute_visibility_internal; +#endif // _di_controller_asynchronous_delete_simple_ /** - * Increase the size of the asynchronouss array, but only if necessary. + * Increase the size of the asynchronous array, but only if necessary. * * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). * If already set to the maximum buffer size, then the resize will fail. @@ -1025,18 +1104,20 @@ extern "C" { * * @return * F_none on success. - * F_data_not on success, but there is no reason to increase size (used + controller_thread_asynchronous_allocation_step <= size). + * F_data_not on success, but there is no reason to increase size (used + controller_default_allocation_step <= size). * * F_array_too_large (with error bit) if the new array length is too large. * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. + * + * @see controller_asynchronouss_resize() */ #ifndef _di_controller_asynchronouss_increase_ extern f_status_t controller_asynchronouss_increase(controller_asynchronouss_t *asynchronouss) f_gcc_attribute_visibility_internal; #endif // _di_controller_asynchronouss_increase_ /** - * Resize the string asynchronouss array. + * Resize the string asynchronous array. * * @param length * The new size to use. @@ -1048,12 +1129,94 @@ extern "C" { * * F_memory_not (with error bit) on out of memory. * F_parameter (with error bit) if a parameter is invalid. + * + * @see f_memory_resize() */ #ifndef _di_controller_asynchronouss_resize_ extern f_status_t controller_asynchronouss_resize(const f_array_length_t length, controller_asynchronouss_t *asynchronouss) f_gcc_attribute_visibility_internal; #endif // _di_controller_asynchronouss_resize_ /** + * Fully deallocate all memory for the given cache without caring about return status. + * + * @param cache + * The cache to deallocate. + * + * @see f_string_dynamic_resize() + */ +#ifndef _di_controller_cache_action_delete_simple_ + extern void controller_cache_action_delete_simple(controller_cache_action_t *cache) f_gcc_attribute_visibility_internal; +#endif // _di_controller_cache_action_delete_simple_ + +/** + * Fully deallocate all memory for the given cache without caring about return status. + * + * @param cache + * The cache to deallocate. + * + * @see f_macro_array_lengths_t_delete_simple() + * @see f_macro_fss_delimits_t_delete_simple() + * + * @see controller_cache_action_delete_simple() + * @see f_string_dynamic_resize() + * @see f_string_ranges_resize() + * @see f_string_rangess_resize() + */ +#ifndef _di_controller_cache_delete_simple_ + extern void controller_cache_delete_simple(controller_cache_t *cache) f_gcc_attribute_visibility_internal; +#endif // _di_controller_cache_delete_simple_ + +/** + * Fully deallocate all memory for the given entry action without caring about return status. + * + * @param action + * The action to deallocate. + * + * @see f_string_dynamics_resize() + */ +#ifndef _di_controller_entry_action_delete_simple_ + extern void controller_entry_action_delete_simple(controller_entry_action_t *action) f_gcc_attribute_visibility_internal; +#endif // _di_controller_entry_action_delete_simple_ + +/** + * Fully deallocate all memory for the given entry actions without caring about return status. + * + * @param actions + * The entry_actions to deallocate. + * + * @see controller_entry_action_delete_simple() + * @see f_memory_delete() + */ +#ifndef _di_controller_entry_actions_delete_simple_ + extern void controller_entry_actions_delete_simple(controller_entry_actions_t *actions) f_gcc_attribute_visibility_internal; +#endif // _di_controller_entry_actions_delete_simple_ + +/** + * Fully deallocate all memory for the given entry item without caring about return status. + * + * @param item + * The item to deallocate. + * + * @see f_string_dynamic_resize() + */ +#ifndef _di_controller_entry_item_delete_simple_ + extern void controller_entry_item_delete_simple(controller_entry_item_t *item) f_gcc_attribute_visibility_internal; +#endif // _di_controller_entry_item_delete_simple_ + +/** + * Fully deallocate all memory for the given entry items without caring about return status. + * + * @param items + * The entry_items to deallocate. + * + * @see controller_entry_item_delete_simple() + * @see f_memory_delete() + */ +#ifndef _di_controller_entry_items_delete_simple_ + extern void controller_entry_items_delete_simple(controller_entry_items_t *items) f_gcc_attribute_visibility_internal; +#endif // _di_controller_entry_items_delete_simple_ + +/** * Print the error, locking the print mutex during the print. * * @param print @@ -1076,23 +1239,228 @@ extern "C" { #endif // _di_controller_error_print_locked_ /** - * Increase the size of the rules array, but only if necessary. + * Fully deallocate all memory for the given process without caring about return status. * - * @param rules - * The rules to resize. + * @param process + * The process to deallocate. + * + * @see f_string_dynamic_resize() + * @see f_thread_condition_delete() + * @see f_thread_mutex_delete() + */ +#ifndef _di_controller_process_delete_simple_ + extern void controller_process_delete_simple(controller_process_t *process) f_gcc_attribute_visibility_internal; +#endif // _di_controller_process_delete_simple_ + +/** + * Fully deallocate all memory for the given processs without caring about return status. + * + * @param processs + * The process array to deallocate. + * + * @see controller_processs_resize() + */ +#ifndef _di_controller_processs_delete_simple_ + extern void controller_processs_delete_simple(controller_processs_t *processs) f_gcc_attribute_visibility_internal; +#endif // _di_controller_processs_delete_simple_ + +/** + * Increase the size of the rule array, but only if necessary. + * + * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param processs + * The process array to resize. * * @return * F_none on success. - * F_array_too_large (with error bit) if the resulting new size is bigger than the max array length. + * F_data_not on success, but there is no reason to increase size (used + controller_default_allocation_step <= size). * - * Errors (with error bit) from: f_memory_resize(). + * F_array_too_large (with error bit) if the new array length is too large. + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see controller_processs_resize() + */ +#ifndef _di_controller_processs_increase_ + extern f_status_t controller_processs_increase(controller_processs_t *processs) f_gcc_attribute_visibility_internal; +#endif // _di_controller_rule_increase_ + +/** + * Resize the rule array. + * + * @param length + * The new size to use. + * @param processs + * The process array to resize. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. * * @see f_memory_resize() */ +#ifndef _di_controller_processs_resize_ + extern f_status_t controller_processs_resize(const f_array_length_t length, controller_processs_t *processs) f_gcc_attribute_visibility_internal; +#endif // _di_controller_processs_resize_ + +/** + * Fully deallocate all memory for the given rule action without caring about return status. + * + * @param action + * The action to deallocate. + * + * @see f_string_dynamics_resize() + */ +#ifndef _di_controller_rule_action_delete_simple_ + extern void controller_rule_action_delete_simple(controller_rule_action_t *action) f_gcc_attribute_visibility_internal; +#endif // _di_controller_rule_action_delete_simple_ + +/** + * Fully deallocate all memory for the given rule actions without caring about return status. + * + * @param actions + * The rule_actions to deallocate. + * + * @see controller_rule_action_delete_simple() + * @see f_memory_delete() + */ +#ifndef _di_controller_rule_actions_delete_simple_ + extern void controller_rule_actions_delete_simple(controller_rule_actions_t *actions) f_gcc_attribute_visibility_internal; +#endif // _di_controller_rule_actions_delete_simple_ + +/** + * Fully deallocate all memory for the given rule without caring about return status. + * + * @param rule + * The rule to deallocate. + * + * @see f_macro_control_group_t_delete_simple() + * @see f_macro_int32s_t_delete_simple() + * @see f_macro_limit_sets_t_delete_simple() + * @see f_macro_string_dynamics_t_delete_simple() + * @see f_macro_string_maps_t_delete_simple() + * @see f_macro_thread_condition_t_delete_simple() + * @see f_macro_thread_mutex_t_delete_simple() + * + * @see controller_rule_items_delete_simple() + * @see f_capability_delete() + * @see f_string_dynamic_resize() + */ +#ifndef _di_controller_rule_delete_simple_ + extern void controller_rule_delete_simple(controller_rule_t *rule) f_gcc_attribute_visibility_internal; +#endif // _di_controller_rule_delete_simple_ + +/** + * Fully deallocate all memory for the given rule item without caring about return status. + * + * @param item + * The item to deallocate. + * + * @see f_string_dynamic_resize() + */ +#ifndef _di_controller_rule_item_delete_simple_ + extern void controller_rule_item_delete_simple(controller_rule_item_t *item) f_gcc_attribute_visibility_internal; +#endif // _di_controller_rule_item_delete_simple_ + +/** + * Fully deallocate all memory for the given rule items without caring about return status. + * + * @param items + * The rule_items to deallocate. + * + * @see controller_rule_item_delete_simple() + * @see f_memory_delete() + */ +#ifndef _di_controller_rule_items_delete_simple_ + extern void controller_rule_items_delete_simple(controller_rule_items_t *items) f_gcc_attribute_visibility_internal; +#endif // _di_controller_rule_items_delete_simple_ + +/** + * Fully deallocate all memory for the given rules without caring about return status. + * + * @param rules + * The rules to deallocate. + * + * @see controller_rules_resize() + */ +#ifndef _di_controller_rules_delete_simple_ + extern void controller_rules_delete_simple(controller_rules_t *rules) f_gcc_attribute_visibility_internal; +#endif // _di_controller_rules_delete_simple_ + +/** + * Increase the size of the rule array, but only if necessary. + * + * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param rules + * The rule array to resize. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + controller_default_allocation_step <= size). + * + * F_array_too_large (with error bit) if the new array length is too large. + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see controller_rules_resize() + */ #ifndef _di_controller_rules_increase_ extern f_status_t controller_rules_increase(controller_rules_t *rules) f_gcc_attribute_visibility_internal; #endif // _di_controller_rule_increase_ +/** + * Resize the rule array. + * + * @param length + * The new size to use. + * @param rules + * The rule array to resize. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + * + * @see f_memory_resize() + */ +#ifndef _di_controller_rules_resize_ + extern f_status_t controller_rules_resize(const f_array_length_t length, controller_rules_t *rules) f_gcc_attribute_visibility_internal; +#endif // _di_controller_rules_resize_ + +/** + * Fully deallocate all memory for the given setting without caring about return status. + * + * @param setting + * The setting to deallocate. + * + * @see controller_entry_delete_simple() + * @see controller_rules_delete_simple() + * @see f_string_dynamic_resize() + */ +#ifndef _di_controller_setting_delete_simple_ + extern void controller_setting_delete_simple(controller_setting_t *setting) f_gcc_attribute_visibility_internal; +#endif // _di_controller_setting_delete_simple_ + +/** + * Fully deallocate all memory for the given setting without caring about return status. + * + * @param thread + * The thread to deallocate. + * + * @see controller_asynchronouss_resize() + * @see f_thread_mutex_unlock() + */ +#ifndef _di_controller_thread_delete_simple_ + extern void controller_thread_delete_simple(controller_thread_t *thread) f_gcc_attribute_visibility_internal; +#endif // _di_controller_thread_delete_simple_ + #ifdef __cplusplus } // extern "C" #endif diff --git a/level_3/controller/c/private-controller.c b/level_3/controller/c/private-controller.c index a976a0a..3b096b4 100644 --- a/level_3/controller/c/private-controller.c +++ b/level_3/controller/c/private-controller.c @@ -41,7 +41,7 @@ extern "C" { #endif // _di_controller_string_dynamic_partial_append_terminated_ #ifndef _di_controller_file_load_ - f_status_t controller_file_load(const controller_data_t data, const controller_setting_t setting, const f_string_t path_prefix, const f_string_static_t path_name, const f_string_t path_suffix, const f_string_length_t path_prefix_length, const f_string_length_t path_suffix_length, controller_cache_t *cache) { + f_status_t controller_file_load(const f_string_t path_prefix, const f_string_static_t path_name, const f_string_t path_suffix, const f_array_length_t path_prefix_length, const f_array_length_t path_suffix_length, controller_thread_data_t thread_data, controller_cache_t *cache) { f_status_t status = F_none; f_file_t file = f_file_t_initialize; @@ -69,25 +69,25 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_string_append", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_append", F_true); return status; } status = f_string_dynamic_terminate_after(&cache->action.name_file); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true); return status; } - const f_string_length_t path_length = setting.path_setting.used ? setting.path_setting.used + f_path_separator_length + cache->action.name_file.used : cache->action.name_file.used; + const f_array_length_t path_length = thread_data.setting->path_setting.used ? thread_data.setting->path_setting.used + f_path_separator_length + cache->action.name_file.used : cache->action.name_file.used; char path[path_length + 1]; - if (setting.path_setting.used) { - memcpy(path, setting.path_setting.string, setting.path_setting.used); - memcpy(path + setting.path_setting.used + f_path_separator_length, cache->action.name_file.string, cache->action.name_file.used); + if (thread_data.setting->path_setting.used) { + memcpy(path, thread_data.setting->path_setting.string, thread_data.setting->path_setting.used); + memcpy(path + thread_data.setting->path_setting.used + f_path_separator_length, cache->action.name_file.string, cache->action.name_file.used); - path[setting.path_setting.used] = f_path_separator_s[0]; + path[thread_data.setting->path_setting.used] = f_path_separator_s[0]; } path[path_length] = 0; @@ -95,13 +95,13 @@ extern "C" { status = f_file_stream_open(path, 0, &file); if (F_status_is_error(status)) { - fll_error_file_print(data.error, F_status_set_fine(status), "f_file_stream_open", F_true, path, "open", fll_error_file_type_file); + fll_error_file_print(thread_data.data->error, F_status_set_fine(status), "f_file_stream_open", F_true, path, "open", fll_error_file_type_file); } else { status = f_file_stream_read(file, 1, &cache->buffer_file); if (F_status_is_error(status)) { - fll_error_file_print(data.error, F_status_set_fine(status), "f_file_stream_read", F_true, path, "read", fll_error_file_type_file); + fll_error_file_print(thread_data.data->error, F_status_set_fine(status), "f_file_stream_read", F_true, path, "read", fll_error_file_type_file); } } @@ -113,7 +113,7 @@ extern "C" { status = f_file_stat(path, F_true, &stat_file); if (F_status_is_error(status)) { - fll_error_file_print(data.error, F_status_set_fine(status), "f_file_stat", F_true, path, "stat", fll_error_file_type_file); + fll_error_file_print(thread_data.data->error, F_status_set_fine(status), "f_file_stat", F_true, path, "stat", fll_error_file_type_file); } else { cache->timestamp.seconds = stat_file.st_ctim.tv_sec; @@ -304,29 +304,29 @@ extern "C" { #endif // _di_controller_get_id_group_ #ifndef _di_controller_perform_ready_ - f_status_t controller_perform_ready(const controller_data_t data, controller_setting_t *setting, controller_cache_t *cache) { + f_status_t controller_perform_ready(controller_thread_data_t thread_data, controller_cache_t *cache) { f_status_t status = F_none; // only create pid file when not in validate mode. - if (data.parameters[controller_parameter_validate].result == f_console_result_none) { + if (thread_data.data->parameters[controller_parameter_validate].result == f_console_result_none) { - status = controller_file_pid_create(data, setting->path_pid); + status = controller_file_pid_create(*thread_data.data, thread_data.setting->path_pid); // report pid file error but because this could be an "init" program, consider the pid file as optional and continue on. if (F_status_is_error(status)) { // always return immediately on memory errors. if (F_status_set_fine(status) == F_memory_not) { - fll_error_file_print(data.error, F_status_set_fine(status), "controller_file_pid_create", F_true, setting->path_pid.string, "create", fll_error_file_type_file); + fll_error_file_print(thread_data.data->error, F_status_set_fine(status), "controller_file_pid_create", F_true, thread_data.setting->path_pid.string, "create", fll_error_file_type_file); - controller_entry_error_print(data.error, cache->action); + controller_entry_error_print(thread_data.data->error, cache->action); return status; } - fll_error_file_print(data.warning, F_status_set_fine(status), "controller_file_pid_create", F_true, setting->path_pid.string, "create", fll_error_file_type_file); + fll_error_file_print(thread_data.data->warning, F_status_set_fine(status), "controller_file_pid_create", F_true, thread_data.setting->path_pid.string, "create", fll_error_file_type_file); - controller_entry_error_print(data.warning, cache->action); + controller_entry_error_print(thread_data.data->warning, cache->action); status = F_none; } @@ -337,7 +337,7 @@ extern "C" { #endif // _di_controller_perform_ready_ #ifndef _di_controller_preprocess_entry_ - f_status_t controller_preprocess_entry(controller_cache_t *cache, controller_thread_t *thread) { + f_status_t controller_preprocess_entry(controller_thread_data_t thread_data, controller_cache_t *cache) { f_status_t status = F_none; f_status_t status2 = F_none; @@ -347,25 +347,23 @@ extern "C" { f_array_length_t at_i = 0; f_array_length_t at_j = 1; - controller_data_t *data = thread->data; - controller_setting_t *setting = thread->setting; controller_entry_actions_t *actions = 0; uint8_t error_has = F_false; - setting->ready = controller_setting_ready_no; + thread_data.setting->ready = controller_setting_ready_no; cache->ats.used = 0; - thread->cache_action->line_action = 0; - thread->cache_action->line_item = 0; - thread->cache_action->name_action.used = 0; - thread->cache_action->name_item.used = 0; + cache->action.line_action = 0; + cache->action.line_item = 0; + cache->action.name_action.used = 0; + cache->action.name_item.used = 0; f_macro_array_lengths_t_increase_by(status, cache->ats, controller_default_allocation_step) if (F_status_is_error(status)) { - fll_error_print(data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true); return status; } @@ -374,55 +372,55 @@ extern "C" { cache->ats.array[1] = 0; cache->ats.used = 2; - thread->cache_action->line_item = setting->entry.items.array[0].line; - thread->cache_action->name_item.used = 0; + cache->action.line_item = thread_data.setting->entry.items.array[0].line; + cache->action.name_item.used = 0; - status = controller_string_dynamic_append_terminated(setting->entry.items.array[0].name, &thread->cache_action->name_item); + status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[0].name, &cache->action.name_item); if (F_status_is_error(status)) { - fll_error_print(data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); - controller_entry_error_print(data->error, *thread->cache_action); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); + controller_entry_error_print(thread_data.data->error, cache->action); return status; } for (;;) { - actions = &setting->entry.items.array[cache->ats.array[at_i]].actions; + actions = &thread_data.setting->entry.items.array[cache->ats.array[at_i]].actions; for (; cache->ats.array[at_j] < actions->used; ++cache->ats.array[at_j]) { - if (setting->signal) { + if (thread_data.setting->signal) { return F_signal; } - thread->cache_action->line_action = actions->array[cache->ats.array[at_j]].line; - thread->cache_action->name_action.used = 0; + cache->action.line_action = actions->array[cache->ats.array[at_j]].line; + cache->action.name_action.used = 0; - status2 = controller_string_dynamic_append_terminated(controller_entry_action_type_name(actions->array[cache->ats.array[at_j]].type), &thread->cache_action->name_action); + status2 = controller_string_dynamic_append_terminated(controller_entry_action_type_name(actions->array[cache->ats.array[at_j]].type), &cache->action.name_action); if (F_status_is_error(status2)) { - fll_error_print(data->error, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true); - controller_entry_error_print(data->error, *thread->cache_action); + fll_error_print(thread_data.data->error, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true); + controller_entry_error_print(thread_data.data->error, cache->action); return status2; } if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_ready) { - if (setting->ready == controller_setting_ready_wait) { - if (data->warning.verbosity == f_console_verbosity_debug) { - fprintf(data->warning.to.stream, "%c", f_string_eol_s[0]); - fprintf(data->warning.to.stream, "%s%sMultiple '", data->warning.context.before->string, data->warning.prefix ? data->warning.prefix : f_string_empty_s); - fprintf(data->warning.to.stream, "%s%s%s%s", data->warning.context.after->string, data->warning.notable.before->string, controller_string_ready_s, data->warning.notable.after->string); - fprintf(data->warning.to.stream, "%s' entry item actions detected; only the first will be used.%s%c", data->warning.context.before->string, data->warning.context.after->string, f_string_eol_s[0]); + if (thread_data.setting->ready == controller_setting_ready_wait) { + if (thread_data.data->warning.verbosity == f_console_verbosity_debug) { + fprintf(thread_data.data->warning.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->warning.to.stream, "%s%sMultiple '", thread_data.data->warning.context.before->string, thread_data.data->warning.prefix ? thread_data.data->warning.prefix : f_string_empty_s); + fprintf(thread_data.data->warning.to.stream, "%s%s%s%s", thread_data.data->warning.context.after->string, thread_data.data->warning.notable.before->string, controller_string_ready_s, thread_data.data->warning.notable.after->string); + fprintf(thread_data.data->warning.to.stream, "%s' entry item actions detected; only the first will be used.%s%c", thread_data.data->warning.context.before->string, thread_data.data->warning.context.after->string, f_string_eol_s[0]); - controller_entry_error_print(data->warning, *thread->cache_action); + controller_entry_error_print(thread_data.data->warning, cache->action); } } // the pre-process currently only looks for "ready", so once found, pre-process is complete. - setting->ready = controller_setting_ready_wait; + thread_data.setting->ready = controller_setting_ready_wait; } else if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_item) { error_has = F_false; @@ -432,22 +430,22 @@ extern "C" { } // walk though each items and check to see if the item actually exists (skipping main). - for (i = 1; i < setting->entry.items.used; ++i) { + for (i = 1; i < thread_data.setting->entry.items.used; ++i) { - if (fl_string_dynamic_compare(setting->entry.items.array[i].name, actions->array[cache->ats.array[at_j]].parameters.array[0]) == F_equal_to) { + if (fl_string_dynamic_compare(thread_data.setting->entry.items.array[i].name, actions->array[cache->ats.array[at_j]].parameters.array[0]) == F_equal_to) { // check to see if "i" is already in the stack (to prevent recursion) (skipping main). for (j = 2; j < cache->ats.used; j += 2) { if (cache->ats.array[j] == i) { - if (data->error.verbosity != f_console_verbosity_quiet) { - fprintf(data->error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data->error.to.stream, "%s%sThe entry item named '", data->error.context.before->string, data->error.prefix ? data->error.prefix : f_string_empty_s); - fprintf(data->error.to.stream, "%s%s%s%s", data->error.context.after->string, data->error.notable.before->string, setting->entry.items.array[i].name.string, data->error.notable.after->string); - fprintf(data->error.to.stream, "%s' cannot be executed because recursion is not allowed.%s%c", data->error.context.before->string, data->error.context.after->string, f_string_eol_s[0]); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe entry item named '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, thread_data.setting->entry.items.array[i].name.string, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s' cannot be executed because recursion is not allowed.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } - controller_entry_error_print(data->error, *thread->cache_action); + controller_entry_error_print(thread_data.data->error, cache->action); if (F_status_is_error_not(status)) { status = F_status_set_error(F_recurse); @@ -463,8 +461,8 @@ extern "C" { f_macro_array_lengths_t_increase_by(status2, cache->ats, controller_default_allocation_step) if (F_status_is_error(status2)) { - fll_error_print(data->error, F_status_set_fine(status2), "f_macro_array_lengths_t_increase_by", F_true); - controller_entry_error_print(data->error, *thread->cache_action); + fll_error_print(thread_data.data->error, F_status_set_fine(status2), "f_macro_array_lengths_t_increase_by", F_true); + controller_entry_error_print(thread_data.data->error, cache->action); return status2; } @@ -480,17 +478,17 @@ extern "C" { cache->ats.array[at_j] = 0; cache->ats.used += 2; - thread->cache_action->name_action.used = 0; - thread->cache_action->line_action = 0; + cache->action.name_action.used = 0; + cache->action.line_action = 0; - thread->cache_action->name_item.used = 0; - thread->cache_action->line_item = setting->entry.items.array[i].line; + cache->action.name_item.used = 0; + cache->action.line_item = thread_data.setting->entry.items.array[i].line; - status2 = controller_string_dynamic_append_terminated(setting->entry.items.array[i].name, &thread->cache_action->name_item); + status2 = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[i].name, &cache->action.name_item); if (F_status_is_error(status2)) { - fll_error_print(data->error, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true); - controller_entry_error_print(data->error, *thread->cache_action); + fll_error_print(thread_data.data->error, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true); + controller_entry_error_print(thread_data.data->error, cache->action); return status2; } @@ -499,16 +497,16 @@ extern "C" { } } // for - if (error_has || i >= setting->entry.items.used) { - if (i >= setting->entry.items.used) { - if (data->error.verbosity != f_console_verbosity_quiet) { - fprintf(data->error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data->error.to.stream, "%s%sThe entry item named '", data->error.context.before->string, data->error.prefix ? data->error.prefix : f_string_empty_s); - fprintf(data->error.to.stream, "%s%s%s%s", data->error.context.after->string, data->error.notable.before->string, actions->array[cache->ats.array[at_j]].parameters.array[0].string, data->error.notable.after->string); - fprintf(data->error.to.stream, "%s' does not exist.%s%c", data->error.context.before->string, data->error.context.after->string, f_string_eol_s[0]); + if (error_has || i >= thread_data.setting->entry.items.used) { + if (i >= thread_data.setting->entry.items.used) { + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe entry item named '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, actions->array[cache->ats.array[at_j]].parameters.array[0].string, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s' does not exist.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } - controller_entry_error_print(data->error, *thread->cache_action); + controller_entry_error_print(thread_data.data->error, cache->action); if (F_status_is_error_not(status)) { status = F_status_set_error(F_valid_not); @@ -521,8 +519,8 @@ extern "C" { } } // for - thread->cache_action->line_action = 0; - thread->cache_action->name_action.used = 0; + cache->action.line_action = 0; + cache->action.name_action.used = 0; // end of actions found, so drop to previous loop in stack. if (cache->ats.array[at_j] == actions->used) { @@ -536,14 +534,14 @@ extern "C" { cache->ats.used -= 2; cache->ats.array[at_j]++; - thread->cache_action->line_item = setting->entry.items.array[cache->ats.array[at_i]].line; - thread->cache_action->name_item.used = 0; + cache->action.line_item = thread_data.setting->entry.items.array[cache->ats.array[at_i]].line; + cache->action.name_item.used = 0; - status2 = controller_string_dynamic_append_terminated(setting->entry.items.array[cache->ats.array[at_i]].name, &thread->cache_action->name_item); + status2 = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item); if (F_status_is_error(status2)) { - fll_error_print(data->error, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true); - controller_entry_error_print(data->error, *thread->cache_action); + fll_error_print(thread_data.data->error, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true); + controller_entry_error_print(thread_data.data->error, cache->action); return status2; } @@ -551,8 +549,8 @@ extern "C" { } // for // if ready was never found in the entry, then default to always ready. - if (setting->ready == controller_setting_ready_no) { - setting->ready = controller_setting_ready_yes; + if (thread_data.setting->ready == controller_setting_ready_no) { + thread_data.setting->ready = controller_setting_ready_yes; } return status; @@ -560,7 +558,7 @@ extern "C" { #endif // _di_controller_preprocess_entry_ #ifndef _di_controller_process_entry_ - f_status_t controller_process_entry(controller_cache_t *cache, controller_thread_t *thread) { + f_status_t controller_process_entry(controller_thread_data_t thread_data, controller_cache_t *cache) { f_status_t status = F_none; f_array_length_t i = 0; @@ -572,30 +570,28 @@ extern "C" { uint8_t rule_options = 0; - controller_data_t *data = thread->data; - controller_setting_t *setting = thread->setting; controller_entry_actions_t *actions = 0; - const bool simulate = data->parameters[controller_parameter_test].result == f_console_result_found; + const bool simulate = thread_data.data->parameters[controller_parameter_test].result == f_console_result_found; cache->ats.used = 0; cache->stack.used = 0; - thread->cache_action->line_action = 0; - thread->cache_action->line_item = 0; - thread->cache_action->name_action.used = 0; - thread->cache_action->name_item.used = 0; + cache->action.line_action = 0; + cache->action.line_item = 0; + cache->action.name_action.used = 0; + cache->action.name_item.used = 0; - if (setting->ready == controller_setting_ready_yes) { - status = controller_perform_ready(*data, setting, cache); + if (thread_data.setting->ready == controller_setting_ready_yes) { + status = controller_perform_ready(thread_data, cache); if (F_status_is_error(status)) return status; } f_macro_array_lengths_t_increase_by(status, cache->ats, controller_default_allocation_step) if (F_status_is_error(status)) { - fll_error_print(data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true); - controller_entry_error_print(data->error, *thread->cache_action); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true); + controller_entry_error_print(thread_data.data->error, cache->action); return status; } @@ -605,44 +601,44 @@ extern "C" { cache->ats.array[1] = 0; cache->ats.used = 2; - thread->cache_action->line_item = setting->entry.items.array[0].line; - thread->cache_action->name_item.used = 0; + cache->action.line_item = thread_data.setting->entry.items.array[0].line; + cache->action.name_item.used = 0; - status = controller_string_dynamic_append_terminated(setting->entry.items.array[0].name, &thread->cache_action->name_item); + status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[0].name, &cache->action.name_item); if (F_status_is_error(status)) { - fll_error_print(data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); - controller_entry_error_print(data->error, *thread->cache_action); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); + controller_entry_error_print(thread_data.data->error, cache->action); return status; } if (simulate) { - fprintf(data->output.stream, "%c", f_string_eol_s[0]); - fprintf(data->output.stream, "Processing entry item rule '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_main_s, data->context.set.title.after->string); - fprintf(data->output.stream, "'.%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "Processing entry item rule '"); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.set.title.before->string, controller_string_main_s, thread_data.data->context.set.title.after->string); + fprintf(thread_data.data->output.stream, "'.%c", f_string_eol_s[0]); } for (;;) { - actions = &setting->entry.items.array[cache->ats.array[at_i]].actions; + actions = &thread_data.setting->entry.items.array[cache->ats.array[at_i]].actions; for (; cache->ats.array[at_j] < actions->used; ++cache->ats.array[at_j]) { - if (setting->signal) { + if (thread_data.setting->signal) { status = F_signal; break; } - thread->cache_action->line_action = actions->array[cache->ats.array[at_j]].line; - thread->cache_action->name_action.used = 0; + cache->action.line_action = actions->array[cache->ats.array[at_j]].line; + cache->action.name_action.used = 0; - status = controller_string_dynamic_append_terminated(controller_entry_action_type_name(actions->array[cache->ats.array[at_j]].type), &thread->cache_action->name_action); + status = controller_string_dynamic_append_terminated(controller_entry_action_type_name(actions->array[cache->ats.array[at_j]].type), &cache->action.name_action); if (F_status_is_error(status)) { - fll_error_print(data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); - controller_entry_error_print(data->error, *thread->cache_action); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); + controller_entry_error_print(thread_data.data->error, cache->action); return status; } @@ -652,91 +648,91 @@ extern "C" { if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_rule) { if (simulate) { - fprintf(data->output.stream, "%c", f_string_eol_s[0]); - fprintf(data->output.stream, "The entry item action '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, thread->cache_action->name_action.string, data->context.set.title.after->string); + fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "The entry item action '"); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.set.title.before->string, cache->action.name_action.string, thread_data.data->context.set.title.after->string); if (actions->array[cache->ats.array[at_j]].parameters.used) { - fprintf(data->output.stream, f_string_space_s); - fprintf(data->output.stream, "%s", data->context.set.notable.before->string); - controller_entry_action_parameters_print(data->output.stream, actions->array[cache->ats.array[at_j]]); - fprintf(data->output.stream, "%s", data->context.set.notable.after->string); + fprintf(thread_data.data->output.stream, f_string_space_s); + fprintf(thread_data.data->output.stream, "%s", thread_data.data->context.set.notable.before->string); + controller_entry_action_parameters_print(thread_data.data->output.stream, actions->array[cache->ats.array[at_j]]); + fprintf(thread_data.data->output.stream, "%s", thread_data.data->context.set.notable.after->string); } - fprintf(data->output.stream, "' is %s and is in a %sfailed%s state, skipping execution.%c", actions->array[cache->ats.array[at_j]].code & controller_entry_rule_code_require ? "required" : "optional", data->error.context.before->string, data->error.context.after->string, f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "' is %s and is in a %sfailed%s state, skipping execution.%c", actions->array[cache->ats.array[at_j]].code & controller_entry_rule_code_require ? "required" : "optional", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } else if (actions->array[cache->ats.array[at_j]].code & controller_entry_rule_code_require) { - if (data->error.verbosity != f_console_verbosity_quiet) { - fprintf(data->error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data->error.to.stream, "%s%sThe entry item action '", data->error.context.before->string, data->error.prefix ? data->error.prefix : f_string_empty_s); - fprintf(data->error.to.stream, "%s%s%s", data->error.context.after->string, data->error.notable.before->string, thread->cache_action->name_action.string); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe entry item action '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, cache->action.name_action.string); if (actions->array[cache->ats.array[at_j]].parameters.used) { - fprintf(data->error.to.stream, f_string_space_s); - controller_entry_action_parameters_print(data->error.to.stream, actions->array[cache->ats.array[at_j]]); + fprintf(thread_data.data->error.to.stream, f_string_space_s); + controller_entry_action_parameters_print(thread_data.data->error.to.stream, actions->array[cache->ats.array[at_j]]); } - fprintf(data->error.to.stream, "%s%s' is ", data->error.notable.after->string, data->error.context.before->string); - fprintf(data->error.to.stream, "%s%srequired%s", data->error.context.after->string, data->error.notable.before->string, data->error.notable.after->string); - fprintf(data->error.to.stream, "%s and is in a ", data->error.context.before->string); - fprintf(data->error.to.stream, "%s%sfailed%s", data->error.context.after->string, data->error.notable.before->string, data->error.notable.after->string); - fprintf(data->error.to.stream, "%s state, skipping execution.%s%c", data->error.context.before->string, data->error.context.after->string, f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%s' is ", thread_data.data->error.notable.after->string, thread_data.data->error.context.before->string); + fprintf(thread_data.data->error.to.stream, "%s%srequired%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s and is in a ", thread_data.data->error.context.before->string); + fprintf(thread_data.data->error.to.stream, "%s%sfailed%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s state, skipping execution.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } - controller_entry_error_print(data->error, *thread->cache_action); + controller_entry_error_print(thread_data.data->error, cache->action); return F_status_is_error(F_require); } - else if (data->warning.verbosity == f_console_verbosity_debug) { - fprintf(data->warning.to.stream, "%c", f_string_eol_s[0]); - fprintf(data->warning.to.stream, "%s%sThe entry item action '", data->warning.context.before->string, data->warning.prefix ? data->warning.prefix : f_string_empty_s); - fprintf(data->warning.to.stream, "%s%s%s", data->warning.context.after->string, data->warning.notable.before->string, thread->cache_action->name_action.string); + else if (thread_data.data->warning.verbosity == f_console_verbosity_debug) { + fprintf(thread_data.data->warning.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->warning.to.stream, "%s%sThe entry item action '", thread_data.data->warning.context.before->string, thread_data.data->warning.prefix ? thread_data.data->warning.prefix : f_string_empty_s); + fprintf(thread_data.data->warning.to.stream, "%s%s%s", thread_data.data->warning.context.after->string, thread_data.data->warning.notable.before->string, cache->action.name_action.string); if (actions->array[cache->ats.array[at_j]].parameters.used) { - fprintf(data->warning.to.stream, f_string_space_s); - controller_entry_action_parameters_print(data->warning.to.stream, actions->array[cache->ats.array[at_j]]); + fprintf(thread_data.data->warning.to.stream, f_string_space_s); + controller_entry_action_parameters_print(thread_data.data->warning.to.stream, actions->array[cache->ats.array[at_j]]); } - fprintf(data->warning.to.stream, "%s%s' is ", data->warning.notable.after->string, data->warning.context.before->string); - fprintf(data->warning.to.stream, "%s%srequired%s", data->warning.context.after->string, data->warning.notable.before->string, data->warning.notable.after->string); - fprintf(data->warning.to.stream, "%s and is in a ", data->warning.context.before->string); - fprintf(data->warning.to.stream, "%s%sfailed%s", data->warning.context.after->string, data->warning.notable.before->string, data->warning.notable.after->string); - fprintf(data->warning.to.stream, "%s state, skipping execution.%s%c", data->warning.context.before->string, data->warning.context.after->string, f_string_eol_s[0]); + fprintf(thread_data.data->warning.to.stream, "%s%s' is ", thread_data.data->warning.notable.after->string, thread_data.data->warning.context.before->string); + fprintf(thread_data.data->warning.to.stream, "%s%srequired%s", thread_data.data->warning.context.after->string, thread_data.data->warning.notable.before->string, thread_data.data->warning.notable.after->string); + fprintf(thread_data.data->warning.to.stream, "%s and is in a ", thread_data.data->warning.context.before->string); + fprintf(thread_data.data->warning.to.stream, "%s%sfailed%s", thread_data.data->warning.context.after->string, thread_data.data->warning.notable.before->string, thread_data.data->warning.notable.after->string); + fprintf(thread_data.data->warning.to.stream, "%s state, skipping execution.%s%c", thread_data.data->warning.context.before->string, thread_data.data->warning.context.after->string, f_string_eol_s[0]); - controller_entry_error_print(data->warning, *thread->cache_action); + controller_entry_error_print(thread_data.data->warning, cache->action); } } else { if (simulate) { - fprintf(data->output.stream, "%c", f_string_eol_s[0]); - fprintf(data->output.stream, "The entry item action '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, thread->cache_action->name_action.string, data->context.set.title.after->string); + fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "The entry item action '"); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.set.title.before->string, cache->action.name_action.string, thread_data.data->context.set.title.after->string); if (actions->array[cache->ats.array[at_j]].parameters.used) { - fprintf(data->output.stream, f_string_space_s); - fprintf(data->output.stream, "%s", data->context.set.notable.before->string); - controller_entry_action_parameters_print(data->output.stream, actions->array[cache->ats.array[at_j]]); - fprintf(data->output.stream, "%s", data->context.set.notable.after->string); + fprintf(thread_data.data->output.stream, f_string_space_s); + fprintf(thread_data.data->output.stream, "%s", thread_data.data->context.set.notable.before->string); + controller_entry_action_parameters_print(thread_data.data->output.stream, actions->array[cache->ats.array[at_j]]); + fprintf(thread_data.data->output.stream, "%s", thread_data.data->context.set.notable.after->string); } - fprintf(data->output.stream, "' is in a %sfailed%s state, skipping.%c", data->error.context.before->string, data->error.context.after->string, f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "' is in a %sfailed%s state, skipping.%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } - else if (data->warning.verbosity == f_console_verbosity_debug) { - fprintf(data->warning.to.stream, "%c", f_string_eol_s[0]); - fprintf(data->warning.to.stream, "%s%sThe entry item action '", data->warning.context.before->string, data->warning.prefix ? data->warning.prefix : f_string_empty_s); - fprintf(data->warning.to.stream, "%s%s", data->warning.notable.before->string, thread->cache_action->name_action.string); + else if (thread_data.data->warning.verbosity == f_console_verbosity_debug) { + fprintf(thread_data.data->warning.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->warning.to.stream, "%s%sThe entry item action '", thread_data.data->warning.context.before->string, thread_data.data->warning.prefix ? thread_data.data->warning.prefix : f_string_empty_s); + fprintf(thread_data.data->warning.to.stream, "%s%s", thread_data.data->warning.notable.before->string, cache->action.name_action.string); if (actions->array[cache->ats.array[at_j]].parameters.used) { - fprintf(data->warning.to.stream, f_string_space_s); - controller_entry_action_parameters_print(data->warning.to.stream, actions->array[cache->ats.array[at_j]]); + fprintf(thread_data.data->warning.to.stream, f_string_space_s); + controller_entry_action_parameters_print(thread_data.data->warning.to.stream, actions->array[cache->ats.array[at_j]]); } - fprintf(data->warning.to.stream, "%s' is in a ", data->warning.notable.after->string); - fprintf(data->warning.to.stream, "%s%sfailed%s", data->warning.context.after->string, data->warning.notable.before->string, data->warning.notable.after->string); - fprintf(data->warning.to.stream, "%s state, skipping.%s%c", data->warning.context.before->string, data->warning.context.after->string, f_string_eol_s[0]); + fprintf(thread_data.data->warning.to.stream, "%s' is in a ", thread_data.data->warning.notable.after->string); + fprintf(thread_data.data->warning.to.stream, "%s%sfailed%s", thread_data.data->warning.context.after->string, thread_data.data->warning.notable.before->string, thread_data.data->warning.notable.after->string); + fprintf(thread_data.data->warning.to.stream, "%s state, skipping.%s%c", thread_data.data->warning.context.before->string, thread_data.data->warning.context.after->string, f_string_eol_s[0]); - controller_entry_error_print(data->warning, *thread->cache_action); + controller_entry_error_print(thread_data.data->warning, cache->action); } } @@ -745,41 +741,41 @@ extern "C" { if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_ready) { - if (setting->ready == controller_setting_ready_wait) { + if (thread_data.setting->ready == controller_setting_ready_wait) { if (simulate) { - fprintf(data->output.stream, "%c", f_string_eol_s[0]); - fprintf(data->output.stream, "Processing entry item action '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_ready_s, data->context.set.title.after->string); - fprintf(data->output.stream, "'.%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "Processing entry item action '"); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.set.title.before->string, controller_string_ready_s, thread_data.data->context.set.title.after->string); + fprintf(thread_data.data->output.stream, "'.%c", f_string_eol_s[0]); } else { - controller_perform_ready(*data, setting, cache); + controller_perform_ready(thread_data, cache); if (F_status_is_error(status)) return status; } - setting->ready = controller_setting_ready_yes; + thread_data.setting->ready = controller_setting_ready_yes; } else if (simulate) { - fprintf(data->output.stream, "%c", f_string_eol_s[0]); - fprintf(data->output.stream, "Ignoring entry item action '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_ready_s, data->context.set.title.after->string); - fprintf(data->output.stream, "', state already is ready.%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "Ignoring entry item action '"); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.set.title.before->string, controller_string_ready_s, thread_data.data->context.set.title.after->string); + fprintf(thread_data.data->output.stream, "', state already is ready.%c", f_string_eol_s[0]); } } else if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_item) { - if (actions->array[cache->ats.array[at_j]].number == 0 || actions->array[cache->ats.array[at_j]].number >= setting->entry.items.used) { + if (actions->array[cache->ats.array[at_j]].number == 0 || actions->array[cache->ats.array[at_j]].number >= thread_data.setting->entry.items.used) { // This should not happen if the pre-process is working as designed, but in case it doesn't, return a critical error to prevent infinite recursion and similar errors. - if (data->error.verbosity != f_console_verbosity_quiet) { - fprintf(data->error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data->error.to.stream, "%s%sInvalid entry item index ", data->error.context.before->string, data->error.prefix ? data->error.prefix : f_string_empty_s); - fprintf(data->error.to.stream, "%s%s%llu%s", data->error.context.after->string, data->error.notable.before->string, actions->array[cache->ats.array[at_j]].number, data->error.notable.after->string); - fprintf(data->error.to.stream, "%s detected.%s%c", data->error.context.before->string, data->error.context.after->string, f_string_eol_s[0]); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sInvalid entry item index ", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%llu%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, actions->array[cache->ats.array[at_j]].number, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s detected.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } - controller_entry_error_print(data->error, *thread->cache_action); + controller_entry_error_print(thread_data.data->error, cache->action); return F_status_is_error(F_critical); } @@ -787,8 +783,8 @@ extern "C" { f_macro_array_lengths_t_increase_by(status, cache->ats, controller_default_allocation_step) if (F_status_is_error(status)) { - fll_error_print(data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true); - controller_entry_error_print(data->error, *thread->cache_action); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true); + controller_entry_error_print(thread_data.data->error, cache->action); return status; } @@ -802,26 +798,26 @@ extern "C" { cache->ats.used += 2; - thread->cache_action->name_action.used = 0; - thread->cache_action->line_action = 0; + cache->action.name_action.used = 0; + cache->action.line_action = 0; - thread->cache_action->name_item.used = 0; - thread->cache_action->line_item = setting->entry.items.array[cache->ats.array[at_i]].line; + cache->action.name_item.used = 0; + cache->action.line_item = thread_data.setting->entry.items.array[cache->ats.array[at_i]].line; - status = controller_string_dynamic_append_terminated(setting->entry.items.array[cache->ats.array[at_i]].name, &thread->cache_action->name_item); + status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item); if (F_status_is_error(status)) { - fll_error_print(data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); - controller_entry_error_print(data->error, *thread->cache_action); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); + controller_entry_error_print(thread_data.data->error, cache->action); return status; } if (simulate) { - fprintf(data->output.stream, "%c", f_string_eol_s[0]); - fprintf(data->output.stream, "Processing entry item '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, thread->cache_action->name_item.string, data->context.set.title.after->string); - fprintf(data->output.stream, "'.%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "Processing entry item '"); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.set.title.before->string, cache->action.name_item.string, thread_data.data->context.set.title.after->string); + fprintf(thread_data.data->output.stream, "'.%c", f_string_eol_s[0]); } // exit inner loop to force restarting and start processing the requested item. @@ -829,16 +825,16 @@ extern "C" { } else if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_consider || actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_rule) { - status = controller_rules_increase(&setting->rules); + status = controller_rules_increase(&thread_data.setting->rules); if (F_status_is_error(status)) { - fll_error_print(data->error, F_status_set_fine(status), "controller_rules_increase", F_true); - controller_entry_error_print(data->error, *thread->cache_action); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_rules_increase", F_true); + controller_entry_error_print(thread_data.data->error, cache->action); return status; } - const f_string_length_t rule_id_length = actions->array[cache->ats.array[at_j]].parameters.array[0].used + actions->array[cache->ats.array[at_j]].parameters.array[1].used + 1; + const f_array_length_t rule_id_length = actions->array[cache->ats.array[at_j]].parameters.array[0].used + actions->array[cache->ats.array[at_j]].parameters.array[1].used + 1; char rule_id_name[rule_id_length + 1]; const f_string_static_t rule_id = f_macro_string_static_t_initialize(rule_id_name, rule_id_length); @@ -848,79 +844,91 @@ extern "C" { rule_id_name[actions->array[cache->ats.array[at_j]].parameters.array[0].used] = f_path_separator_s[0]; rule_id_name[rule_id_length] = 0; - at = controller_rule_find_loaded(*data, *setting, rule_id); + f_thread_mutex_lock(&thread_data.thread->mutex.rule); + + at = controller_rule_find_loaded(rule_id, thread_data); + + if (at < thread_data.setting->rules.used) { + f_thread_mutex_unlock(&thread_data.thread->mutex.rule); + } if (simulate) { - fprintf(data->output.stream, "%c", f_string_eol_s[0]); - fprintf(data->output.stream, "%s entry item rule '", actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_rule ? "Processing" : "Considering"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, rule_id.string, data->context.set.title.after->string); - fprintf(data->output.stream, "'.%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "%s entry item rule '", actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_rule ? "Processing" : "Considering"); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.set.title.before->string, rule_id.string, thread_data.data->context.set.title.after->string); + fprintf(thread_data.data->output.stream, "'.%c", f_string_eol_s[0]); } // the rule is not yet loaded, ensure that it is loaded. - if (at == setting->rules.used) { + if (at == thread_data.setting->rules.used) { // rule execution will re-use the existing cache, so save the current cache. - const f_array_length_t cache_line_action = thread->cache_action->line_action; - const f_array_length_t cache_line_item = thread->cache_action->line_item; + const f_array_length_t cache_line_action = cache->action.line_action; + const f_array_length_t cache_line_item = cache->action.line_item; - const f_string_length_t cache_name_action_used = thread->cache_action->name_action.used; - const f_string_length_t cache_name_item_used = thread->cache_action->name_item.used; - const f_string_length_t cache_name_file_used = thread->cache_action->name_file.used; + const f_array_length_t cache_name_action_used = cache->action.name_action.used; + const f_array_length_t cache_name_item_used = cache->action.name_item.used; + const f_array_length_t cache_name_file_used = cache->action.name_file.used; char cache_name_action[cache_name_action_used]; char cache_name_item[cache_name_item_used]; char cache_name_file[cache_name_file_used]; - memcpy(cache_name_action, thread->cache_action->name_action.string, thread->cache_action->name_action.used); - memcpy(cache_name_item, thread->cache_action->name_item.string, thread->cache_action->name_item.used); - memcpy(cache_name_file, thread->cache_action->name_file.string, thread->cache_action->name_file.used); + memcpy(cache_name_action, cache->action.name_action.string, cache->action.name_action.used); + memcpy(cache_name_item, cache->action.name_item.string, cache->action.name_item.used); + memcpy(cache_name_file, cache->action.name_file.string, cache->action.name_file.used); - status = controller_rule_read(*data, *setting, rule_id, thread, cache, &setting->rules.array[setting->rules.used]); + status = controller_rule_read(rule_id, thread_data, cache, &thread_data.setting->rules.array[thread_data.setting->rules.used]); // restore cache. - memcpy(thread->cache_action->name_action.string, cache_name_action, cache_name_action_used); - memcpy(thread->cache_action->name_item.string, cache_name_item, cache_name_item_used); - memcpy(thread->cache_action->name_file.string, cache_name_file, cache_name_file_used); + memcpy(cache->action.name_action.string, cache_name_action, cache_name_action_used); + memcpy(cache->action.name_item.string, cache_name_item, cache_name_item_used); + memcpy(cache->action.name_file.string, cache_name_file, cache_name_file_used); - thread->cache_action->name_action.string[cache_name_action_used] = 0; - thread->cache_action->name_item.string[cache_name_item_used] = 0; - thread->cache_action->name_file.string[cache_name_file_used] = 0; + cache->action.name_action.string[cache_name_action_used] = 0; + cache->action.name_item.string[cache_name_item_used] = 0; + cache->action.name_file.string[cache_name_file_used] = 0; - thread->cache_action->name_action.used = cache_name_action_used; - thread->cache_action->name_item.used = cache_name_item_used; - thread->cache_action->name_file.used = cache_name_file_used; + cache->action.name_action.used = cache_name_action_used; + cache->action.name_item.used = cache_name_item_used; + cache->action.name_file.used = cache_name_file_used; - thread->cache_action->line_action = cache_line_action; - thread->cache_action->line_item = cache_line_item; + cache->action.line_action = cache_line_action; + cache->action.line_item = cache_line_item; if (F_status_is_error(status)) { - controller_entry_error_print(data->error, *thread->cache_action); + controller_entry_error_print(thread_data.data->error, cache->action); - if (!simulate) break; + if (!simulate) { + f_thread_mutex_unlock(&thread_data.thread->mutex.rule); + + break; + } } else { - setting->rules.used++; + thread_data.setting->rules.used++; } + + f_thread_mutex_unlock(&thread_data.thread->mutex.rule); } if (F_status_is_error_not(status)) { // rule execution will re-use the existing cache, so save the current cache. - const f_array_length_t cache_line_action = thread->cache_action->line_action; - const f_array_length_t cache_line_item = thread->cache_action->line_item; + const f_array_length_t cache_line_action = cache->action.line_action; + const f_array_length_t cache_line_item = cache->action.line_item; - const f_string_length_t cache_name_action_used = thread->cache_action->name_action.used; - const f_string_length_t cache_name_item_used = thread->cache_action->name_item.used; - const f_string_length_t cache_name_file_used = thread->cache_action->name_file.used; + const f_array_length_t cache_name_action_used = cache->action.name_action.used; + const f_array_length_t cache_name_item_used = cache->action.name_item.used; + const f_array_length_t cache_name_file_used = cache->action.name_file.used; char cache_name_action[cache_name_action_used]; char cache_name_item[cache_name_item_used]; char cache_name_file[cache_name_file_used]; - memcpy(cache_name_action, thread->cache_action->name_action.string, thread->cache_action->name_action.used); - memcpy(cache_name_item, thread->cache_action->name_item.string, thread->cache_action->name_item.used); - memcpy(cache_name_file, thread->cache_action->name_file.string, thread->cache_action->name_file.used); + memcpy(cache_name_action, cache->action.name_action.string, cache->action.name_action.used); + memcpy(cache_name_item, cache->action.name_item.string, cache->action.name_item.used); + memcpy(cache_name_file, cache->action.name_file.string, cache->action.name_file.used); if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_rule) { rule_options = 0; @@ -937,42 +945,45 @@ extern "C" { rule_options |= controller_rule_option_wait; } - f_thread_mutex_lock(&thread->setting->rules.array[at].lock); + // @fixme this logic needs to change. + // determine how to pass rule ids. + // each thread has a main rule, but child threads need to be copied over and passed somehow. + f_thread_mutex_lock(&thread_data.setting->rules.array[at].lock); if (actions->array[cache->ats.array[at_j]].code & controller_entry_rule_code_asynchronous) { rule_options |= controller_rule_option_asynchronous; - status = controller_rule_process_asynchronous(at, controller_rule_action_type_start, rule_options, thread); + status = controller_rule_process_asynchronous(at, controller_rule_action_type_start, rule_options, thread_data, cache); } else { - status = controller_rule_process(at, controller_rule_action_type_start, rule_options, thread, 0); + status = controller_rule_process(at, controller_rule_action_type_start, rule_options, thread_data, cache); } if (status == F_child || status == F_signal) break; - f_thread_condition_signal(&thread->setting->rules.array[at].wait); - f_thread_mutex_unlock(&thread->setting->rules.array[at].lock); + f_thread_condition_signal(&thread_data.setting->rules.array[at].wait); + f_thread_mutex_unlock(&thread_data.setting->rules.array[at].lock); } // restore cache. - memcpy(thread->cache_action->name_action.string, cache_name_action, cache_name_action_used); - memcpy(thread->cache_action->name_item.string, cache_name_item, cache_name_item_used); - memcpy(thread->cache_action->name_file.string, cache_name_file, cache_name_file_used); + memcpy(cache->action.name_action.string, cache_name_action, cache_name_action_used); + memcpy(cache->action.name_item.string, cache_name_item, cache_name_item_used); + memcpy(cache->action.name_file.string, cache_name_file, cache_name_file_used); - thread->cache_action->name_action.string[cache_name_action_used] = 0; - thread->cache_action->name_item.string[cache_name_item_used] = 0; - thread->cache_action->name_file.string[cache_name_file_used] = 0; + cache->action.name_action.string[cache_name_action_used] = 0; + cache->action.name_item.string[cache_name_item_used] = 0; + cache->action.name_file.string[cache_name_file_used] = 0; - thread->cache_action->name_action.used = cache_name_action_used; - thread->cache_action->name_item.used = cache_name_item_used; - thread->cache_action->name_file.used = cache_name_file_used; + cache->action.name_action.used = cache_name_action_used; + cache->action.name_item.used = cache_name_item_used; + cache->action.name_file.used = cache_name_file_used; - thread->cache_action->line_action = cache_line_action; - thread->cache_action->line_item = cache_line_item; + cache->action.line_action = cache_line_action; + cache->action.line_item = cache_line_item; } if (F_status_is_error(status)) { - controller_entry_error_print(data->error, *thread->cache_action); + controller_entry_error_print(thread_data.data->error, cache->action); if (!simulate || F_status_set_fine(status) == F_memory_not) { break; @@ -994,66 +1005,66 @@ extern "C" { code = controller_string_stop_s; } - fprintf(data->output.stream, "%c", f_string_eol_s[0]); - fprintf(data->output.stream, "Processing entry item action '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_timeout_s, data->context.set.title.after->string); - fprintf(data->output.stream, "' setting '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.important.before->string, code, data->context.set.important.after->string); - fprintf(data->output.stream, "' to '"); - fprintf(data->output.stream, "%s%llu%s", data->context.set.important.before->string, actions->array[cache->ats.array[at_j]].number, data->context.set.important.after->string); - fprintf(data->output.stream, "' MegaTime (milliseconds).%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "Processing entry item action '"); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.set.title.before->string, controller_string_timeout_s, thread_data.data->context.set.title.after->string); + fprintf(thread_data.data->output.stream, "' setting '"); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.set.important.before->string, code, thread_data.data->context.set.important.after->string); + fprintf(thread_data.data->output.stream, "' to '"); + fprintf(thread_data.data->output.stream, "%s%llu%s", thread_data.data->context.set.important.before->string, actions->array[cache->ats.array[at_j]].number, thread_data.data->context.set.important.after->string); + fprintf(thread_data.data->output.stream, "' MegaTime (milliseconds).%c", f_string_eol_s[0]); } if (actions->array[cache->ats.array[at_j]].code == controller_entry_timeout_code_kill) { - setting->timeout_kill = actions->array[cache->ats.array[at_j]].number; + thread_data.setting->timeout_kill = actions->array[cache->ats.array[at_j]].number; } else if (actions->array[cache->ats.array[at_j]].code == controller_entry_timeout_code_start) { - setting->timeout_start = actions->array[cache->ats.array[at_j]].number; + thread_data.setting->timeout_start = actions->array[cache->ats.array[at_j]].number; } else if (actions->array[cache->ats.array[at_j]].code == controller_entry_timeout_code_stop) { - setting->timeout_stop = actions->array[cache->ats.array[at_j]].number; + thread_data.setting->timeout_stop = actions->array[cache->ats.array[at_j]].number; } } else if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_failsafe) { - if (actions->array[cache->ats.array[at_j]].number == 0 || actions->array[cache->ats.array[at_j]].number >= setting->entry.items.used) { + if (actions->array[cache->ats.array[at_j]].number == 0 || actions->array[cache->ats.array[at_j]].number >= thread_data.setting->entry.items.used) { // This should not happen if the pre-process is working as designed, but in case it doesn't, return a critical error to prevent infinite recursion and similar errors. - if (data->error.verbosity != f_console_verbosity_quiet) { - fprintf(data->error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data->error.to.stream, "%s%sInvalid entry item index ", data->error.context.before->string, data->error.prefix ? data->error.prefix : f_string_empty_s); - fprintf(data->error.to.stream, "%s%s%llu%s", data->error.context.after->string, data->error.notable.before->string, actions->array[cache->ats.array[at_j]].number, data->error.notable.after->string); - fprintf(data->error.to.stream, "%s detected.%s%c", data->error.context.before->string, data->error.context.after->string, f_string_eol_s[0]); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sInvalid entry item index ", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%llu%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, actions->array[cache->ats.array[at_j]].number, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s detected.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } - controller_entry_error_print(data->error, *thread->cache_action); + controller_entry_error_print(thread_data.data->error, cache->action); return F_status_is_error(F_critical); } else { - setting->failsafe_enabled = F_true; - setting->failsafe_rule_id = actions->array[cache->ats.array[at_j]].number; + thread_data.setting->failsafe_enabled = F_true; + thread_data.setting->failsafe_rule_id = actions->array[cache->ats.array[at_j]].number; if (simulate) { - fprintf(data->output.stream, "%c", f_string_eol_s[0]); - fprintf(data->output.stream, "Processing entry item action '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, controller_string_failsafe_s, data->context.set.title.after->string); - fprintf(data->output.stream, "' setting value to '"); - fprintf(data->output.stream, "%s%s%s", data->context.set.important.before->string, setting->entry.items.array[setting->failsafe_rule_id].name.string, data->context.set.important.after->string); - fprintf(data->output.stream, "'.%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "Processing entry item action '"); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.set.title.before->string, controller_string_failsafe_s, thread_data.data->context.set.title.after->string); + fprintf(thread_data.data->output.stream, "' setting value to '"); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.set.important.before->string, thread_data.setting->entry.items.array[thread_data.setting->failsafe_rule_id].name.string, thread_data.data->context.set.important.after->string); + fprintf(thread_data.data->output.stream, "'.%c", f_string_eol_s[0]); } } } } // for - if (setting->signal) { + if (thread_data.setting->signal) { status = F_signal; } if (status == F_child || status == F_signal) break; - thread->cache_action->line_action = 0; - thread->cache_action->name_action.used = 0; + cache->action.line_action = 0; + cache->action.name_action.used = 0; if (F_status_is_error(status)) { if (!simulate || F_status_set_fine(status) == F_memory_not) { @@ -1073,14 +1084,14 @@ extern "C" { cache->ats.used -= 2; cache->ats.array[at_j]++; - thread->cache_action->line_item = setting->entry.items.array[cache->ats.array[at_i]].line; - thread->cache_action->name_item.used = 0; + cache->action.line_item = thread_data.setting->entry.items.array[cache->ats.array[at_i]].line; + cache->action.name_item.used = 0; - status = controller_string_dynamic_append_terminated(setting->entry.items.array[cache->ats.array[at_i]].name, &thread->cache_action->name_item); + status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item); if (F_status_is_error(status)) { - fll_error_print(data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); - controller_entry_error_print(data->error, *thread->cache_action); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); + controller_entry_error_print(thread_data.data->error, cache->action); break; } @@ -1092,7 +1103,7 @@ extern "C" { } if (F_status_is_error_not(status) && simulate) { - fprintf(data->output.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]); } return status; @@ -1144,7 +1155,7 @@ extern "C" { if (status == F_false) return F_false; } - for (f_string_length_t i = f_macro_utf_byte_width(name.string[0]); i < name.used; i += f_macro_utf_byte_width(name.string[i])) { + for (f_array_length_t i = f_macro_utf_byte_width(name.string[0]); i < name.used; i += f_macro_utf_byte_width(name.string[i])) { if (name.string[i] == '_') continue; @@ -1165,7 +1176,7 @@ extern "C" { f_status_t status = F_none; - for (f_string_length_t i = 0; i < name.used; i += f_macro_utf_byte_width(name.string[i])) { + for (f_array_length_t i = 0; i < name.used; i += f_macro_utf_byte_width(name.string[i])) { status = f_utf_is_graph(name.string, name.used); diff --git a/level_3/controller/c/private-controller.h b/level_3/controller/c/private-controller.h index a173406..38eb59a 100644 --- a/level_3/controller/c/private-controller.h +++ b/level_3/controller/c/private-controller.h @@ -80,10 +80,6 @@ extern "C" { /** * Load a file from the controller settings directory. * - * @param data - * The program data. - * @param setting - * The controller settings data. * @param path_prefix * The path prefix, such as 'entries' from '/etc/controller/entries/default.entry'. * @param path_name @@ -94,6 +90,8 @@ extern "C" { * The length of the prefix path. * @param path_suffix_length * The length of the suffix path. + * @param thread_data + * The thread data. * @param cache * The following within the cache is updated: * - name_file: The partial path of the file is inserted. @@ -116,7 +114,7 @@ extern "C" { * @see f_string_dynamic_terminate_after() */ #ifndef _di_controller_file_load_ - extern f_status_t controller_file_load(const controller_data_t data, const controller_setting_t setting, const f_string_t path_prefix, const f_string_static_t path_name, const f_string_t path_suffix, const f_string_length_t path_prefix_length, const f_string_length_t path_suffix_length, controller_cache_t *cache) f_gcc_attribute_visibility_internal; + extern f_status_t controller_file_load(const f_string_t path_prefix, const f_string_static_t path_name, const f_string_t path_suffix, const f_array_length_t path_prefix_length, const f_array_length_t path_suffix_length, controller_thread_data_t thread_data, controller_cache_t *cache) f_gcc_attribute_visibility_internal; #endif // _di_controller_file_load_ /** @@ -217,10 +215,8 @@ extern "C" { * * This prints messages on errors. * - * @param data - * The program data. - * @param setting - * The controller settings data. + * @param thread_data + * The thread data. * @param cache * The cache. * @@ -232,16 +228,16 @@ extern "C" { * @see controller_file_pid_create() */ #ifndef _di_controller_perform_ready_ - extern f_status_t controller_perform_ready(const controller_data_t data, controller_setting_t *setting, controller_cache_t *cache) f_gcc_attribute_visibility_internal; + extern f_status_t controller_perform_ready(controller_thread_data_t thread_data, controller_cache_t *cache) f_gcc_attribute_visibility_internal; #endif // _di_controller_perform_ready_ /** * Pre-process all items for the loaded entry. * + * @param thread_data + * The thread data. * @param cache * The main/global cache to use. - * @param thread - * The thread data. * * @return * F_none on success. @@ -260,16 +256,16 @@ extern "C" { * @see f_string_dynamic_terminate_after() */ #ifndef _di_controller_preprocess_entry_ - extern f_status_t controller_preprocess_entry(controller_cache_t *cache, controller_thread_t *thread) f_gcc_attribute_visibility_internal; + extern f_status_t controller_preprocess_entry(controller_thread_data_t thread_data, controller_cache_t *cache) f_gcc_attribute_visibility_internal; #endif // _di_controller_preprocess_entry_ /** * Process (execute) all items for the loaded entry. * + * @param thread_data + * The thread data. * @param cache * The main/global cache to use. - * @param thread - * The thread data. * * @return * F_none on success. @@ -284,7 +280,7 @@ extern "C" { * @see controller_string_dynamic_append_terminated() */ #ifndef _di_controller_process_entry_ - extern f_status_t controller_process_entry(controller_cache_t *cache, controller_thread_t *thread) f_gcc_attribute_visibility_internal; + extern f_status_t controller_process_entry(controller_thread_data_t thread_data, controller_cache_t *cache) f_gcc_attribute_visibility_internal; #endif // _di_controller_process_entry_ /** diff --git a/level_3/controller/c/private-entry.c b/level_3/controller/c/private-entry.c index 4679ef7..0834af0 100644 --- a/level_3/controller/c/private-entry.c +++ b/level_3/controller/c/private-entry.c @@ -91,7 +91,7 @@ extern "C" { #endif // _di_controller_entry_actions_increase_by_ #ifndef _di_controller_entry_actions_read_ - f_status_t controller_entry_actions_read(const controller_data_t data, const controller_setting_t setting, const f_string_range_t content_range, controller_cache_t *cache, controller_entry_actions_t *actions) { + f_status_t controller_entry_actions_read(const f_string_range_t content_range, controller_thread_data_t thread_data, controller_cache_t *cache, controller_entry_actions_t *actions) { f_status_t status = F_none; f_status_t status_action = F_none; @@ -119,7 +119,7 @@ extern "C" { } if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fll_fss_extended_read", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "fll_fss_extended_read", F_true); return status; } @@ -127,7 +127,7 @@ extern "C" { status = fl_fss_apply_delimit(cache->delimits, &cache->buffer_file); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true); return status; } @@ -137,7 +137,7 @@ extern "C" { status = controller_entry_actions_increase_by(cache->object_actions.used, actions); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "controller_entry_actions_increase_by", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_entry_actions_increase_by", F_true); return status; } @@ -167,7 +167,7 @@ extern "C" { status = f_fss_count_lines(cache->buffer_file, cache->object_actions.array[i].start, &cache->action.line_action); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_fss_count_lines", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_fss_count_lines", F_true); break; } @@ -176,7 +176,7 @@ extern "C" { status = controller_string_dynamic_rip_nulless_terminated(cache->buffer_file, cache->object_actions.array[i], &cache->action.name_action); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "controller_string_dynamic_rip_nulless_terminated", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_rip_nulless_terminated", F_true); break; } @@ -199,14 +199,14 @@ extern "C" { actions->array[actions->used].type = controller_entry_action_type_timeout; } else { - if (data.warning.verbosity == f_console_verbosity_debug) { - fprintf(data.warning.to.stream, "%s%sUnknown entry item action '", data.warning.context.before->string, data.warning.prefix ? data.warning.prefix : f_string_empty_s); - fprintf(data.warning.to.stream, "%s%s", data.warning.context.after->string, data.warning.notable.before->string); - f_print_dynamic(data.warning.to.stream, cache->action.name_action); - fprintf(data.warning.to.stream, "%s", data.warning.notable.after->string); - fprintf(data.warning.to.stream, "%s'.%s%c", data.warning.context.before->string, data.warning.context.after->string, f_string_eol_s[0]); - - controller_entry_error_print(data.warning, cache->action); + if (thread_data.data->warning.verbosity == f_console_verbosity_debug) { + fprintf(thread_data.data->warning.to.stream, "%s%sUnknown entry item action '", thread_data.data->warning.context.before->string, thread_data.data->warning.prefix ? thread_data.data->warning.prefix : f_string_empty_s); + fprintf(thread_data.data->warning.to.stream, "%s%s", thread_data.data->warning.context.after->string, thread_data.data->warning.notable.before->string); + f_print_dynamic(thread_data.data->warning.to.stream, cache->action.name_action); + fprintf(thread_data.data->warning.to.stream, "%s", thread_data.data->warning.notable.after->string); + fprintf(thread_data.data->warning.to.stream, "%s'.%s%c", thread_data.data->warning.context.before->string, thread_data.data->warning.context.after->string, f_string_eol_s[0]); + + controller_entry_error_print(thread_data.data->warning, cache->action); } continue; @@ -237,15 +237,15 @@ extern "C" { if (cache->content_actions.array[i].used < at_least || cache->content_actions.array[i].used > at_most) { action->status = F_status_set_error(F_parameter); - if (data.error.verbosity != f_console_verbosity_quiet) { - fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data.error.to.stream, "%s%sThe entry item action '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, cache->action.name_action.string, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s' requires ", data.error.context.before->string); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe entry item action '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, cache->action.name_action.string, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s' requires ", thread_data.data->error.context.before->string); if (action->type == controller_entry_action_type_failsafe || action->type == controller_entry_action_type_item) { - fprintf(data.error.to.stream, "%s%s%llu%s", data.error.context.after->string, data.error.notable.before->string, cache->action.line_action, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s or more parameters.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%s%llu%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, cache->action.line_action, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s or more parameters.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } else { uint8_t parameters = 0; @@ -257,9 +257,9 @@ extern "C" { parameters = 2; } - fprintf(data.error.to.stream, "exactly ", data.error.context.before->string); - fprintf(data.error.to.stream, "%s%s%u%s", data.error.context.after->string, data.error.notable.before->string, parameters, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s parameters.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "exactly ", thread_data.data->error.context.before->string); + fprintf(thread_data.data->error.to.stream, "%s%s%u%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, parameters, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s parameters.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } } } @@ -279,7 +279,7 @@ extern "C" { status = f_string_dynamics_increase_by(allocate, &action->parameters); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_string_dynamics_increase_by", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamics_increase_by", F_true); action->status = status; @@ -297,7 +297,7 @@ extern "C" { status = f_string_dynamic_partial_append_nulless(cache->buffer_file, cache->content_actions.array[i].array[j], &action->parameters.array[j]); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true); action->status = status; @@ -319,7 +319,7 @@ extern "C" { status = fll_path_canonical(action->parameters.array[0].string, &cache->buffer_path); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fll_path_canonical", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "fll_path_canonical", F_true); action->status = status; @@ -340,9 +340,9 @@ extern "C" { status_action = action->status; } - if (data.error.verbosity != f_console_verbosity_quiet) { - fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data.error.to.stream, "%s%sThe entry item action must not have an empty string for a path (the first parameter).%s%c", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe entry item action must not have an empty string for a path (the first parameter).%s%c", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s, thread_data.data->error.context.after->string, f_string_eol_s[0]); } } @@ -352,7 +352,7 @@ extern "C" { status = f_file_name_base(action->parameters.array[1].string, action->parameters.array[1].used, &cache->buffer_path); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_file_name_base", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_file_name_base", F_true); if (F_status_set_fine(status) == F_memory_not) { status_action = status; @@ -368,11 +368,11 @@ extern "C" { else { if (fl_string_dynamic_compare(action->parameters.array[1], cache->buffer_path) == F_equal_to_not) { - if (data.error.verbosity != f_console_verbosity_quiet) { + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { status = f_string_dynamic_terminate_after(&cache->buffer_path); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true); action->status = status; @@ -383,12 +383,12 @@ extern "C" { break; } - fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data.error.to.stream, "%s%sThe entry item action second parameter '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, action->parameters.array[1].string, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s' must be a base path name, such as '", data.error.context.before->string); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, cache->buffer_path.string, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s'.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe entry item action second parameter '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, action->parameters.array[1].string, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s' must be a base path name, such as '", thread_data.data->error.context.before->string); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, cache->buffer_path.string, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s'.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } action->status = F_status_set_error(F_parameter); @@ -406,9 +406,9 @@ extern "C" { status_action = action->status; } - if (data.error.verbosity != f_console_verbosity_quiet) { - fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data.error.to.stream, "%s%sThe entry item action must not have an empty string for a rule name (the second parameter).%s%c", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe entry item action must not have an empty string for a rule name (the second parameter).%s%c", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s, thread_data.data->error.context.after->string, f_string_eol_s[0]); } } @@ -432,17 +432,17 @@ extern "C" { } } - if (data.error.verbosity != f_console_verbosity_quiet) { - fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data.error.to.stream, "%s%sThe entry item action third parameter (and beyond) must be one of '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_asynchronous_s, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s', '", data.error.context.before->string); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_require_s, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s', or '", data.error.context.before->string); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_wait_s, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s' but instead has '", data.error.context.before->string); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, action->parameters.array[j].string, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s'.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe entry item action third parameter (and beyond) must be one of '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, controller_string_asynchronous_s, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s', '", thread_data.data->error.context.before->string); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, controller_string_require_s, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s', or '", thread_data.data->error.context.before->string); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, controller_string_wait_s, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s' but instead has '", thread_data.data->error.context.before->string); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, action->parameters.array[j].string, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s'.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } } } // for @@ -455,11 +455,11 @@ extern "C" { status_action = action->status; } - if (data.error.verbosity != f_console_verbosity_quiet) { - fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data.error.to.stream, "%s%sThe entry item action may not specify the reserved item '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_main_s, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s'.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe entry item action may not specify the reserved item '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, controller_string_main_s, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s'.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } } } @@ -481,17 +481,17 @@ extern "C" { status_action = action->status; } - if (data.error.verbosity != f_console_verbosity_quiet) { - fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data.error.to.stream, "%s%sThe entry item action must have one of '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_kill_s, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s', '", data.error.context.before->string); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_start_s, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s', or '", data.error.context.before->string); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_stop_s, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s' but instead has '", data.error.context.before->string); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, action->parameters.array[0].string, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s'.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe entry item action must have one of '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, controller_string_kill_s, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s', '", thread_data.data->error.context.before->string); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, controller_string_start_s, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s', or '", thread_data.data->error.context.before->string); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, controller_string_stop_s, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s' but instead has '", thread_data.data->error.context.before->string); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, action->parameters.array[0].string, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s'.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } } @@ -511,17 +511,17 @@ extern "C" { } if (F_status_set_fine(status) == F_memory_not) { - fll_error_print(data.error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true); status_action = status; break; } - if (data.error.verbosity != f_console_verbosity_quiet) { - fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data.error.to.stream, "%s%sThe entry item action parameter '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, action->parameters.array[1].string, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s' is not a valid supported number.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe entry item action parameter '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, action->parameters.array[1].string, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s' is not a valid supported number.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } } } @@ -594,11 +594,14 @@ extern "C" { #endif // _di_controller_entry_items_increase_by_ #ifndef _di_controller_entry_read_ - f_status_t controller_entry_read(const controller_data_t data, const controller_setting_t setting, const f_string_static_t entry_name, controller_cache_t *cache, controller_entry_t *entry) { + f_status_t controller_entry_read(const f_string_static_t entry_name, controller_thread_data_t thread_data, controller_cache_t *cache) { f_status_t status = F_none; - entry->status = F_known_not; - entry->items.used = 0; + // @fixme all printfs in this function and child functions now need to be using the print mutex. + // @fixme this should lock the global rule mutex until all rules for the entry have been processed. + + thread_data.setting->entry.status = F_known_not; + thread_data.setting->entry.items.used = 0; cache->action.line_action = 0; cache->action.line_item = 0; @@ -635,7 +638,7 @@ extern "C" { cache->action.name_action.used = 0; cache->action.name_item.used = 0; - status = controller_file_load(data, setting, controller_string_entries_s, entry_name, controller_string_entry_s, controller_string_entries_length, controller_string_entry_length, cache); + status = controller_file_load(controller_string_entries_s, entry_name, controller_string_entry_s, controller_string_entries_length, controller_string_entry_length, thread_data, cache); if (F_status_is_error_not(status)) { if (cache->buffer_file.used) { @@ -644,20 +647,20 @@ extern "C" { status = fll_fss_basic_list_read(cache->buffer_file, &range, &cache->object_items, &cache->content_items, &cache->delimits, 0, &cache->comments); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true); } else { status = fl_fss_apply_delimit(cache->delimits, &cache->buffer_file); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true); } } } else { - if (data.error.verbosity != f_console_verbosity_quiet) { - fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data.error.to.stream, "%s%sThe entry file is empty.%s%c", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s, data.error.context.after->string, f_string_eol_s[0]); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe entry file is empty.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s, thread_data.data->error.context.after->string, f_string_eol_s[0]); } status = F_status_set_error(F_data_not); @@ -665,10 +668,10 @@ extern "C" { } if (F_status_is_error_not(status) && cache->object_items.used) { - status = controller_entry_items_increase_by(cache->object_items.used, &entry->items); + status = controller_entry_items_increase_by(cache->object_items.used, &thread_data.setting->entry.items); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "controller_entry_items_increase_by", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_entry_items_increase_by", F_true); } else { @@ -683,7 +686,7 @@ extern "C" { for (; i < cache->object_items.used; ++i) { - if (setting.signal) { + if (thread_data.setting->signal) { return F_signal; } @@ -710,39 +713,39 @@ extern "C" { cache->action.name_action.used = 0; cache->action.name_item.used = 0; - status = controller_entry_items_increase_by(controller_default_allocation_step, &entry->items); + status = controller_entry_items_increase_by(controller_default_allocation_step, &thread_data.setting->entry.items); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "controller_entry_items_increase_by", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_entry_items_increase_by", F_true); break; } status = controller_string_dynamic_partial_append_terminated(cache->buffer_file, cache->object_items.array[i], &cache->action.name_item); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "controller_string_dynamic_partial_append_terminated", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_partial_append_terminated", F_true); break; } status = f_fss_count_lines(cache->buffer_file, cache->object_items.array[i].start, &cache->action.line_item); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_fss_count_lines", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_fss_count_lines", F_true); break; } cache->action.line_item++; - for (j = (code & 0x1) ? 1 : 0; j < entry->items.used; ++j) { + for (j = (code & 0x1) ? 1 : 0; j < thread_data.setting->entry.items.used; ++j) { - if (fl_string_dynamic_compare(entry->items.array[j].name, cache->action.name_item) == F_equal_to) { - if (data.warning.verbosity == f_console_verbosity_debug) { - fprintf(data.warning.to.stream, "%c", f_string_eol_s[0]); - fprintf(data.warning.to.stream, "%s%sIgnoring duplicate entry item '", data.warning.context.before->string, data.warning.prefix ? data.warning.prefix : f_string_empty_s); - fprintf(data.warning.to.stream, "%s%s%s%s", data.warning.context.after->string, data.warning.notable.before->string, cache->action.name_file.string, data.warning.notable.after->string); - fprintf(data.warning.to.stream, "%s'.%s%c", data.warning.context.before->string, data.warning.context.after->string, f_string_eol_s[0]); + if (fl_string_dynamic_compare(thread_data.setting->entry.items.array[j].name, cache->action.name_item) == F_equal_to) { + if (thread_data.data->warning.verbosity == f_console_verbosity_debug) { + fprintf(thread_data.data->warning.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->warning.to.stream, "%s%sIgnoring duplicate entry item '", thread_data.data->warning.context.before->string, thread_data.data->warning.prefix ? thread_data.data->warning.prefix : f_string_empty_s); + fprintf(thread_data.data->warning.to.stream, "%s%s%s%s", thread_data.data->warning.context.after->string, thread_data.data->warning.notable.before->string, cache->action.name_file.string, thread_data.data->warning.notable.after->string); + fprintf(thread_data.data->warning.to.stream, "%s'.%s%c", thread_data.data->warning.context.before->string, thread_data.data->warning.context.after->string, f_string_eol_s[0]); - controller_entry_error_print(data.warning, cache->action); + controller_entry_error_print(thread_data.data->warning, cache->action); } code |= 0x2; @@ -759,35 +762,35 @@ extern "C" { at = 0; - if (!entry->items.used) { - entry->items.used = 1; + if (!thread_data.setting->entry.items.used) { + thread_data.setting->entry.items.used = 1; } } - else if (entry->items.used) { - at = entry->items.used++; + else if (thread_data.setting->entry.items.used) { + at = thread_data.setting->entry.items.used++; } else { // skip position 0, which is reserved for "main". - entry->items.array[0].name.used = 0; + thread_data.setting->entry.items.array[0].name.used = 0; at = 1; - entry->items.used = 2; + thread_data.setting->entry.items.used = 2; } - entry->items.array[at].line = cache->action.line_item; + thread_data.setting->entry.items.array[at].line = cache->action.line_item; - status = controller_string_dynamic_append_terminated(cache->action.name_item, &entry->items.array[at].name); + status = controller_string_dynamic_append_terminated(cache->action.name_item, &thread_data.setting->entry.items.array[at].name); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); break; } - status = controller_entry_actions_read(data, setting, *range, cache, &entry->items.array[at].actions); + status = controller_entry_actions_read(*range, thread_data, cache, &thread_data.setting->entry.items.array[at].actions); if (F_status_is_error(status)) { - controller_entry_error_print(data.error, cache->action); + controller_entry_error_print(thread_data.data->error, cache->action); if (F_status_set_fine(status) == F_memory_not) { break; @@ -800,11 +803,11 @@ extern "C" { cache->action.name_item.used = 0; if (!(code & 0x1)) { - if (data.error.verbosity != f_console_verbosity_quiet) { - fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data.error.to.stream, "%s%sThe required entry item '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, controller_string_main_s, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s' was not found.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe required entry item '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, controller_string_main_s, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s' was not found.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); } status = F_status_set_error(F_found_not); @@ -818,15 +821,15 @@ extern "C" { // 0x1 = missing or not, 0x2 = one or more missing. uint8_t missing = 0; - for (i = 0; i < entry->items.used; ++i) { + for (i = 0; i < thread_data.setting->entry.items.used; ++i) { - for (j = 0; j < entry->items.array[i].actions.used; ++j) { + for (j = 0; j < thread_data.setting->entry.items.array[i].actions.used; ++j) { - if (setting.signal) { + if (thread_data.setting->signal) { return F_signal; } - action = &entry->items.array[i].actions.array[j]; + action = &thread_data.setting->entry.items.array[i].actions.array[j]; // only process actions that don't already have an error. if (F_status_is_error(action->status)) continue; @@ -834,9 +837,9 @@ extern "C" { if (action->type == controller_entry_action_type_failsafe || action->type == controller_entry_action_type_item) { missing |= 0x1; - for (k = 0; k < entry->items.used; ++k) { + for (k = 0; k < thread_data.setting->entry.items.used; ++k) { - if (fl_string_dynamic_compare(action->parameters.array[0], entry->items.array[k].name) == F_equal_to) { + if (fl_string_dynamic_compare(action->parameters.array[0], thread_data.setting->entry.items.array[k].name) == F_equal_to) { if (missing & 0x1) { missing -= 0x1; } @@ -849,29 +852,29 @@ extern "C" { missing |= 0x2; cache->action.line_action = action->line; - cache->action.line_item = entry->items.array[i].line; + cache->action.line_item = thread_data.setting->entry.items.array[i].line; - status = controller_string_dynamic_append_terminated(entry->items.array[i].name, &cache->action.name_item); + status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[i].name, &cache->action.name_item); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true); break; } - if (data.error.verbosity != f_console_verbosity_quiet) { - fprintf(data.error.to.stream, "%c", f_string_eol_s[0]); - fprintf(data.error.to.stream, "%s%sThe required entry item '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s); - fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, action->parameters.array[0].string, data.error.notable.after->string); - fprintf(data.error.to.stream, "%s' does not exist.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe required entry item '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, action->parameters.array[0].string, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s' does not exist.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); - controller_entry_error_print(data.error, cache->action); + controller_entry_error_print(thread_data.data->error, cache->action); } action->number = 0; action->status = controller_status_simplify(F_found_not); - // @fixme review how entry->status is being handled with respect to action->status (here the action failed, should the entire entry fail? at the moment if mode is simulation this prevents simulation from continuing). - //entry->status = controller_status_simplify(F_found_not); + // @fixme review how thread_data.setting->entry.status is being handled with respect to action->status (here the action failed, should the entire entry fail? at the moment if mode is simulation this prevents simulation from continuing). + //thread_data.setting->entry.status = controller_status_simplify(F_found_not); cache->action.name_action.used = 0; cache->action.name_item.used = 0; @@ -885,8 +888,8 @@ extern "C" { // the error is already fully printed and the entry status is already assigned, so immediately exit. if (missing & 0x2) { - // @fixme review how entry->status is being handled with respect to action->status (here the action failed, should the entire entry fail? at the moment if mode is simulation this prevents simulation from continuing). - //return entry->status; + // @fixme review how thread_data.setting->entry.status is being handled with respect to action->status (here the action failed, should the entire entry fail? at the moment if mode is simulation this prevents simulation from continuing). + //return thread_data.setting->entry.status; } } } @@ -894,15 +897,15 @@ extern "C" { } if (F_status_is_error(status)) { - controller_entry_error_print(data.error, cache->action); + controller_entry_error_print(thread_data.data->error, cache->action); - entry->status = controller_status_simplify(F_status_set_fine(status)); + thread_data.setting->entry.status = controller_status_simplify(F_status_set_fine(status)); } else { - entry->status = F_none; + thread_data.setting->entry.status = F_none; } - return entry->status; + return thread_data.setting->entry.status; } #endif // _di_controller_entry_read_ diff --git a/level_3/controller/c/private-entry.h b/level_3/controller/c/private-entry.h index 40d0988..349aa76 100644 --- a/level_3/controller/c/private-entry.h +++ b/level_3/controller/c/private-entry.h @@ -63,12 +63,10 @@ extern "C" { /** * Read the entry list, extracting all items and values. * - * @param data - * The program data. - * @param setting - * The controller settings data. * @param content_range * The range in the list buffer representing the content. + * @param thread_data + * The thread data. * @param cache * A structure for containing and caching relevant data. * @param actions @@ -96,7 +94,7 @@ extern "C" { * @see fll_fss_extended_read() */ #ifndef _di_controller_entry_actions_read_ - extern f_status_t controller_entry_actions_read(const controller_data_t data, const controller_setting_t setting, const f_string_range_t content_range, controller_cache_t *cache, controller_entry_actions_t *actions) f_gcc_attribute_visibility_internal; + extern f_status_t controller_entry_actions_read(const f_string_range_t content_range, controller_thread_data_t thread_data, controller_cache_t *cache, controller_entry_actions_t *actions) f_gcc_attribute_visibility_internal; #endif // _di_controller_entry_actions_read_ /** @@ -141,18 +139,15 @@ extern "C" { /** * Read the entry, extracting all lists. * - * @param data - * The program data. - * @param setting - * The controller settings data. * @param entry_name * The string identifying the entry. * This is constructed from the path parts to the file without the file extension and without the settings directory prefix. * "/etc/controller/entries/example/my.entry" would have a rule id of "example/my". + * @param thread_data + * The thread data. * @param cache - * A structure for containing and caching relevant data. - * @param entry - * The processed entry. + * The cache for the specific thread. + * This should be the cache thread_data.thread->asynchronouss.array[thread_data.id].cache. * * @return * F_none on success. @@ -184,7 +179,7 @@ extern "C" { * @see fll_fss_basic_list_read() */ #ifndef _di_controller_entry_read_ - extern f_status_t controller_entry_read(const controller_data_t data, const controller_setting_t setting, const f_string_static_t entry_name, controller_cache_t *cache, controller_entry_t *entry) f_gcc_attribute_visibility_internal; + extern f_status_t controller_entry_read(const f_string_static_t entry_name, controller_thread_data_t thread_data, controller_cache_t *cache) f_gcc_attribute_visibility_internal; #endif // _di_controller_entry_read_ #ifdef __cplusplus diff --git a/level_3/controller/c/private-rule.c b/level_3/controller/c/private-rule.c index aaed5ec..a351cab 100644 --- a/level_3/controller/c/private-rule.c +++ b/level_3/controller/c/private-rule.c @@ -398,6 +398,21 @@ extern "C" { } #endif // _di_controller_rule_action_read_ +#ifndef _di_controller_rule_copy_ + f_status_t controller_rule_copy(controller_rule_t *source, controller_rule_t *destination) { + f_status_t status = F_none; + + f_thread_condition_wait(&source->wait, &destination->lock); + + // @todo + + f_thread_condition_signal(&source->wait); + f_thread_mutex_unlock(&destination->lock); + + return status; + } +#endif // _di_controller_rule_copy_ + #ifndef _di_controller_rule_error_print_ void controller_rule_error_print(const fll_error_print_t output, const controller_cache_action_t cache, const bool item) { @@ -437,11 +452,11 @@ extern "C" { void controller_rule_error_print_locked(const fll_error_print_t output, const controller_cache_action_t cache, const bool item, controller_thread_t *thread) { if (output.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&thread->mutex->print); + f_thread_mutex_lock(&thread->mutex.print); controller_rule_error_print(output, cache, item); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread->mutex.print); } } #endif // _di_controller_rule_error_print_ @@ -510,7 +525,7 @@ extern "C" { #endif // _di_controller_rule_error_print_need_want_wish_ #ifndef _di_controller_rule_execute_ - f_status_t controller_rule_execute(const f_array_length_t index, const uint8_t type, const uint8_t options, controller_thread_t *thread, controller_asynchronous_t *asynchronous) { + f_status_t controller_rule_execute(const uint8_t type, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache, controller_rule_t *rule) { f_status_t status = F_none; f_status_t success = F_false; @@ -535,94 +550,95 @@ extern "C" { uid_t local_id_user; gid_t local_id_group; + // @todo now that "rule' is a (local) copy, this workaround might no longer be necessary. f_int32s_t local_affinity; f_control_group_t local_control_group; f_int32s_t local_id_groups; f_limit_sets_t local_limits; f_execute_scheduler_t local_scheduler; - if (thread->setting->rules.array[index].affinity.used) { - local_affinity = thread->setting->rules.array[index].affinity; + if (rule->affinity.used) { + local_affinity = rule->affinity; execute_set.as.affinity = &local_affinity; } - if (thread->setting->rules.array[index].capability) { - execute_set.as.capability = thread->setting->rules.array[index].capability; + if (rule->capability) { + execute_set.as.capability = rule->capability; } - if (thread->setting->rules.array[index].has & controller_rule_has_control_group) { - local_control_group = thread->setting->rules.array[index].control_group; + if (rule->has & controller_rule_has_control_group) { + local_control_group = rule->control_group; execute_set.as.control_group = &local_control_group; // make sure all required cgroup directories exist. - if (thread->setting->rules.array[index].status == F_known_not) { - status = fll_control_group_prepare(thread->setting->rules.array[index].control_group); + if (rule->status == F_known_not) { + status = fll_control_group_prepare(rule->control_group); if (F_status_is_error(status)) { - controller_error_print_locked(thread->data->error, F_status_set_fine(status), "fll_control_group_prepare", F_true, thread); + controller_error_print_locked(thread_data.data->error, F_status_set_fine(status), "fll_control_group_prepare", F_true, thread_data.thread); - thread->setting->rules.array[index].status = F_status_set_error(F_failure); + rule->status = F_status_set_error(F_failure); return status; } } } - if (thread->setting->rules.array[index].has & controller_rule_has_group) { - local_id_group = thread->setting->rules.array[index].group; + if (rule->has & controller_rule_has_group) { + local_id_group = rule->group; execute_set.as.id_group = &local_id_group; - if (thread->setting->rules.array[index].groups.used) { - local_id_groups = thread->setting->rules.array[index].groups; + if (rule->groups.used) { + local_id_groups = rule->groups; execute_set.as.id_groups = &local_id_groups; } } - if (thread->setting->rules.array[index].limits.used) { - local_limits = thread->setting->rules.array[index].limits; + if (rule->limits.used) { + local_limits = rule->limits; execute_set.as.limits = &local_limits; } - if (thread->setting->rules.array[index].has & controller_rule_has_scheduler) { - local_scheduler = thread->setting->rules.array[index].scheduler; + if (rule->has & controller_rule_has_scheduler) { + local_scheduler = rule->scheduler; execute_set.as.scheduler = &local_scheduler; } - if (thread->setting->rules.array[index].has & controller_rule_has_nice) { - local_nice = thread->setting->rules.array[index].nice; + if (rule->has & controller_rule_has_nice) { + local_nice = rule->nice; execute_set.as.nice = &local_nice; } - if (thread->setting->rules.array[index].has & controller_rule_has_user) { - local_id_user = thread->setting->rules.array[index].user; + if (rule->has & controller_rule_has_user) { + local_id_user = rule->user; execute_set.as.id_user = &local_id_user; } - status = fl_environment_load_names(thread->setting->rules.array[index].environment, &environment); + status = fl_environment_load_names(rule->environment, &environment); if (F_status_is_error(status)) { - controller_error_print_locked(thread->data->error, F_status_set_fine(status), "fl_environment_load_names", F_true, thread); + controller_error_print_locked(thread_data.data->error, F_status_set_fine(status), "fl_environment_load_names", F_true, thread_data.thread); - thread->setting->rules.array[index].status = F_status_set_error(F_failure); + rule->status = F_status_set_error(F_failure); return status; } - for (i = 0; i < thread->setting->rules.array[index].items.used; ++i) { + for (i = 0; i < rule->items.used; ++i) { - if (thread->setting->signal) { + if (thread_data.setting->signal) { status = F_signal; break; } - if (thread->setting->rules.array[index].items.array[i].type == controller_rule_item_type_setting) continue; + if (rule->items.array[i].type == controller_rule_item_type_setting) continue; - for (j = 0; j < thread->setting->rules.array[index].items.array[i].actions.used; ++j) { + for (j = 0; j < rule->items.array[i].actions.used; ++j) { - if (thread->setting->signal) { + if (thread_data.setting->signal) { status = F_signal; break; } - if (thread->setting->rules.array[index].items.array[i].actions.array[j].type != type) continue; + if (rule->items.array[i].actions.array[j].type != type) continue; execute_set.parameter.data = 0; execute_set.parameter.option = fl_execute_parameter_option_threadsafe; @@ -631,55 +647,55 @@ extern "C" { execute_set.parameter.option |= fl_execute_parameter_option_return; } - if (thread->setting->rules.array[index].items.array[i].type == controller_rule_item_type_command) { + if (rule->items.array[i].type == controller_rule_item_type_command) { - if (strchr(thread->setting->rules.array[index].items.array[i].actions.array[j].parameters.array[0].string, f_path_separator_s[0])) { + if (strchr(rule->items.array[i].actions.array[j].parameters.array[0].string, f_path_separator_s[0])) { execute_set.parameter.option |= fl_execute_parameter_option_path; } - status = controller_rule_execute_foreground(index, thread->setting->rules.array[index].items.array[i].type, thread->setting->rules.array[index].items.array[i].actions.array[j], 0, thread->setting->rules.array[index].items.array[i].actions.array[j].parameters, options, &execute_set, thread, asynchronous); + status = controller_rule_execute_foreground(rule->items.array[i].type, rule->items.array[i].actions.array[j], 0, rule->items.array[i].actions.array[j].parameters, options, &execute_set, thread_data, rule); if (status == F_child) break; if (F_status_is_error(status)) { - thread->setting->rules.array[index].items.array[i].actions.array[j].status = F_status_set_error(F_failure); + rule->items.array[i].actions.array[j].status = F_status_set_error(F_failure); if (!(options & controller_rule_option_simulate)) break; } success = F_true; } - else if (thread->setting->rules.array[index].items.array[i].type == controller_rule_item_type_script) { - execute_set.parameter.data = &thread->setting->rules.array[index].items.array[i].actions.array[j].parameters.array[0]; + else if (rule->items.array[i].type == controller_rule_item_type_script) { + execute_set.parameter.data = &rule->items.array[i].actions.array[j].parameters.array[0]; - if (thread->setting->rules.array[index].script.used && strchr(thread->setting->rules.array[index].script.string, f_path_separator_s[0])) { + if (rule->script.used && strchr(rule->script.string, f_path_separator_s[0])) { execute_set.parameter.option |= fl_execute_parameter_option_path; } - status = controller_rule_execute_foreground(index, thread->setting->rules.array[index].items.array[i].type, thread->setting->rules.array[index].items.array[i].actions.array[j], thread->setting->rules.array[index].script.used ? thread->setting->rules.array[index].script.string : controller_default_program_script, arguments_none, options, &execute_set, thread, asynchronous); + status = controller_rule_execute_foreground(rule->items.array[i].type, rule->items.array[i].actions.array[j], rule->script.used ? rule->script.string : controller_default_program_script, arguments_none, options, &execute_set, thread_data, rule); if (status == F_child) break; if (F_status_is_error(status)) { - thread->setting->rules.array[index].items.array[i].actions.array[j].status = F_status_set_error(F_failure); + rule->items.array[i].actions.array[j].status = F_status_set_error(F_failure); if (!(options & controller_rule_option_simulate)) break; } success = F_true; } - else if (thread->setting->rules.array[index].items.array[i].type == controller_rule_item_type_service) { + else if (rule->items.array[i].type == controller_rule_item_type_service) { - if (strchr(thread->setting->rules.array[index].items.array[i].actions.array[j].parameters.array[0].string, f_path_separator_s[0])) { + if (strchr(rule->items.array[i].actions.array[j].parameters.array[0].string, f_path_separator_s[0])) { execute_set.parameter.option |= fl_execute_parameter_option_path; } - status = controller_rule_execute_pid_with(index, thread->setting->rules.array[index].items.array[i].type, thread->setting->rules.array[index].items.array[i].actions.array[j], 0, thread->setting->rules.array[index].items.array[i].actions.array[j].parameters, options, &execute_set, thread, asynchronous); + status = controller_rule_execute_pid_with(rule->items.array[i].type, rule->items.array[i].actions.array[j], 0, rule->items.array[i].actions.array[j].parameters, options, &execute_set, thread_data, rule); if (status == F_child) break; if (F_status_is_error(status)) { - thread->setting->rules.array[index].items.array[i].actions.array[j].status = F_status_set_error(F_failure); + rule->items.array[i].actions.array[j].status = F_status_set_error(F_failure); if (!(options & controller_rule_option_simulate)) break; } @@ -688,18 +704,18 @@ extern "C" { } else { - if (thread->data->warning.verbosity == f_console_verbosity_debug) { - f_thread_mutex_lock(&thread->mutex->print); + if (thread_data.data->warning.verbosity == f_console_verbosity_debug) { + f_thread_mutex_lock(&thread_data.thread->mutex.print); - fprintf(thread->data->warning.to.stream, "%c", f_string_eol_s[0]); - fprintf(thread->data->warning.to.stream, "%s%sAction type is unknown, ignoring.%s%c", thread->data->warning.context.before->string, thread->data->warning.prefix ? thread->data->warning.prefix : f_string_empty_s, thread->data->warning.context.after->string, f_string_eol_s[0]); + fprintf(thread_data.data->warning.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->warning.to.stream, "%s%sAction type is unknown, ignoring.%s%c", thread_data.data->warning.context.before->string, thread_data.data->warning.prefix ? thread_data.data->warning.prefix : f_string_empty_s, thread_data.data->warning.context.after->string, f_string_eol_s[0]); - controller_rule_error_print(thread->data->warning, *thread->cache_action, F_true); + controller_rule_error_print(thread_data.data->warning, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); } - thread->setting->rules.array[index].items.array[i].actions.array[j].status = F_ignore; + rule->items.array[i].actions.array[j].status = F_ignore; if (success != F_true) { success = F_ignore; @@ -721,21 +737,21 @@ extern "C" { } if (F_status_is_error(status) || success == F_false) { - thread->setting->rules.array[index].status = F_status_set_error(F_failure); + rule->status = F_status_set_error(F_failure); } else if (success == F_ignore || success == F_busy) { - thread->setting->rules.array[index].status = success; + rule->status = success; } else { - thread->setting->rules.array[index].status = F_none; + rule->status = F_none; } - return thread->setting->rules.array[index].status; + return rule->status; } #endif // _di_controller_rule_execute_ #ifndef _di_controller_rule_execute_foreground_ - f_status_t controller_rule_execute_foreground(const f_array_length_t index, const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, controller_execute_set_t * const execute_set, controller_thread_t *thread, controller_asynchronous_t *asynchronous) { + f_status_t controller_rule_execute_foreground(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, controller_execute_set_t * const execute_set, controller_thread_data_t thread_data, controller_rule_t *rule) { f_status_t status = F_none; int result = 0; @@ -743,23 +759,23 @@ extern "C" { if (options & controller_rule_option_simulate) { - if (thread->data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&thread->mutex->print); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&thread_data.thread->mutex.print); - fprintf(thread->data->output.stream, "%c", f_string_eol_s[0]); - fprintf(thread->data->output.stream, "Simulating execution of '"); - fprintf(thread->data->output.stream, "%s%s%s", thread->data->context.title.string, program ? program : arguments.used && arguments.array[0].used ? arguments.array[0].string : f_string_empty_s, thread->data->context.reset.string); - fprintf(thread->data->output.stream, "' with the arguments: '%s", thread->data->context.important.string); + fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "Simulating execution of '"); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.title.string, program ? program : arguments.used && arguments.array[0].used ? arguments.array[0].string : f_string_empty_s, thread_data.data->context.reset.string); + fprintf(thread_data.data->output.stream, "' with the arguments: '%s", thread_data.data->context.important.string); for (f_array_length_t i = program ? 0 : 1; i < arguments.used; ++i) { - fprintf(thread->data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string); + fprintf(thread_data.data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string); } // for - fprintf(thread->data->output.stream, "%s' from '", thread->data->context.reset.string); - fprintf(thread->data->output.stream, "%s%s%s", thread->data->context.notable.string, thread->setting->rules.array[index].name.used ? thread->setting->rules.array[index].name.string : f_string_empty_s, thread->data->context.reset.string); - fprintf(thread->data->output.stream, "%s'.%c", thread->data->context.reset.string, f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "%s' from '", thread_data.data->context.reset.string); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.notable.string, rule->name.used ? rule->name.string : f_string_empty_s, thread_data.data->context.reset.string); + fprintf(thread_data.data->output.stream, "%s'.%c", thread_data.data->context.reset.string, f_string_eol_s[0]); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); } // sleep for less than a second to better show simulation of synchronous vs asynchronous. @@ -779,13 +795,13 @@ extern "C" { result = 0; // assign the child process id to the asynchronous thread to allow for the cancel process to send appropriate termination signals to the child process. - asynchronous->child = id_process; + thread_data.thread->asynchronouss.array[thread_data.id].child = id_process; // have the parent wait for the child process to finish. waitpid(id_process, &result, WUNTRACED | WCONTINUED); // remove the pid now that waidpid() has returned. - asynchronous->child = 0; + thread_data.thread->asynchronouss.array[thread_data.id].child = 0; // this must explicitly check for 0 (as opposed to checking (!result)). if (!WIFEXITED(result)) { @@ -815,19 +831,19 @@ extern "C" { if (F_status_is_error(status)) { status = F_status_set_fine(status); - f_thread_mutex_lock(&thread->mutex->print); + f_thread_mutex_lock(&thread_data.thread->mutex.print); if (status == F_control_group || status == F_failure || status == F_limit || status == F_processor || status == F_schedule) { - controller_rule_error_print_execute(thread->data->error, type == controller_rule_item_type_script, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, result, status); + controller_rule_error_print_execute(thread_data.data->error, type == controller_rule_item_type_script, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, result, status); } else if (status == F_file_found_not) { - controller_rule_error_print_execute_not_found(thread->data->error, F_false, program); + controller_rule_error_print_execute_not_found(thread_data.data->error, F_false, program); } else { - fll_error_print(thread->data->error, status, "fll_execute_program", F_true); + fll_error_print(thread_data.data->error, status, "fll_execute_program", F_true); } - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); status = F_status_set_error(status); } @@ -837,7 +853,7 @@ extern "C" { #endif // _di_controller_rule_execute_foreground_ #ifndef _di_controller_rule_execute_pid_with_ - f_status_t controller_rule_execute_pid_with(const f_array_length_t index, const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, controller_execute_set_t * const execute_set, controller_thread_t *thread, controller_asynchronous_t *asynchronous) { + f_status_t controller_rule_execute_pid_with(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, controller_execute_set_t * const execute_set, controller_thread_data_t thread_data, controller_rule_t *rule) { f_status_t status = F_none; int result = 0; @@ -852,23 +868,23 @@ extern "C" { if (options & controller_rule_option_simulate) { - if (thread->data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&thread->mutex->print); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&thread_data.thread->mutex.print); - fprintf(thread->data->output.stream, "%c", f_string_eol_s[0]); - fprintf(thread->data->output.stream, "Simulating execution of '"); - fprintf(thread->data->output.stream, "%s%s%s", thread->data->context.title.string, program ? program : arguments.used && arguments.array[0].used ? arguments.array[0].string : f_string_empty_s, thread->data->context.reset.string); - fprintf(thread->data->output.stream, "' with the arguments: '%s", thread->data->context.important.string); + fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "Simulating execution of '"); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.title.string, program ? program : arguments.used && arguments.array[0].used ? arguments.array[0].string : f_string_empty_s, thread_data.data->context.reset.string); + fprintf(thread_data.data->output.stream, "' with the arguments: '%s", thread_data.data->context.important.string); for (f_array_length_t i = program ? 0 : 1; i < arguments.used; ++i) { - fprintf(thread->data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string); + fprintf(thread_data.data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string); } // for - fprintf(thread->data->output.stream, "%s' from '", thread->data->context.reset.string); - fprintf(thread->data->output.stream, "%s%s%s", thread->data->context.notable.string, thread->setting->rules.array[index].name.used ? thread->setting->rules.array[index].name.string : f_string_empty_s, thread->data->context.reset.string); - fprintf(thread->data->output.stream, "%s'.%c", thread->data->context.reset.string, f_string_eol_s[0]); + fprintf(thread_data.data->output.stream, "%s' from '", thread_data.data->context.reset.string); + fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.notable.string, rule->name.used ? rule->name.string : f_string_empty_s, thread_data.data->context.reset.string); + fprintf(thread_data.data->output.stream, "%s'.%c", thread_data.data->context.reset.string, f_string_eol_s[0]); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); } // sleep for less than a second to better show simulation of synchronous vs asynchronous. @@ -888,13 +904,13 @@ extern "C" { result = 0; // assign the child process id to the asynchronous thread to allow for the cancel process to send appropriate termination signals to the child process. - asynchronous->child = id_process; + thread_data.thread->asynchronouss.array[thread_data.id].child = id_process; // have the parent wait for the child process to finish. waitpid(id_process, &result, WUNTRACED | WCONTINUED); // remove the pid now that waidpid() has returned. - asynchronous->child = 0; + thread_data.thread->asynchronouss.array[thread_data.id].child = 0; // this must explicitly check for 0 (as opposed to checking (!result)). if (!WIFEXITED(result)) { @@ -924,19 +940,19 @@ extern "C" { if (F_status_is_error(status)) { status = F_status_set_fine(status); - f_thread_mutex_lock(&thread->mutex->print); + f_thread_mutex_lock(&thread_data.thread->mutex.print); if (status == F_control_group || status == F_failure || status == F_limit || status == F_processor || status == F_schedule) { - controller_rule_error_print_execute(thread->data->error, type == controller_rule_item_type_script, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, result, status); + controller_rule_error_print_execute(thread_data.data->error, type == controller_rule_item_type_script, program ? program : arguments.used ? arguments.array[0].string : f_string_empty_s, result, status); } else if (status == F_file_found_not) { - controller_rule_error_print_execute_not_found(thread->data->error, F_false, program); + controller_rule_error_print_execute_not_found(thread_data.data->error, F_false, program); } else { - fll_error_print(thread->data->error, status, "fll_execute_program", F_true); + fll_error_print(thread_data.data->error, status, "fll_execute_program", F_true); } - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); return F_status_set_error(status); } @@ -948,15 +964,15 @@ extern "C" { #endif // _di_controller_rule_execute_pid_with_ #ifndef _di_controller_rule_find_loaded_ - f_array_length_t controller_rule_find_loaded(const controller_data_t data, const controller_setting_t setting, const f_string_static_t rule_id) { + f_array_length_t controller_rule_find_loaded(const f_string_static_t rule_id, controller_thread_data_t thread_data) { - f_array_length_t i = 0; + f_array_length_t i = thread_data.setting->rules.used; - for (; i < setting.rules.used; ++i) { - if (fl_string_dynamic_compare(rule_id, setting.rules.array[i].id) == F_equal_to) break; + for (; i; --i) { + if (fl_string_dynamic_compare(rule_id, thread_data.setting->rules.array[i].id) == F_equal_to) return i; } // for - return i; + return thread_data.setting->rules.used; } #endif // _di_controller_rule_find_loaded_ @@ -1002,7 +1018,7 @@ extern "C" { f_status_t status = F_none; f_string_range_t range = f_macro_string_range_t_initialize(cache->buffer_item.used); - f_string_length_t last = 0; + f_array_length_t last = 0; uint8_t type = 0; uint8_t method = 0; @@ -1365,7 +1381,7 @@ extern "C" { #endif // _di_controller_rule_path_ #ifndef _di_controller_rule_process_ - f_status_t controller_rule_process(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_thread_t *thread, controller_asynchronous_t *asynchronous) { + f_status_t controller_rule_process(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache) { switch (action) { case controller_rule_action_type_freeze: @@ -1381,64 +1397,64 @@ extern "C" { default: - if (thread->data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&thread->mutex->print); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&thread_data.thread->mutex.print); - fprintf(thread->data->error.to.stream, "%c", f_string_eol_s[0]); - fprintf(thread->data->error.to.stream, "%s%sUnsupported action type '", thread->data->error.context.before->string, thread->data->error.prefix ? thread->data->error.prefix : f_string_empty_s); - fprintf(thread->data->error.to.stream, "%s%s%s%s", thread->data->error.context.after->string, thread->data->error.notable.before->string, controller_rule_action_type_name(action), thread->data->error.notable.after->string); - fprintf(thread->data->error.to.stream, "%s' while attempting to execute rule.%s%c", thread->data->error.context.before->string, thread->data->error.context.after->string, f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sUnsupported action type '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, controller_rule_action_type_name(action), thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s' while attempting to execute rule.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); - controller_rule_error_print(thread->data->error, *thread->cache_action, F_true); + controller_rule_error_print(thread_data.data->error, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); } return F_status_set_error(F_parameter); } - if (index >= thread->setting->rules.used) { - f_thread_mutex_lock(&thread->mutex->print); + if (index >= thread_data.setting->rules.used) { + f_thread_mutex_lock(&thread_data.thread->mutex.print); - fll_error_print(thread->data->error, F_parameter, "controller_rule_process", F_true); - controller_rule_error_print(thread->data->error, *thread->cache_action, F_true); + fll_error_print(thread_data.data->error, F_parameter, "controller_rule_process", F_true); + controller_rule_error_print(thread_data.data->error, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); return F_status_set_error(F_parameter); } f_status_t status = F_none; - f_macro_array_lengths_t_increase_by(status, (*thread->stack), controller_default_allocation_step) + f_macro_array_lengths_t_increase_by(status, thread_data.thread->asynchronouss.array[thread_data.id].stack, controller_default_allocation_step) if (F_status_is_error(status)) { - f_thread_mutex_lock(&thread->mutex->print); + f_thread_mutex_lock(&thread_data.thread->mutex.print); - fll_error_print(thread->data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true); - controller_rule_error_print(thread->data->error, *thread->cache_action, F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true); + controller_rule_error_print(thread_data.data->error, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); return status; } f_array_length_t i = 0; - for (; i < thread->stack->used; ++i) { + for (; i < thread_data.thread->asynchronouss.array[thread_data.id].stack.used; ++i) { - if (thread->stack->array[i] == index) { - if (thread->data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&thread->mutex->print); + if (thread_data.thread->asynchronouss.array[thread_data.id].stack.array[i] == index) { + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&thread_data.thread->mutex.print); - fprintf(thread->data->error.to.stream, "%c", f_string_eol_s[0]); - fprintf(thread->data->error.to.stream, "%s%sThe rule '", thread->data->error.context.before->string, thread->data->error.prefix ? thread->data->error.prefix : f_string_empty_s); - fprintf(thread->data->error.to.stream, "%s%s%s%s", thread->data->error.context.after->string, thread->data->error.notable.before->string, thread->setting->rules.array[i].name.string, thread->data->error.notable.after->string); - fprintf(thread->data->error.to.stream, "%s' is already on the execution stack, this recursion is prohibited.%s%c", thread->data->error.context.before->string, thread->data->error.context.after->string, f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe rule '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, thread_data.setting->rules.array[i].name.string, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s' is already on the execution stack, this recursion is prohibited.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); - controller_rule_error_print(thread->data->error, *thread->cache_action, F_true); + controller_rule_error_print(thread_data.data->error, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); } // never continue on recursion errors even in simulate mode. @@ -1446,76 +1462,89 @@ extern "C" { } } - thread->cache_action->name_action.used = 0; - thread->cache_action->name_item.used = 0; - thread->cache_action->name_file.used = 0; + cache->action.name_action.used = 0; + cache->action.name_item.used = 0; + cache->action.name_file.used = 0; - status = f_string_append(controller_string_rules_s, controller_string_rules_length, &thread->cache_action->name_file); + status = f_string_append(controller_string_rules_s, controller_string_rules_length, &cache->action.name_file); if (F_status_is_error_not(status)) { - status = f_string_append(f_path_separator_s, f_path_separator_length, &thread->cache_action->name_file); + status = f_string_append(f_path_separator_s, f_path_separator_length, &cache->action.name_file); } if (F_status_is_error(status)) { - f_thread_mutex_lock(&thread->mutex->print); + f_thread_mutex_lock(&thread_data.thread->mutex.print); - fll_error_print(thread->data->error, F_status_set_fine(status), "f_string_append", F_true); - controller_rule_error_print(thread->data->error, *thread->cache_action, F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_append", F_true); + controller_rule_error_print(thread_data.data->error, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); return status; } - status = f_string_dynamic_append(thread->setting->rules.array[index].id, &thread->cache_action->name_file); + status = f_string_dynamic_append(thread_data.setting->rules.array[index].id, &cache->action.name_file); if (F_status_is_error(status)) { - f_thread_mutex_lock(&thread->mutex->print); + f_thread_mutex_lock(&thread_data.thread->mutex.print); - fll_error_print(thread->data->error, F_status_set_fine(status), "f_string_dynamic_append", F_true); - controller_rule_error_print(thread->data->error, *thread->cache_action, F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_append", F_true); + controller_rule_error_print(thread_data.data->error, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); return status; } - status = f_string_append(f_path_extension_separator, f_path_extension_separator_length, &thread->cache_action->name_file); + status = f_string_append(f_path_extension_separator, f_path_extension_separator_length, &cache->action.name_file); if (F_status_is_error_not(status)) { - status = f_string_append(controller_string_rule_s, controller_string_rule_length, &thread->cache_action->name_file); + status = f_string_append(controller_string_rule_s, controller_string_rule_length, &cache->action.name_file); } if (F_status_is_error(status)) { - f_thread_mutex_lock(&thread->mutex->print); + f_thread_mutex_lock(&thread_data.thread->mutex.print); - fll_error_print(thread->data->error, F_status_set_fine(status), "f_string_append", F_true); - controller_rule_error_print(thread->data->error, *thread->cache_action, F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_append", F_true); + controller_rule_error_print(thread_data.data->error, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); return status; } - status = f_string_dynamic_terminate_after(&thread->cache_action->name_file); + status = f_string_dynamic_terminate_after(&cache->action.name_file); if (F_status_is_error(status)) { - f_thread_mutex_lock(&thread->mutex->print); + f_thread_mutex_lock(&thread_data.thread->mutex.print); - fll_error_print(thread->data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true); - controller_rule_error_print(thread->data->error, *thread->cache_action, F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true); + controller_rule_error_print(thread_data.data->error, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); return status; } - thread->stack->array[thread->stack->used++] = index; + thread_data.thread->asynchronouss.array[thread_data.id].stack.array[thread_data.thread->asynchronouss.array[thread_data.id].stack.used++] = index; - controller_rule_t *rule = &thread->setting->rules.array[index]; + controller_rule_t *rule = &thread_data.setting->rules.array[index]; - if ((options & controller_rule_option_simulate) && thread->data->parameters[controller_parameter_validate].result == f_console_result_found) { - controller_rule_simulate(index, controller_rule_action_type_start, options, thread); + if ((options & controller_rule_option_simulate) && thread_data.data->parameters[controller_parameter_validate].result == f_console_result_found) { + // @fixme the cache should probably store a rule type and then that can used instead of calling controller_rule_copy() here. + controller_rule_t rule_simulate = controller_rule_t_initialize; + + status = controller_rule_copy(rule, &rule_simulate); + + if (F_status_is_error(status)) { + controller_rule_delete_simple(&rule_simulate); + + return status; + } + + controller_rule_simulate(controller_rule_action_type_start, options, thread_data, cache, &rule_simulate); + + controller_rule_delete_simple(&rule_simulate); } { @@ -1538,165 +1567,167 @@ extern "C" { for (i = 0; i < 3; ++i) { for (j = 0; j < dynamics[i]->used; ++j) { - at = controller_rule_find_loaded(*thread->data, *thread->setting, dynamics[i]->array[j]); + at = controller_rule_find_loaded(*thread_data.data, *thread_data.setting, dynamics[i]->array[j]); - if (at == thread->setting->rules.used) { + if (at == thread_data.setting->rules.used) { if (i == 0) { - f_thread_mutex_lock(&thread->mutex->print); + f_thread_mutex_lock(&thread_data.thread->mutex.print); - controller_rule_error_print_need_want_wish(thread->data->error, strings[i], dynamics[i]->array[j].string, "was not found"); + controller_rule_error_print_need_want_wish(thread_data.data->error, strings[i], dynamics[i]->array[j].string, "was not found"); status = F_status_set_error(F_found_not); - controller_rule_error_print(thread->data->error, *thread->cache_action, F_true); + controller_rule_error_print(thread_data.data->error, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); if (!(options & controller_rule_option_simulate)) break; } else { - if (thread->data->warning.verbosity == f_console_verbosity_debug) { - f_thread_mutex_lock(&thread->mutex->print); + if (thread_data.data->warning.verbosity == f_console_verbosity_debug) { + f_thread_mutex_lock(&thread_data.thread->mutex.print); - controller_rule_error_print_need_want_wish(thread->data->warning, strings[i], dynamics[i]->array[j].string, "was not found"); - controller_rule_error_print(thread->data->warning, *thread->cache_action, F_true); + controller_rule_error_print_need_want_wish(thread_data.data->warning, strings[i], dynamics[i]->array[j].string, "was not found"); + controller_rule_error_print(thread_data.data->warning, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); } } } - if (F_status_is_error_not(status) && at < thread->setting->rules.used) { + if (F_status_is_error_not(status) && at < thread_data.setting->rules.used) { - f_thread_mutex_lock(&thread->setting->rules.array[at].lock); + f_thread_mutex_lock(&thread_data.setting->rules.array[at].lock); - while (thread->asynchronouss.enabled && thread->setting->rules.array[at].status == F_known_not) { - f_thread_condition_wait(&thread->setting->rules.array[at].wait, &thread->setting->rules.array[at].lock); + while (thread_data.enabled && thread_data.setting->rules.array[at].status == F_known_not) { + f_thread_condition_wait(&thread_data.setting->rules.array[at].wait, &thread_data.setting->rules.array[at].lock); } // while - if (!thread->asynchronouss.enabled) { - f_thread_condition_signal(&thread->setting->rules.array[at].wait); - f_thread_mutex_unlock(&thread->setting->rules.array[at].lock); + if (!thread_data.enabled) { + f_thread_condition_signal(&thread_data.setting->rules.array[at].wait); + f_thread_mutex_unlock(&thread_data.setting->rules.array[at].lock); status = F_signal; break; } // when the status is unknown, then the rule has not been executed, so attempt to execute it. - if (thread->setting->rules.array[at].status == F_known_not) { + if (thread_data.setting->rules.array[at].status == F_known_not) { - f_macro_array_lengths_t_increase_by(status, (*thread->stack), controller_default_allocation_step) + f_macro_array_lengths_t_increase_by(status, thread_data.thread->asynchronouss.array[thread_data.id].stack, controller_default_allocation_step) if (F_status_is_error(status)) { - f_thread_mutex_lock(&thread->mutex->print); + f_thread_mutex_lock(&thread_data.thread->mutex.print); - fll_error_print(thread->data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true); - controller_rule_error_print(thread->data->error, *thread->cache_action, F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true); + controller_rule_error_print(thread_data.data->error, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); - f_thread_condition_signal(&thread->setting->rules.array[at].wait); - f_thread_mutex_unlock(&thread->setting->rules.array[at].lock); + f_thread_condition_signal(&thread_data.setting->rules.array[at].wait); + f_thread_mutex_unlock(&thread_data.setting->rules.array[at].lock); // always exit on memory errors, even in simulate mode. break; } // rule execution will re-use the existing cache, so save the current cache. - const f_array_length_t cache_line_action = thread->cache_action->line_action; - const f_array_length_t cache_line_item = thread->cache_action->line_item; + const f_array_length_t cache_line_action = cache->action.line_action; + const f_array_length_t cache_line_item = cache->action.line_item; - const f_string_length_t cache_name_action_used = thread->cache_action->name_action.used; - const f_string_length_t cache_name_item_used = thread->cache_action->name_item.used; - const f_string_length_t cache_name_file_used = thread->cache_action->name_file.used; + const f_array_length_t cache_name_action_used = cache->action.name_action.used; + const f_array_length_t cache_name_item_used = cache->action.name_item.used; + const f_array_length_t cache_name_file_used = cache->action.name_file.used; char cache_name_action[cache_name_action_used]; char cache_name_item[cache_name_item_used]; char cache_name_file[cache_name_file_used]; - memcpy(cache_name_action, thread->cache_action->name_action.string, thread->cache_action->name_action.used); - memcpy(cache_name_item, thread->cache_action->name_item.string, thread->cache_action->name_item.used); - memcpy(cache_name_file, thread->cache_action->name_file.string, thread->cache_action->name_file.used); + memcpy(cache_name_action, cache->action.name_action.string, cache->action.name_action.used); + memcpy(cache_name_item, cache->action.name_item.string, cache->action.name_item.used); + memcpy(cache_name_file, cache->action.name_file.string, cache->action.name_file.used); + + // @fixme the cache should probably store a rule type and then that can used instead of calling controller_rule_copy(), which would need to be copied here just like the other cache properties. // recursive rule processing is to always be synchronous. status = controller_rule_process(at, action, options & controller_rule_option_asynchronous ? options - controller_rule_option_asynchronous : options, thread, 0); if (status == F_child || status == F_signal) { - f_thread_condition_signal(&thread->setting->rules.array[at].wait); - f_thread_mutex_unlock(&thread->setting->rules.array[at].lock); + f_thread_condition_signal(&thread_data.setting->rules.array[at].wait); + f_thread_mutex_unlock(&thread_data.setting->rules.array[at].lock); break; } // restore cache. - memcpy(thread->cache_action->name_action.string, cache_name_action, cache_name_action_used); - memcpy(thread->cache_action->name_item.string, cache_name_item, cache_name_item_used); - memcpy(thread->cache_action->name_file.string, cache_name_file, cache_name_file_used); + memcpy(cache->action.name_action.string, cache_name_action, cache_name_action_used); + memcpy(cache->action.name_item.string, cache_name_item, cache_name_item_used); + memcpy(cache->action.name_file.string, cache_name_file, cache_name_file_used); - thread->cache_action->name_action.string[cache_name_action_used] = 0; - thread->cache_action->name_item.string[cache_name_item_used] = 0; + cache->action.name_action.string[cache_name_action_used] = 0; + cache->action.name_item.string[cache_name_item_used] = 0; - thread->cache_action->name_action.used = cache_name_action_used; - thread->cache_action->name_item.used = cache_name_item_used; - thread->cache_action->name_file.used = cache_name_file_used; + cache->action.name_action.used = cache_name_action_used; + cache->action.name_item.used = cache_name_item_used; + cache->action.name_file.used = cache_name_file_used; - thread->cache_action->line_action = cache_line_action; - thread->cache_action->line_item = cache_line_item; + cache->action.line_action = cache_line_action; + cache->action.line_item = cache_line_item; if (F_status_is_error(status)) { if (i == 0 || i == 1 || F_status_set_fine(status) == F_memory_not) { - f_thread_mutex_lock(&thread->mutex->print); + f_thread_mutex_lock(&thread_data.thread->mutex.print); - controller_rule_error_print_need_want_wish(thread->data->error, strings[i], dynamics[i]->array[j].string, "failed during execution"); - controller_rule_error_print(thread->data->error, *thread->cache_action, F_true); + controller_rule_error_print_need_want_wish(thread_data.data->error, strings[i], dynamics[i]->array[j].string, "failed during execution"); + controller_rule_error_print(thread_data.data->error, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); if (!(options & controller_rule_option_simulate) || F_status_set_fine(status) == F_memory_not) { - f_thread_condition_signal(&thread->setting->rules.array[at].wait); - f_thread_mutex_unlock(&thread->setting->rules.array[at].lock); + f_thread_condition_signal(&thread_data.setting->rules.array[at].wait); + f_thread_mutex_unlock(&thread_data.setting->rules.array[at].lock); break; } } else { - if (thread->data->warning.verbosity == f_console_verbosity_debug) { - f_thread_mutex_lock(&thread->mutex->print); + if (thread_data.data->warning.verbosity == f_console_verbosity_debug) { + f_thread_mutex_lock(&thread_data.thread->mutex.print); - controller_rule_error_print_need_want_wish(thread->data->warning, strings[i], dynamics[i]->array[j].string, "failed during execution"); - controller_rule_error_print(thread->data->warning, *thread->cache_action, F_true); + controller_rule_error_print_need_want_wish(thread_data.data->warning, strings[i], dynamics[i]->array[j].string, "failed during execution"); + controller_rule_error_print(thread_data.data->warning, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); } } } } - f_thread_condition_signal(&thread->setting->rules.array[at].wait); - f_thread_mutex_unlock(&thread->setting->rules.array[at].lock); + f_thread_condition_signal(&thread_data.setting->rules.array[at].wait); + f_thread_mutex_unlock(&thread_data.setting->rules.array[at].lock); - if (F_status_is_error(thread->setting->rules.array[at].status)) { + if (F_status_is_error(thread_data.setting->rules.array[at].status)) { if (i == 0 || i == 1) { - f_thread_mutex_lock(&thread->mutex->print); + f_thread_mutex_lock(&thread_data.thread->mutex.print); - controller_rule_error_print_need_want_wish(thread->data->error, strings[i], dynamics[i]->array[j].string, "is in a failed state"); + controller_rule_error_print_need_want_wish(thread_data.data->error, strings[i], dynamics[i]->array[j].string, "is in a failed state"); status = F_status_set_error(F_found_not); - controller_rule_error_print(thread->data->error, *thread->cache_action, F_true); + controller_rule_error_print(thread_data.data->error, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); if (!(options & controller_rule_option_simulate)) break; } else { - if (thread->data->warning.verbosity == f_console_verbosity_debug) { - f_thread_mutex_lock(&thread->mutex->print); + if (thread_data.data->warning.verbosity == f_console_verbosity_debug) { + f_thread_mutex_lock(&thread_data.thread->mutex.print); - controller_rule_error_print_need_want_wish(thread->data->warning, strings[i], dynamics[i]->array[j].string, "is in a failed state"); - controller_rule_error_print(thread->data->warning, *thread->cache_action, F_true); + controller_rule_error_print_need_want_wish(thread_data.data->warning, strings[i], dynamics[i]->array[j].string, "is in a failed state"); + controller_rule_error_print(thread_data.data->warning, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); } } } @@ -1713,7 +1744,7 @@ extern "C" { return status; } - if (!thread->asynchronouss.enabled) { + if (!thread_data.enabled) { return F_signal; } @@ -1721,7 +1752,7 @@ extern "C" { if (!(options & controller_rule_option_wait) && F_status_is_error_not(status)) { controller_rule_wait_all(thread); - if (!thread->asynchronouss.enabled) { + if (!thread_data.enabled) { return F_signal; } } @@ -1747,19 +1778,19 @@ extern "C" { if (missing) { - if (thread->data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&thread->mutex->print); + if (thread_data.data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&thread_data.thread->mutex.print); - fprintf(thread->data->error.to.stream, "%c", f_string_eol_s[0]); - fprintf(thread->data->error.to.stream, "%s%sThe rule '", thread->data->error.context.before->string, thread->data->error.prefix ? thread->data->error.prefix : f_string_empty_s); - fprintf(thread->data->error.to.stream, "%s%s%s%s", thread->data->error.context.after->string, thread->data->error.notable.before->string, rule->name.used ? rule->name.string : f_string_empty_s, thread->data->error.notable.after->string); - fprintf(thread->data->error.to.stream, "%s' has no '", thread->data->error.context.before->string); - fprintf(thread->data->error.to.stream, "%s%s%s%s", thread->data->error.context.after->string, thread->data->error.notable.before->string, controller_rule_action_type_name(action).string, thread->data->error.notable.after->string); - fprintf(thread->data->error.to.stream, "%s' action to execute.%s%c", thread->data->error.context.before->string, thread->data->error.context.after->string, f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(thread_data.data->error.to.stream, "%s%sThe rule '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, rule->name.used ? rule->name.string : f_string_empty_s, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s' has no '", thread_data.data->error.context.before->string); + fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, controller_rule_action_type_name(action).string, thread_data.data->error.notable.after->string); + fprintf(thread_data.data->error.to.stream, "%s' action to execute.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]); - controller_rule_error_print(thread->data->error, *thread->cache_action, F_true); + controller_rule_error_print(thread_data.data->error, cache->action, F_true); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); } status = F_status_set_error(F_parameter); @@ -1767,24 +1798,36 @@ extern "C" { } if (F_status_is_error_not(status)) { - status = controller_rule_execute(index, action, options, thread, asynchronous); + // @fixme the cache should probably store a rule type and then that can used instead of calling controller_rule_copy() here. + controller_rule_t rule = controller_rule_t_initialize; + + status = controller_rule_copy(&thread_data.setting->rules.array[index], &rule); + + if (F_status_is_error_not(status)) { + status = controller_rule_execute(action, options, thread_data, &cache, &rule); + + // @fixme there needs to be a new rule structure for storing the status state and the rule data, for any given execution (this should also be locking and unlocking). + thread_data.setting->rules.array[index].status = rule.status; + } + + controller_rule_delete_simple(&rule); if (status == F_child) { return F_child; } - if (!thread->asynchronouss.enabled) { + if (!thread_data.enabled) { return F_signal; } if (F_status_is_error(status)) { - controller_rule_error_print_locked(thread->data->error, *thread->cache_action, F_true, thread); + controller_rule_error_print_locked(thread_data.data->error, cache->action, F_true, thread); } } } // remove this rule off the stack. - thread->stack->used--; + thread_data.thread->asynchronouss.array[thread_data.id].stack.used--; if (F_status_is_error(status)) { return status; @@ -1795,25 +1838,25 @@ extern "C" { #endif // _di_controller_rule_process_ #ifndef _di_controller_rule_process_asynchronous_ - f_status_t controller_rule_process_asynchronous(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_thread_t *thread) { + f_status_t controller_rule_process_asynchronous(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache) { - f_thread_mutex_lock(&thread->mutex->asynchronous); + f_thread_mutex_lock(&thread_data->mutex.asynchronous); - if (!thread->asynchronouss.enabled) { - f_thread_mutex_unlock(&thread->mutex->asynchronous); + if (!thread_data.thread->enabled) { + f_thread_mutex_unlock(&thread_data.thread->mutex.asynchronous); return F_signal; } - f_status_t status = controller_asynchronouss_increase(&thread->asynchronouss); + f_status_t status = controller_asynchronouss_increase(&thread_data.thread->asynchronouss); if (F_status_is_error(status)) { - f_thread_mutex_unlock(&thread->mutex->asynchronous); + f_thread_mutex_unlock(&thread_data.thread->mutex.asynchronous); return status; } - controller_asynchronous_t *asynchronous = &thread->asynchronouss.array[thread->asynchronouss.used++]; + controller_asynchronous_t *asynchronous = &thread_data.thread->asynchronouss.array[thread_data.thread->asynchronouss.used++]; controller_macro_asynchronous_t_clear((*asynchronous)); @@ -1821,18 +1864,18 @@ extern "C" { asynchronous->state = controller_asynchronous_state_active; asynchronous->action = action; asynchronous->options = options; - asynchronous->thread = (void *) thread; - asynchronous->cache.line_action = thread->cache_action->line_action; - asynchronous->cache.line_item = thread->cache_action->line_item; + asynchronous->thread_data.thread = (void *) thread_data.thread; + asynchronous->cache.line_action = thread_data.thread->cache_action->line_action; + asynchronous->cache.line_item = thread_data.thread->cache_action->line_item; - status = f_string_dynamic_append(thread->cache_action->name_action, &asynchronous->cache.name_action); + status = f_string_dynamic_append(thread_data.thread->cache_action->name_action, &asynchronous->cache.name_action); if (F_status_is_error_not(status)) { - status = f_string_dynamic_append(thread->cache_action->name_file, &asynchronous->cache.name_file); + status = f_string_dynamic_append(thread_data.thread->cache_action->name_file, &asynchronous->cache.name_file); } if (F_status_is_error_not(status)) { - status = f_string_dynamic_append(thread->cache_action->name_item, &asynchronous->cache.name_item); + status = f_string_dynamic_append(thread_data.thread->cache_action->name_item, &asynchronous->cache.name_item); } if (F_status_is_error_not(status)) { @@ -1842,10 +1885,10 @@ extern "C" { if (F_status_is_error(status)) { controller_macro_asynchronous_t_delete_simple((*asynchronous)); - thread->asynchronouss.used--; + thread_data.thread->asynchronouss.used--; } - f_thread_mutex_unlock(&thread->mutex->asynchronous); + f_thread_mutex_unlock(&thread_data.thread->mutex.asynchronous); if (F_status_is_error(status)) { return status; @@ -1856,7 +1899,7 @@ extern "C" { #endif // _di_controller_rule_process_asynchronous_ #ifndef _di_controller_rule_read_ - f_status_t controller_rule_read(const controller_data_t data, const controller_setting_t setting, const f_string_static_t rule_id, controller_thread_t *thread, controller_cache_t *cache, controller_rule_t *rule) { + f_status_t controller_rule_read(const f_string_static_t rule_id, controller_thread_data_t thread_data, controller_cache_t *cache, controller_rule_t *rule) { f_status_t status = F_none; bool for_item = F_true; @@ -1940,16 +1983,16 @@ extern "C" { status = f_string_dynamic_append_nulless(rule_id, &rule->id); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true); } else { status = f_string_dynamic_terminate_after(&rule->id); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true); } else { - status = controller_file_load(data, setting, controller_string_rules_s, rule->id, controller_string_rule_s, controller_string_rules_length, controller_string_rule_length, cache); + status = controller_file_load(controller_string_rules_s, rule->id, controller_string_rule_s, controller_string_rules_length, controller_string_rule_length, thread_data, cache); } } @@ -1962,13 +2005,13 @@ extern "C" { status = fll_fss_basic_list_read(cache->buffer_file, &range, &cache->object_items, &cache->content_items, &cache->delimits, 0, &cache->comments); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true); } else { status = fl_fss_apply_delimit(cache->delimits, &cache->buffer_file); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true); } } } @@ -1978,7 +2021,7 @@ extern "C" { status = controller_rule_items_increase_by(cache->object_items.used, &rule->items); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "controller_rule_items_increase_by", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_rule_items_increase_by", F_true); } else { f_array_length_t i = 0; @@ -2015,7 +2058,7 @@ extern "C" { status = f_fss_count_lines(cache->buffer_file, cache->object_items.array[i].start, &cache->action.line_item); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_fss_count_lines", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_fss_count_lines", F_true); break; } @@ -2024,7 +2067,7 @@ extern "C" { status = controller_string_dynamic_rip_nulless_terminated(cache->buffer_file, cache->object_items.array[i], &cache->action.name_item); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "controller_string_dynamic_rip_nulless_terminated", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_rip_nulless_terminated", F_true); break; } @@ -2041,14 +2084,14 @@ extern "C" { rule->items.array[rule->items.used].type = controller_rule_item_type_service; } else { - if (data.warning.verbosity == f_console_verbosity_debug) { - fprintf(data.warning.to.stream, "%s%sUnknown rule item '", data.warning.context.before->string, data.warning.prefix ? data.warning.prefix : f_string_empty_s); - fprintf(data.warning.to.stream, "%s%s", data.warning.context.after->string, data.warning.notable.before->string); - f_print_dynamic(data.warning.to.stream, cache->action.name_item); - fprintf(data.warning.to.stream, "%s", data.warning.notable.after->string); - fprintf(data.warning.to.stream, "%s'.%s%c", data.warning.context.before->string, data.warning.context.after->string, f_string_eol_s[0]); - - controller_rule_error_print(data.warning, cache->action, F_true); + if (thread_data.data->warning.verbosity == f_console_verbosity_debug) { + fprintf(thread_data.data->warning.to.stream, "%s%sUnknown rule item '", thread_data.data->warning.context.before->string, thread_data.data->warning.prefix ? thread_data.data->warning.prefix : f_string_empty_s); + fprintf(thread_data.data->warning.to.stream, "%s%s", thread_data.data->warning.context.after->string, thread_data.data->warning.notable.before->string); + f_print_dynamic(thread_data.data->warning.to.stream, cache->action.name_item); + fprintf(thread_data.data->warning.to.stream, "%s", thread_data.data->warning.notable.after->string); + fprintf(thread_data.data->warning.to.stream, "%s'.%s%c", thread_data.data->warning.context.before->string, thread_data.data->warning.context.after->string, f_string_eol_s[0]); + + controller_rule_error_print(thread_data.data->warning, cache->action, F_true); } continue; @@ -2057,19 +2100,19 @@ extern "C" { status = f_string_dynamic_partial_append(cache->buffer_file, cache->content_items.array[i].array[0], &cache->buffer_item); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_string_dynamic_partial_append", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_partial_append", F_true); break; } status = f_string_dynamic_terminate_after(&cache->buffer_item); if (F_status_is_error(status)) { - fll_error_print(data.error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true); + fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true); break; } if (rule->items.array[rule->items.used].type) { - status = controller_rule_item_read(data, cache, &rule->items.array[rule->items.used]); + status = controller_rule_item_read(thread_data, cache, &rule->items.array[rule->items.used]); if (F_status_is_error(status)) break; rule->items.used++; @@ -2077,7 +2120,7 @@ extern "C" { else { for_item = F_false; - status = controller_rule_setting_read(data, setting, cache, rule); + status = controller_rule_setting_read(thread_data, cache, rule); if (F_status_is_error(status)) { if (F_status_set_fine(status) == F_memory_not) { @@ -2090,7 +2133,7 @@ extern "C" { } if (F_status_is_error(status)) { - controller_rule_error_print(data.error, cache->action, for_item); + controller_rule_error_print(thread_data.data->error, cache->action, for_item); rule->status = controller_status_simplify(F_status_set_fine(status)); return F_false; @@ -2117,7 +2160,7 @@ extern "C" { return status; } - f_string_length_t path_original_length = 0; + f_array_length_t path_original_length = 0; f_string_dynamic_t *setting_value = 0; f_string_dynamics_t *setting_values = 0; f_string_maps_t *setting_maps = 0; @@ -3752,12 +3795,12 @@ extern "C" { #endif // _di_controller_rule_setting_read_ #ifndef _di_controller_rule_simulate_ - void controller_rule_simulate(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_thread_t *thread) { + void controller_rule_simulate(const uint8_t action, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache, controller_rule_t *rule) { - controller_data_t *data = thread->data; - controller_setting_t *setting = thread->setting; + controller_data_t *data = thread_data.thread->data; + controller_setting_t *setting = thread_data.thread->setting; - f_thread_mutex_lock(&thread->mutex->print); + f_thread_mutex_lock(&thread_data.thread->mutex.print); switch (action) { case controller_rule_action_type_kill: @@ -3775,10 +3818,10 @@ extern "C" { fprintf(data->error.to.stream, "%s%s%s%s", data->error.context.after->string, data->error.notable.before->string, controller_rule_action_type_name(action).string, data->error.notable.after->string); fprintf(data->error.to.stream, "%s' while attempting to simulate rule execution.%s%c", data->error.context.before->string, data->error.context.after->string, f_string_eol_s[0]); - controller_rule_error_print(data->error, *thread->cache_action, F_true); + controller_rule_error_print(data->error, cache->action, F_true); } - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); return; } @@ -3827,10 +3870,10 @@ extern "C" { fprintf(data->output.stream, " %s%s%s ", data->context.set.important.before->string, controller_string_capability_s, data->context.set.important.after->string); if (rule->capability) { - thread->cache_action->generic.used = 0; + cache->action.generic.used = 0; - if (F_status_is_error_not(f_capability_to_text(rule->capability, &thread->cache_action->generic))) { - fprintf(data->output.stream, "%s", thread->cache_action->generic.string); + if (F_status_is_error_not(f_capability_to_text(rule->capability, &cache->action.generic))) { + fprintf(data->output.stream, "%s", cache->action.generic.string); } } @@ -4054,14 +4097,14 @@ extern "C" { setting->rules.array[index].status = F_complete; - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread_data.thread->mutex.print); } #endif // _di_controller_rule_simulate_ #ifndef _di_controller_rule_wait_all_ void controller_rule_wait_all(controller_thread_t *thread) { - for (f_array_length_t i = 0; i < thread->asynchronouss.used && thread->asynchronouss.enabled; ++i) { + for (f_array_length_t i = 0; i < thread->asynchronouss.used && thread->enabled; ++i) { // do not need to wait when state is 0 or joined. if (!thread->asynchronouss.array[i].state || thread->asynchronouss.array[i].state == controller_asynchronous_state_joined) { @@ -4074,21 +4117,21 @@ extern "C" { f_thread_mutex_lock(&thread->setting->rules.array[thread->asynchronouss.array[i].index].lock); - while (thread->asynchronouss.enabled && thread->setting->rules.array[thread->asynchronouss.array[i].index].status == F_known_not) { + while (thread->enabled && thread->setting->rules.array[thread->asynchronouss.array[i].index].status == F_known_not) { f_thread_condition_wait(&thread->setting->rules.array[thread->asynchronouss.array[i].index].wait, &thread->setting->rules.array[thread->asynchronouss.array[i].index].lock); } // while f_thread_mutex_unlock(&thread->setting->rules.array[thread->asynchronouss.array[i].index].lock); - if (!thread->asynchronouss.enabled) break; + if (!thread->enabled) break; - if (f_thread_mutex_lock_try(&thread->mutex->asynchronous) == F_none) { + if (f_thread_mutex_lock_try(&thread->mutex.asynchronous) == F_none) { if (thread->asynchronouss.array[i].state != controller_asynchronous_state_joined) { f_thread_join(thread->asynchronouss.array[i].id, 0); } - if (thread->asynchronouss.enabled && thread->asynchronouss.array[i].state) { + if (thread->enabled && thread->asynchronouss.array[i].state) { if (thread->asynchronouss.array[i].state == controller_asynchronous_state_done) { thread->asynchronouss.array[i].state = controller_asynchronous_state_joined; } @@ -4096,7 +4139,7 @@ extern "C" { controller_macro_cache_action_t_clear(thread->asynchronouss.array[i].cache); } - f_thread_mutex_unlock(&thread->mutex->asynchronous); + f_thread_mutex_unlock(&thread->mutex.asynchronous); } } // for } diff --git a/level_3/controller/c/private-rule.h b/level_3/controller/c/private-rule.h index 6ecb15c..cb26b97 100644 --- a/level_3/controller/c/private-rule.h +++ b/level_3/controller/c/private-rule.h @@ -130,6 +130,23 @@ extern "C" { #endif // _di_controller_rule_action_read_ /** + * Copy a rule, allocating new space as necessary. + * + * @param source + * The source rule to copy from. + * @param destination + * The destination rule to copy to. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: XXXX(). + */ +#ifndef _di_controller_rule_copy_ + extern f_status_t controller_rule_copy(controller_rule_t *source, controller_rule_t *destination) f_gcc_attribute_visibility_internal; +#endif // _di_controller_rule_copy_ + +/** * Print additional error/warning information in addition to existing error. * * This is explicitly intended to be used in addition to the error message. @@ -226,8 +243,6 @@ extern "C" { /** * Perform an execution of the given rule. * - * @param index - * The position in the setting.rules array representing the rule to execute. * @param type * The action to perform based on the action type codes. * @@ -242,11 +257,12 @@ extern "C" { * @param options * A number using bits to represent specific boolean options. * If bit controller_rule_option_simulate, then the rule execution is in simulation mode (printing a message that the rule would be executed but does not execute the rule). - * @param thread + * @param thread_data * The thread data. - * @param asynchronous - * Holds the current asynchronous thread information if this is being run from within one. - * Set to NULL when this is not being called from within an asynchronous thread. + * @param cache + * A structure for containing and caching relevant data. + * @param rule + * The rule to process. * * @return * F_none on success. @@ -258,14 +274,12 @@ extern "C" { * On failure, the individual status for the rule is set to an appropriate error status. */ #ifndef _di_controller_rule_execute_ - extern f_status_t controller_rule_execute(const f_array_length_t index, const uint8_t type, const uint8_t options, controller_thread_t *thread, controller_asynchronous_t *asynchronous) f_gcc_attribute_visibility_internal; + extern f_status_t controller_rule_execute(const uint8_t type, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache, controller_rule_t *rule) f_gcc_attribute_visibility_internal; #endif // _di_controller_rule_execute_ /** * Perform an execution of the given rule in the foreground. * - * @param index - * The index location in the rules running this action. * @param type * The item type code. * @param action @@ -286,11 +300,10 @@ extern "C" { * If bit controller_rule_option_simulate, then the rule execution is in simulation mode (printing a message that the rule would be executed but does not execute the rule). * @param execute_set * The execute parameter and as settings. - * @param thread + * @param thread_data * The thread data. - * @param asynchronous - * Holds the current asynchronous thread information if this is being run from within one. - * Set to NULL when this is not being called from within an asynchronous thread. + * @param rule + * The rule to process. * * @return * F_none on success. @@ -302,7 +315,7 @@ extern "C" { * @see fll_execute_program() */ #ifndef _di_controller_rule_execute_foreground_ - extern f_status_t controller_rule_execute_foreground(const f_array_length_t index, const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, controller_execute_set_t * const execute_set, controller_thread_t *thread, controller_asynchronous_t *asynchronous) f_gcc_attribute_visibility_internal; + extern f_status_t controller_rule_execute_foreground(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, controller_execute_set_t * const execute_set, controller_thread_data_t thread_data, controller_rule_t *rule) f_gcc_attribute_visibility_internal; #endif // _di_controller_rule_execute_foreground_ /** @@ -311,8 +324,6 @@ extern "C" { * When this is synchronous, this will wait for the PID file to be generated before continuing. * When this is asynchronous, this will continue on adding the rule id and action to the asynchronous list. * - * @param index - * The index location in the rules running this action. * @param type * The item type code. * @param action @@ -350,27 +361,28 @@ extern "C" { * @see fll_execute_program() */ #ifndef _di_controller_rule_execute_pid_with_ - extern f_status_t controller_rule_execute_pid_with(const f_array_length_t index, const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, controller_execute_set_t * const execute_set, controller_thread_t *thread, controller_asynchronous_t *asynchronous) f_gcc_attribute_visibility_internal; + extern f_status_t controller_rule_execute_pid_with(const uint8_t type, const controller_rule_action_t action, const f_string_t program, const f_string_dynamics_t arguments, const uint8_t options, controller_execute_set_t * const execute_set, controller_thread_data_t thread_data, controller_rule_t *rule) f_gcc_attribute_visibility_internal; #endif // _di_controller_rule_execute_pid_with_ /** * Search the already loaded rules to see if one is found. * - * @param data - * The program data. - * @param setting - * The controller settings data. + * Looks up the rules starting from the end so that the latest loaded version of any given rule is found and used first. + * The rule thread should be locked before calling this to ensure the rule is not loaded after this search. + * * @param rule_id * The string identifying the rule. * This is constructed from the path parts to the file without the file extension and without the settings directory prefix. * "/etc/controller/rules/example/my.rule" would have a rule id of "example/my". + * @param thread_data + * The thread data. * * @return * If found, a valid location within the setting.rules array. * If not found, then setting.rules.used is returned. */ #ifndef _di_controller_rule_find_loaded_ - extern f_array_length_t controller_rule_find_loaded(const controller_data_t data, const controller_setting_t setting, const f_string_static_t rule_id) f_gcc_attribute_visibility_internal; + extern f_array_length_t controller_rule_find_loaded(const f_string_static_t rule_id, controller_thread_data_t thread_data) f_gcc_attribute_visibility_internal; #endif // _di_controller_rule_find_loaded_ /** @@ -521,8 +533,6 @@ extern "C" { * * This function is recursively called for each "need", "want", and "wish", and has a max recursion length of the max size of the f_array_lengths_t array. * - * @param index - * Position in the rules array representing the rule to execute * @param action * The action to perform based on the action type codes. * @@ -537,11 +547,10 @@ extern "C" { * If no bits set, then operate normally in a synchronous manner. * If bit controller_rule_option_simulate, then the rule execution is in simulation mode (printing a message that the rule would be executed but does not execute the rule). * If bit controller_rule_option_asynchronous, then run asynchronously. - * @param thread + * @param thread_data * The thread data. - * @param asynchronous - * Holds the current asynchronous thread information if this is being run from within one. - * Set to NULL when this is not being called from within an asynchronous thread. + * @param cache + * A structure for containing and caching relevant data. * * @return * F_none on success. @@ -549,7 +558,7 @@ extern "C" { * F_signal on (exit) signal received. */ #ifndef _di_controller_rule_process_ - extern f_status_t controller_rule_process(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_thread_t *thread, controller_asynchronous_t *asynchronous) f_gcc_attribute_visibility_internal; + extern f_status_t controller_rule_process(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache) f_gcc_attribute_visibility_internal; #endif // _di_controller_rule_process_ /** @@ -576,8 +585,10 @@ extern "C" { * If no bits set, then operate normally in a synchronous manner. * If bit controller_rule_option_simulate, then the rule execution is in simulation mode (printing a message that the rule would be executed but does not execute the rule). * If bit controller_rule_option_asynchronous, then run asynchronously. - * @param thread + * @param thread_data * The thread data. + * @param cache + * A structure for containing and caching relevant data. * * @return * F_none on success. @@ -588,21 +599,17 @@ extern "C" { * Errors (with error bit) from: f_thread_create(). */ #ifndef _di_controller_rule_process_asynchronous_ - extern f_status_t controller_rule_process_asynchronous(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_thread_t *thread) f_gcc_attribute_visibility_internal; + extern f_status_t controller_rule_process_asynchronous(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache) f_gcc_attribute_visibility_internal; #endif // _di_controller_rule_process_asynchronous_ /** * Read the rule file, extracting all valid items. * - * @param data - * The program data. - * @param setting - * The controller settings data. * @param rule_id * The string identifying the rule. * This is constructed from the path parts to the file without the file extension and without the settings directory prefix. * "/etc/controller/rules/example/my.rule" would have a rule id of "example/my". - * @param thread + * @param thread_data * The thread data. * @param cache * A structure for containing and caching relevant data. @@ -626,7 +633,7 @@ extern "C" { * @see fll_fss_basic_list_read(). */ #ifndef _di_controller_rule_read_ - extern f_status_t controller_rule_read(const controller_data_t data, const controller_setting_t setting, const f_string_static_t rule_id, controller_thread_t *thread, controller_cache_t *cache, controller_rule_t *rule) f_gcc_attribute_visibility_internal; + extern f_status_t controller_rule_read(const f_string_static_t rule_id, controller_thread_data_t thread_data, controller_cache_t *cache, controller_rule_t *rule) f_gcc_attribute_visibility_internal; #endif // _di_controller_rule_read_ /** @@ -675,8 +682,6 @@ extern "C" { * * This automatically sets the rule's status to F_complete. * - * @param index - * The position in the setting.rules array representing the rule to simulate. * @param action * The action to perform based on the action type codes. * @@ -691,11 +696,15 @@ extern "C" { * If no bits set, then operate normally in a synchronous manner. * If bit controller_rule_option_simulate, then the rule execution is in simulation mode (printing a message that the rule would be executed but does not execute the rule). * If bit controller_rule_option_asynchronous, then run asynchronously. - * @param thread + * @param thread_data * The thread data. + * @param cache + * A structure for containing and caching relevant data. + * @param rule + * The rule to process. */ #ifndef _di_controller_rule_simulate_ - extern void controller_rule_simulate(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_thread_t *thread) f_gcc_attribute_visibility_internal; + extern void controller_rule_simulate(const uint8_t action, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache, controller_rule_t *rule) f_gcc_attribute_visibility_internal; #endif // _di_controller_rule_simulate_ /** diff --git a/level_3/controller/c/private-thread.c b/level_3/controller/c/private-thread.c index b39d6e1..914f6b4 100644 --- a/level_3/controller/c/private-thread.c +++ b/level_3/controller/c/private-thread.c @@ -15,7 +15,7 @@ extern "C" { controller_asynchronous_t *asynchronous = (controller_asynchronous_t *) arguments; controller_thread_t *thread_main = (controller_thread_t *) asynchronous->thread; - if (!thread_main->asynchronouss.enabled) { + if (!thread_main->enabled) { return 0; } @@ -47,9 +47,9 @@ extern "C" { #ifndef _di_controller_thread_asynchronous_cancel_ void controller_thread_asynchronous_cancel(controller_thread_t *thread) { - thread->asynchronouss.enabled = F_false; + thread->enabled = F_false; - f_thread_mutex_lock(&thread->mutex->asynchronous); + f_thread_mutex_lock(&thread->mutex.asynchronous); for (f_array_length_t i = 0; i < thread->asynchronouss.used; ++i) { @@ -75,95 +75,89 @@ extern "C" { thread->asynchronouss.used = 0; - f_thread_mutex_unlock(&thread->mutex->asynchronous); + f_thread_mutex_unlock(&thread->mutex.asynchronous); } #endif // _di_controller_thread_asynchronous_cancel_ -#ifndef _di_controller_thread_cache_ - void * controller_thread_cache(void *arguments) { +#ifndef _di_controller_thread_cleanup_ + void * controller_thread_cleanup(void *arguments) { - controller_thread_t *thread = (controller_thread_t *) arguments; + controller_thread_data_t *thread_data = (controller_thread_data_t *) arguments; - const unsigned int interval = thread->data->parameters[controller_parameter_test].result == f_console_result_found ? controller_thread_cache_cleanup_interval_short : controller_thread_cache_cleanup_interval_long; + const unsigned int interval = thread_data->data->parameters[controller_parameter_test].result == f_console_result_found ? controller_thread_cache_cleanup_interval_short : controller_thread_cache_cleanup_interval_long; f_array_length_t i = 0; - for (; thread->asynchronouss.enabled; ) { + for (; thread_data->thread->enabled; ) { sleep(interval); - if (f_thread_mutex_lock_try(&thread->mutex->cache) == F_none) { - controller_macro_cache_t_delete_simple((*thread->cache_main)); - controller_macro_cache_action_t_delete_simple((*thread->cache_action)); + if (f_thread_mutex_lock_try(&thread_data->thread->mutex.asynchronous) == F_none) { + controller_thread_t *thread = &thread_data->thread; - if (f_thread_mutex_lock_try(&thread->mutex->asynchronous) == F_none) { + if (thread->asynchronouss.used) { + for (i = 0; i < thread->asynchronouss.used; ++i) { - if (thread->asynchronouss.used) { - for (i = 0; i < thread->asynchronouss.used; ++i) { + if (!thread->enabled) break; + if (!thread->asynchronouss.array[i].state) continue; - if (!thread->asynchronouss.enabled) break; - if (!thread->asynchronouss.array[i].state) continue; + if (f_thread_mutex_lock_try(&thread->asynchronouss.array[i].lock) != F_none) continue; - if (f_thread_mutex_lock_try(&thread->asynchronouss.array[i].lock) != F_none) continue; + if (f_thread_mutex_lock_try(&thread_data->setting->rules.array[thread->asynchronouss.array[i].index].lock) == F_none) { - if (f_thread_mutex_lock_try(&thread->setting->rules.array[thread->asynchronouss.array[i].index].lock) == F_none) { - - if (thread->asynchronouss.array[i].state == controller_asynchronous_state_done) { - f_thread_join(thread->asynchronouss.array[i].id, 0); - thread->asynchronouss.array[i].state = controller_asynchronous_state_joined; - } - - if (thread->asynchronouss.array[i].state == controller_asynchronous_state_joined) { - controller_macro_asynchronous_t_delete_simple(thread->asynchronouss.array[i]); + if (thread->asynchronouss.array[i].state == controller_asynchronous_state_done) { + f_thread_join(thread->asynchronouss.array[i].id, 0); + thread->asynchronouss.array[i].state = controller_asynchronous_state_joined; + } - thread->asynchronouss.array[i].state = 0; - } + if (thread->asynchronouss.array[i].state == controller_asynchronous_state_joined) { + controller_macro_asynchronous_t_delete_simple(thread->asynchronouss.array[i]); - f_thread_condition_signal(&thread->setting->rules.array[thread->asynchronouss.array[i].index].wait); - f_thread_mutex_unlock(&thread->setting->rules.array[thread->asynchronouss.array[i].index].lock); + thread->asynchronouss.array[i].state = 0; } - f_thread_mutex_unlock(&thread->asynchronouss.array[i].lock); - } // for + f_thread_condition_signal(&thread_data->setting->rules.array[thread->asynchronouss.array[i].index].wait); + f_thread_mutex_unlock(&thread_data->setting->rules.array[thread->asynchronouss.array[i].index].lock); + } - for (i = thread->asynchronouss.used - 1; thread->asynchronouss.used; --i, --thread->asynchronouss.used) { + f_thread_mutex_unlock(&thread->asynchronouss.array[i].lock); + } // for - if (!thread->asynchronouss.enabled) break; + for (i = thread->asynchronouss.used - 1; thread->asynchronouss.used; --i, --thread->asynchronouss.used) { - if (f_thread_mutex_lock_try(&thread->asynchronouss.array[i].lock) != F_none) break; + if (!thread->enabled) break; - if (thread->asynchronouss.array[i].state == controller_asynchronous_state_joined) { - controller_macro_asynchronous_t_delete_simple(thread->asynchronouss.array[i]); + if (f_thread_mutex_lock_try(&thread->asynchronouss.array[i].lock) != F_none) break; - thread->asynchronouss.array[i].state = 0; - } - else if (thread->asynchronouss.array[i].state) { - f_thread_mutex_unlock(&thread->asynchronouss.array[i].lock); - break; - } + if (thread->asynchronouss.array[i].state == controller_asynchronous_state_joined) { + controller_macro_asynchronous_t_delete_simple(thread->asynchronouss.array[i]); + thread->asynchronouss.array[i].state = 0; + } + else if (thread->asynchronouss.array[i].state) { f_thread_mutex_unlock(&thread->asynchronouss.array[i].lock); - } // for - } + break; + } - if (thread->asynchronouss.enabled && thread->asynchronouss.used < thread->asynchronouss.size) { - controller_asynchronouss_resize(thread->asynchronouss.used, &thread->asynchronouss); - } + f_thread_mutex_unlock(&thread->asynchronouss.array[i].lock); + } // for + } - f_thread_mutex_unlock(&thread->mutex->asynchronous); + if (thread->enabled && thread->asynchronouss.used < thread->asynchronouss.size) { + controller_asynchronouss_resize(thread->asynchronouss.used, &thread->asynchronouss); } - f_thread_mutex_unlock(&thread->mutex->cache); + f_thread_mutex_unlock(&thread->mutex.asynchronous); } } // for return 0; } -#endif // _di_controller_thread_cache_ +#endif // _di_controller_thread_cleanup_ #ifndef _di_controller_thread_control_ void * controller_thread_control(void *arguments) { - controller_thread_t *thread = (controller_thread_t *) arguments; + controller_thread_data_t *thread_data = (controller_thread_data_t *) arguments; // @todo @@ -172,147 +166,158 @@ extern "C" { #endif // _di_controller_thread_control_ #ifndef _di_controller_thread_main_ - f_status_t controller_thread_main(const f_string_static_t entry_name, controller_cache_t *cache, controller_thread_t *thread) { + f_status_t controller_thread_main(const f_string_static_t entry_name, controller_data_t *data, controller_setting_t *setting) { - f_thread_id_t thread_cache = 0; - f_thread_id_t thread_control = 0; - f_thread_id_t thread_rule = 0; - f_thread_id_t thread_signal = 0; + f_status_t status = F_none; - f_status_t status = f_thread_create(0, &thread_signal, &controller_thread_signal, (void *) thread); + controller_thread_t thread = controller_thread_t_initialize; + controller_processs_t processs = controller_processs_t_initialize; + controller_thread_data_t data_main = controller_macro_thread_data_t_initialize(0, data, setting, &processs, &thread); + + status = controller_asynchronouss_increase(&thread.asynchronouss); if (F_status_is_error_not(status)) { - status = f_thread_create(0, &thread_cache, &controller_thread_cache, (void *) thread); + status = f_thread_create(0, &thread.id_signal, &controller_thread_signal, (void *) &data_main); + } + + if (F_status_is_error_not(status)) { + status = f_thread_create(0, &thread.id_cleanup, &controller_thread_cleanup, (void *) &data_main); } if (F_status_is_error(status)) { - if (thread->data->error.verbosity != f_console_verbosity_quiet) { - controller_error_print_locked(thread->data->error, F_status_set_fine(status), "f_thread_create", F_true, thread); + if (data->error.verbosity != f_console_verbosity_quiet) { + controller_error_print_locked(data->error, F_status_set_fine(status), "f_thread_create", F_true, &thread); } } else { - if (thread->data->parameters[controller_parameter_daemon].result == f_console_result_found) { - thread->setting->ready = controller_setting_ready_done; + if (data->parameters[controller_parameter_daemon].result == f_console_result_found) { + setting->ready = controller_setting_ready_done; - if (f_file_exists(thread->setting->path_pid.string) == F_true) { - if (thread->data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&thread->mutex->print); + if (f_file_exists(setting->path_pid.string) == F_true) { + if (data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&thread.mutex.print); - fprintf(thread->data->error.to.stream, "%c", f_string_eol_s[0]); - fprintf(thread->data->error.to.stream, "%s%sThe pid file '", thread->data->error.context.before->string, thread->data->error.prefix ? thread->data->error.prefix : f_string_empty_s); - fprintf(thread->data->error.to.stream, "%s%s%s%s", thread->data->error.context.after->string, thread->data->error.notable.before->string, thread->setting->path_pid.string, thread->data->error.notable.after->string); - fprintf(thread->data->error.to.stream, "%s' must not already exist.%s%c", thread->data->error.context.before->string, thread->data->error.context.after->string, f_string_eol_s[0]); + fprintf(data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(data->error.to.stream, "%s%sThe pid file '", data->error.context.before->string, data->error.prefix ? data->error.prefix : f_string_empty_s); + fprintf(data->error.to.stream, "%s%s%s%s", data->error.context.after->string, data->error.notable.before->string, setting->path_pid.string, data->error.notable.after->string); + fprintf(data->error.to.stream, "%s' must not already exist.%s%c", data->error.context.before->string, data->error.context.after->string, f_string_eol_s[0]); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread.mutex.print); } - thread->setting->ready = controller_setting_ready_abort; + setting->ready = controller_setting_ready_abort; status = F_status_set_error(F_available_not); } } else { - f_thread_mutex_lock(&thread->mutex->cache); - status = controller_entry_read(*thread->data, *thread->setting, entry_name, cache, &thread->setting->entry); + status = controller_entry_read(entry_name, data_main, &thread.asynchronouss.array[0].cache); if (F_status_is_error(status)) { - thread->setting->ready = controller_setting_ready_fail; + setting->ready = controller_setting_ready_fail; } else if (status != F_signal && status != F_child) { - status = controller_preprocess_entry(cache, thread); + status = controller_preprocess_entry(data_main, &thread.asynchronouss.array[0].cache); } if (F_status_is_error_not(status) && status != F_signal && status != F_child) { - if (thread->data->parameters[controller_parameter_validate].result == f_console_result_none || thread->data->parameters[controller_parameter_test].result == f_console_result_found) { + if (data->parameters[controller_parameter_validate].result == f_console_result_none || data->parameters[controller_parameter_test].result == f_console_result_found) { - if (f_file_exists(thread->setting->path_pid.string) == F_true) { - if (thread->data->error.verbosity != f_console_verbosity_quiet) { - f_thread_mutex_lock(&thread->mutex->print); + if (f_file_exists(setting->path_pid.string) == F_true) { + if (data->error.verbosity != f_console_verbosity_quiet) { + f_thread_mutex_lock(&thread.mutex.print); - fprintf(thread->data->error.to.stream, "%c", f_string_eol_s[0]); - fprintf(thread->data->error.to.stream, "%s%sThe pid file '", thread->data->error.context.before->string, thread->data->error.prefix ? thread->data->error.prefix : f_string_empty_s); - fprintf(thread->data->error.to.stream, "%s%s%s%s", thread->data->error.context.after->string, thread->data->error.notable.before->string, thread->setting->path_pid.string, thread->data->error.notable.after->string); - fprintf(thread->data->error.to.stream, "%s' must not already exist.%s%c", thread->data->error.context.before->string, thread->data->error.context.after->string, f_string_eol_s[0]); + fprintf(data->error.to.stream, "%c", f_string_eol_s[0]); + fprintf(data->error.to.stream, "%s%sThe pid file '", data->error.context.before->string, data->error.prefix ? data->error.prefix : f_string_empty_s); + fprintf(data->error.to.stream, "%s%s%s%s", data->error.context.after->string, data->error.notable.before->string, setting->path_pid.string, data->error.notable.after->string); + fprintf(data->error.to.stream, "%s' must not already exist.%s%c", data->error.context.before->string, data->error.context.after->string, f_string_eol_s[0]); - f_thread_mutex_unlock(&thread->mutex->print); + f_thread_mutex_unlock(&thread.mutex.print); } - thread->setting->ready = controller_setting_ready_fail; + setting->ready = controller_setting_ready_fail; status = F_status_set_error(F_available_not); } else { - status = controller_process_entry(cache, thread); + status = controller_process_entry(data_main, &thread.asynchronouss.array[0].cache); if (F_status_is_error(status)) { - thread->setting->ready = controller_setting_ready_fail; + setting->ready = controller_setting_ready_fail; } else if (status == F_signal || status == F_child) { - thread->setting->ready = controller_setting_ready_abort; + setting->ready = controller_setting_ready_abort; } else { - thread->setting->ready = controller_setting_ready_done; + setting->ready = controller_setting_ready_done; } } } } if (status == F_child) { + controller_thread_delete_simple(&thread); + return F_child; } - - f_thread_mutex_unlock(&thread->mutex->cache); } } - if (status != F_signal && thread->setting->signal) { + if (status != F_signal && setting->signal) { status = F_signal; } // only make the rule and control threads available once any/all pre-processing and is completed. if (F_status_is_error_not(status) && status != F_signal && status != F_child) { - if (thread->data->parameters[controller_parameter_validate].result == f_console_result_none) { - controller_rule_wait_all(thread); + if (data->parameters[controller_parameter_validate].result == f_console_result_none) { + controller_rule_wait_all(&thread); - status = f_thread_create(0, &thread_rule, &controller_thread_rule, (void *) thread); + status = f_thread_create(0, &thread.id_rule, &controller_thread_rule, (void *) &data_main); if (F_status_is_error_not(status)) { - status = f_thread_create(0, &thread_control, &controller_thread_control, (void *) thread); + status = f_thread_create(0, &thread.id_control, &controller_thread_control, (void *) &data_main); } if (F_status_is_error(status)) { - if (thread->data->error.verbosity != f_console_verbosity_quiet) { - controller_error_print_locked(thread->data->error, F_status_set_fine(status), "f_thread_create", F_true, thread); + if (data->error.verbosity != f_console_verbosity_quiet) { + controller_error_print_locked(data->error, F_status_set_fine(status), "f_thread_create", F_true, &thread); } } } } if (status == F_child) { + controller_thread_delete_simple(&thread); + return F_child; } - if (F_status_is_error_not(status) && status != F_signal && (thread->data->parameters[controller_parameter_validate].result == f_console_result_none || thread->data->parameters[controller_parameter_test].result == f_console_result_found)) { + // @todo consider f_thread_detach() over f_thread_join() when exiting. + if (F_status_is_error_not(status) && status != F_signal && (data->parameters[controller_parameter_validate].result == f_console_result_none || data->parameters[controller_parameter_test].result == f_console_result_found)) { // wait until signal thread exits, which happens on any termination signal. - f_thread_join(thread_signal, 0); + f_thread_join(thread.id_signal, 0); } else { - f_thread_cancel(thread_signal); - f_thread_join(thread_signal, 0); + f_thread_cancel(thread.id_signal); + f_thread_join(thread.id_signal, 0); } - if (thread->asynchronouss.enabled) { - controller_thread_asynchronous_cancel(thread); + if (thread.enabled) { + controller_thread_asynchronous_cancel(&thread); } - f_thread_cancel(thread_cache); - f_thread_cancel(thread_control); - f_thread_cancel(thread_rule); + // @todo when cancelling, make sure that whatever has a lock, no longer has any lock. + f_thread_cancel(thread.id_cleanup); + f_thread_cancel(thread.id_control); + f_thread_cancel(thread.id_rule); + + f_thread_join(thread.id_cleanup, 0); + f_thread_join(thread.id_control, 0); + f_thread_join(thread.id_rule, 0); - f_thread_join(thread_cache, 0); - f_thread_join(thread_control, 0); - f_thread_join(thread_rule, 0); + controller_processs_delete_simple(&processs); + controller_thread_delete_simple(&thread); if (F_status_is_error(status)) { return F_status_set_error(F_failure); @@ -329,11 +334,11 @@ extern "C" { #ifndef _di_controller_thread_rule_ void * controller_thread_rule(void *arguments) { - controller_thread_t *thread = (controller_thread_t *) arguments; + controller_thread_data_t *thread_data = (controller_thread_data_t *) arguments; // @todo - // f_thread_mutex_lock(&thread->mutex->rule); - // f_thread_mutex_unlock(&thread->mutex->rule); + // f_thread_mutex_lock(&thread_data->mutex.rule); + // f_thread_mutex_unlock(&thread_data->mutex.rule); return 0; } @@ -342,17 +347,17 @@ extern "C" { #ifndef _di_controller_thread_signal_ void * controller_thread_signal(void *arguments) { - controller_thread_t *thread = (controller_thread_t *) arguments; + controller_thread_data_t *thread_data = (controller_thread_data_t *) arguments; - for (int signal = 0; thread->asynchronouss.enabled; ) { + for (int signal = 0; thread_data->thread->enabled; ) { - sigwait(&thread->data->signal.set, &signal); + sigwait(&thread_data->data->signal.set, &signal); - if (thread->data->parameters[controller_parameter_interruptable].result == f_console_result_found) { + if (thread_data->data->parameters[controller_parameter_interruptable].result == f_console_result_found) { if (signal == F_signal_interrupt || signal == F_signal_abort || signal == F_signal_quit || signal == F_signal_termination) { - thread->setting->signal = signal; + thread_data->setting->signal = signal; - controller_thread_asynchronous_cancel(thread); + controller_thread_asynchronous_cancel(thread_data->thread); break; } } diff --git a/level_3/controller/c/private-thread.h b/level_3/controller/c/private-thread.h index 2e06299..99e7f80 100644 --- a/level_3/controller/c/private-thread.h +++ b/level_3/controller/c/private-thread.h @@ -37,25 +37,25 @@ extern "C" { #endif // _di_controller_thread_asynchronous_cancel_ /** - * Thread for periodically clearing cache if cache is not busy. + * Thread for periodically cleanup data when not busy. * * @param arguments * The thread arguments. - * Must be of type controller_thread_t. + * Must be of type controller_thread_data_t. * * @return * 0, always. */ -#ifndef _di_controller_thread_cache_ - extern void * controller_thread_cache(void *arguments) f_gcc_attribute_visibility_internal; -#endif // _di_controller_thread_cache_ +#ifndef _di_controller_thread_cleanup_ + extern void * controller_thread_cleanup(void *arguments) f_gcc_attribute_visibility_internal; +#endif // _di_controller_thread_cleanup_ /** * Thread for handling control requests and responses. * * @param arguments * The thread arguments. - * Must be of type controller_thread_t. + * Must be of type controller_thread_data_t. * * @return * 0, always. @@ -69,10 +69,10 @@ extern "C" { * * @param entry_name * The entry name string. - * @param cache - * The main/global cache to use. - * @param thread - * The thread data. + * @param data + * The controller data. + * @param setting + * The controller settings data. * * @return * F_none on success. @@ -81,7 +81,7 @@ extern "C" { * F_failure (with error bit) on any failure. */ #ifndef _di_controller_thread_main_ - extern f_status_t controller_thread_main(const f_string_static_t entry_name, controller_cache_t *cache, controller_thread_t *thread) f_gcc_attribute_visibility_internal; + extern f_status_t controller_thread_main(const f_string_static_t entry_name, controller_data_t *data, controller_setting_t *setting) f_gcc_attribute_visibility_internal; #endif // _di_controller_thread_main_ /** @@ -89,7 +89,7 @@ extern "C" { * * @param arguments * The thread arguments. - * Must be of type controller_thread_t. + * Must be of type controller_thread_data_t. * * @return * 0, always. @@ -105,7 +105,7 @@ extern "C" { * * @param arguments * The thread arguments. - * Must be of type controller_thread_t. + * Must be of type controller_thread_data_t. * * @return * 0, always. -- 1.8.3.1