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);
- }
-#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_default_allocation_step;
-
- if (size > f_array_length_t_size) {
- if (asynchronouss->used + 1 > f_array_length_t_size) {
- return F_status_set_error(F_array_too_large);
- }
-
- size = f_array_length_t_size;
- }
-
- return controller_asynchronouss_resize(size, asynchronouss);
- }
-
- return F_data_not;
- }
-#endif // _di_controller_asynchronous_increase_
-
-#ifndef _di_controller_asynchronouss_resize_
- f_status_t controller_asynchronouss_resize(const f_array_length_t length, controller_asynchronouss_t *asynchronouss) {
-
- f_status_t status = F_none;
-
- for (f_array_length_t i = length; i < asynchronouss->size; ++i) {
- controller_asynchronous_delete_simple(&asynchronouss->array[i]);
- } // for
-
- status = f_memory_resize(asynchronouss->size, length, sizeof(controller_asynchronous_t), (void **) & asynchronouss->array);
-
- if (F_status_is_error_not(status)) {
- asynchronouss->size = length;
-
- if (asynchronouss->used > asynchronouss->size) {
- asynchronouss->used = length;
- }
- }
-
- return status;
- }
-#endif // _di_controller_asynchronouss_resize_
-
#ifndef _di_controller_cache_action_delete_simple_
void controller_cache_action_delete_simple(controller_cache_action_t *cache) {
}
#endif // _di_controller_error_print_
+#ifndef _di_controller_lock_create_
+ f_status_t controller_lock_create(controller_lock_t *lock) {
+
+ f_status_t status = f_thread_mutex_create(0, &lock->print);
+ if (F_status_is_error(status)) return status;
+
+ status = f_thread_lock_create(0, &lock->entry);
+ if (F_status_is_error(status)) return status;
+
+ status = f_thread_lock_create(0, &lock->process);
+ if (F_status_is_error(status)) return status;
+
+ status = f_thread_lock_create(0, &lock->rule);
+ if (F_status_is_error(status)) return status;
+
+ return F_none;
+ }
+#endif // _di_controller_lock_create_
+
+#ifndef _di_controller_lock_delete_simple_
+ void controller_lock_delete_simple(controller_lock_t *lock) {
+
+ f_thread_mutex_delete(&lock->print);
+
+ f_thread_lock_delete(&lock->entry);
+ f_thread_lock_delete(&lock->process);
+ f_thread_lock_delete(&lock->rule);
+ }
+#endif // _di_controller_lock_delete_simple_
+
#ifndef _di_controller_process_delete_simple_
void controller_process_delete_simple(controller_process_t *process) {
- f_string_dynamic_resize(0, &process->id_rule);
+ f_string_dynamic_resize(0, &process->alias_rule);
f_thread_lock_delete(&process->lock);
f_thread_lock_delete(&process->active);
+ f_thread_mutex_delete(&process->running);
+ f_thread_condition_delete(&process->wait);
+
+ controller_cache_delete_simple(&process->cache);
- f_thread_lock_attribute_delete(&process->lock_attribute);
- f_thread_lock_attribute_delete(&process->active_attribute);
+ f_macro_array_lengths_t_delete_simple(process->stack)
}
#endif // _di_controller_process_delete_simple_
status = f_memory_resize(processs->size, length, sizeof(controller_process_t), (void **) & processs->array);
if (F_status_is_error_not(status)) {
+
+ // the lock must be initialized, but only once, so initialize immediately upon allocation.
+ while (processs->size < length) {
+
+ status = f_thread_lock_create(0, &processs->array[processs->size].lock);
+
+ if (F_status_is_error_not(status)) {
+ status = f_thread_lock_create(0, &processs->array[processs->size].active);
+ }
+
+ if (F_status_is_error_not(status)) {
+ status = f_thread_mutex_create(0, &processs->array[processs->size].running);
+ }
+
+ if (F_status_is_error_not(status)) {
+ status = f_thread_condition_create(0, &processs->array[processs->size].wait);
+ }
+
+ ++processs->size;
+
+ if (F_status_is_error(status)) {
+ processs->size = length;
+ return status;
+ }
+ } // while
+
processs->size = length;
if (processs->used > processs->size) {
#ifndef _di_controller_rule_delete_simple_
void controller_rule_delete_simple(controller_rule_t *rule) {
- f_string_dynamic_resize(0, &rule->id);
+ f_string_dynamic_resize(0, &rule->alias);
f_string_dynamic_resize(0, &rule->name);
f_string_dynamic_resize(0, &rule->path);
f_string_dynamic_resize(0, &rule->script);
#ifndef _di_controller_thread_delete_simple_
void controller_thread_delete_simple(controller_thread_t *thread) {
- f_thread_mutex_delete(&thread->lock.print);
-
- f_thread_lock_delete(&thread->lock.asynchronous);
- f_thread_lock_attribute_delete(&thread->lock.asynchronous_attribute);
-
- f_thread_lock_delete(&thread->lock.process);
- f_thread_lock_attribute_delete(&thread->lock.process_attribute);
-
- f_thread_lock_delete(&thread->lock.rule);
- f_thread_lock_attribute_delete(&thread->lock.rule_attribute);
-
- controller_asynchronouss_resize(0, &thread->asynchronouss);
+ controller_lock_delete_simple(&thread->lock);
+ controller_processs_resize(0, &thread->processs);
}
#endif // _di_controller_thread_delete_simple_
#endif // _di_controller_resource_limit_t_
/**
+ * Action related cache.
+ *
+ * line_action: The line in some file representing an Action.
+ * line_item: The line in some file representing an Item.
+ * name_action: A NULL terminated name of some Action.
+ * name_file: A NULL terminated name of some File.
+ * name_item: A NULL terminated name of some Item.
+ * generic: A NULL terminated string for general use.
+ */
+#ifndef _di_controller_cache_action_t_
+ typedef struct {
+ f_array_length_t line_action;
+ f_array_length_t line_item;
+
+ f_string_dynamic_t name_action;
+ f_string_dynamic_t name_file;
+ f_string_dynamic_t name_item;
+
+ 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_macro_cache_action_t_clear(cache) \
+ cache.line_action = 0; \
+ cache.line_item = 0; \
+ 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_
+
+/**
+ * A cache intended for re-using memory while loading and processing rules whenever possible.
+ *
+ * timestamp: The timestamp.
+ * range_action: The Range for some Action.
+ * ats: Locations.
+ * stack: Locations within a items history used as a history stack for circular recursion prevention.
+ * comments: Comments associated with a buffer string.
+ * delimits: Delimits associated with a buffer string.
+ * content_action: The specific Content for some Action.
+ * content_actions: Content for some Action.
+ * content_items: Content for some Item.
+ * object_actions: Objects for some Action.
+ * object_items: Objects for some Item.
+ * buffer_file: A generic file related buffer.
+ * buffer_item: A generic item related buffer.
+ * buffer_path: A generic path related buffer.
+ * action: A cache for some Action, often used by error printing for reporting where an error happened.
+ */
+#ifndef _di_controller_cache_t_
+ typedef struct {
+ f_time_spec_t timestamp;
+
+ f_string_range_t range_action;
+
+ f_array_lengths_t ats;
+ f_array_lengths_t stack;
+
+ f_fss_comments_t comments;
+ f_fss_delimits_t delimits;
+
+ f_fss_content_t content_action;
+ f_fss_contents_t content_actions;
+ f_fss_contents_t content_items;
+ f_fss_objects_t object_actions;
+ f_fss_objects_t object_items;
+
+ f_string_dynamic_t buffer_file;
+ f_string_dynamic_t buffer_item;
+ f_string_dynamic_t buffer_path;
+
+ 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, \
+ }
+#endif // _di_controller_cache_t_
+
+/**
* A structure for passing execution arguments to the execute functions.
*
* parameter: All parameters sent to the program on execution.
#define controller_macro_execute_set_t_initialize(option, environment, signals, data, as) { \
fl_macro_execute_parameter_t_initialize(option, environment, signals, data), \
- as \
+ 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 and related.
* The print lock is intended to lock any activity printing to stdout/stderr.
+ * The entry lock is intended to lock any activity on the entrys structure.
* 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.
*
- * print: The print mutex lock.
- * asynchronous: The asynchronous r/w lock.
- * asynchronous_attribute: The asynchronous r/w lock attribute.
- * process: The process r/w lock.
- * process_attribute: The process r/w lock attribute.
- * rule: The rule r/w lock.
- * rule_attribute: The rule r/w lock attribute.
- *
+ * print: The print mutex lock.
+ * entry: The entry r/w lock.
+ * process: The process r/w lock.
+ * rule: The rule r/w lock.
*/
#ifndef _di_controller_lock_t_
typedef struct {
f_thread_mutex_t print;
- f_thread_lock_t asynchronous;
- f_thread_lock_attribute_t asynchronous_attribute;
-
+ f_thread_lock_t entry;
f_thread_lock_t process;
- f_thread_lock_attribute_t process_attribute;
-
f_thread_lock_t rule;
- f_thread_lock_attribute_t rule_attribute;
} controller_lock_t;
#define controller_lock_t_initialize { \
f_thread_mutex_t_initialize, \
f_thread_lock_t_initialize, \
- f_thread_lock_attribute_t_initialize, \
f_thread_lock_t_initialize, \
- f_thread_lock_attribute_t_initialize, \
f_thread_lock_t_initialize, \
- f_thread_lock_attribute_t_initialize \
}
#endif // _di_controller_mutex_t_
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_
/**
0, \
0, \
}
-
- #define controller_macro_rule_actions_t_clear(actions) \
- actions.array = 0; \
- actions.size = 0; \
- actions.used = 0;
#endif // _di_controller_rule_actions_t_
/**
0, \
controller_rule_actions_t_initialize, \
}
-
- #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_
/**
0, \
0, \
}
-
- #define controller_macro_rule_items_t_clear(items) \
- items.array = 0; \
- items.size = 0; \
- items.used = 0;
#endif // _di_controller_rule_items_t_
/**
f_time_spec_t timestamp;
- f_string_dynamic_t id;
+ f_string_dynamic_t alias;
f_string_dynamic_t name;
f_string_dynamic_t path;
f_string_dynamic_t script;
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_
/**
0, \
0, \
}
-
- #define controller_macro_rules_t_clear(rules) \
- rules.array = 0; \
- rules.size = 0; \
- rules.used = 0;
#endif // _di_controller_rules_t_
/**
*
* This refers to "process" as in the processing of a single rule for the given Rule ID and does not refer to "process" as in a CPU Process.
*
- * id_rule: The Rule ID, such as "network/ntpdate".
- * status: The last execution status of the Rule.
- * lock: A read/write lock on the structure.
- * active: A read/write lock representing that something is currently using this (read locks = in use, write lock = see if in use and possibly prepare for delete).
- * lock_attribute: The lock attribute for "lock".
- * active_attribute: The lock attribute for "active".
+ * Process States:
+ * - idle: No process is running for this rule.
+ * - busy: A process is actively using this, and is running synchronously.
+ * - active: A process is actively using this, and is running asynchronously.
+ * - done: A process has finished running on this and there is a thread that needs to be cleaned up.
+ *
+ * id: The ID of this process relative to the processes array.
+ * alias_rule: The Rule alias, such as "network/ntpdate".
+ * status: The last execution status of the Rule.
+ * state: The state of the process.
+ * action: The action being performed.
+ * options: Configuration options for this asynchronous thread.
+ * child: The process id of a child process, if one is running (when forking to execute a child process).
+ * id_thread: The thread id, a valid ID when state is "active", and an invalid ID when the state is "busy".
+ * lock: A read/write lock on the structure.
+ * active: A read/write lock representing that something is currently using this (read locks = in use, write lock = begin deleting).
+ * running: A mutex lock for working with "wait" to designate that the process is being executed and to trigger anything waiting when done.
+ * wait: A thread condition to tell a process waiting process that the rule has is done being processed.
+ * cache: The cache used in this process.
+ * stack: A stack used to represent dependencies to avoid circular rule dependencies (If Rule A waits on Rule B, then Rule B must not wait on Rule A).
+ * main_data: Used for passing the controller_data_t data to the process thread (to populate controller_main_t).
+ * main_setting: Used for passing the controller_setting_t data to the process thread (to populate controller_main_t).
+ * main_thread: Used for passing the controller_thread_t data to the process thread (to populate controller_main_t).
*/
#ifndef _di_controller_process_t_
+ enum {
+ controller_process_state_idle = 1,
+ controller_process_state_busy,
+ controller_process_state_active,
+ controller_process_state_done,
+ };
+
typedef struct {
- f_string_dynamic_t id_rule;
+ f_array_length_t id;
+ f_string_dynamic_t alias_rule;
f_status_t status;
+ uint8_t state;
+ uint8_t action;
+ uint8_t options;
+ pid_t child;
+
+ f_thread_id_t id_thread;
f_thread_lock_t lock;
f_thread_lock_t active;
- f_thread_lock_attribute_t lock_attribute;
- f_thread_lock_attribute_t active_attribute;
+ f_thread_mutex_t running;
+ f_thread_condition_t wait;
+
+ controller_cache_t cache;
+ f_array_lengths_t stack;
+
+ void *main_data;
+ void *main_setting;
+ void *main_thread;
} controller_process_t;
#define controller_process_t_initialize { \
+ 0, \
f_string_dynamic_t_initialize \
F_known_not, \
+ 0, \
+ 0, \
+ 0, \
+ 0, \
+ f_thread_id_t_initialize, \
f_thread_lock_t_initialize, \
f_thread_lock_t_initialize, \
- f_thread_lock_attribute_t_initialize, \
- f_thread_lock_attribute_t_initialize, \
+ f_thread_condition_t_initialize, \
+ controller_cache_t_initialize, \
+ f_array_lengths_t_initialize, \
+ 0, \
+ 0, \
+ 0, \
}
#endif // _di_controller_process_t_
0, \
0, \
}
-
- #define controller_macro_processs_t_clear(process) \
- process.array = 0; \
- process.size = 0; \
- process.used = 0;
#endif // _di_controller_processs_t_
/**
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_
/**
0, \
0, \
}
-
- #define controller_macro_entry_actions_t_clear(actions) \
- actions.array = 0; \
- actions.size = 0; \
- actions.used = 0;
#endif // _di_controller_entry_actions_t_
/**
f_string_dynamic_t_initialize, \
controller_entry_actions_t_initialize, \
}
-
- #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_
/**
F_known_not, \
controller_entry_items_t_initialize, \
}
-
- #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_
/**
controller_entry_t_initialize, \
controller_rules_t_initialize, \
}
-
- #define controller_macro_setting_t_clear(setting) \
- setting.interruptable = F_false; \
- setting.ready = 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
/**
- * Action related cache.
- *
- * line_action: The line in some file representing an Action.
- * line_item: The line in some file representing an Item.
- * name_action: A NULL terminated name of some Action.
- * name_file: A NULL terminated name of some File.
- * name_item: A NULL terminated name of some Item.
- * generic: A NULL terminated string for general use.
- */
-#ifndef _di_controller_cache_action_t_
- typedef struct {
- f_array_length_t line_action;
- f_array_length_t line_item;
-
- f_string_dynamic_t name_action;
- f_string_dynamic_t name_file;
- f_string_dynamic_t name_item;
-
- 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_macro_cache_action_t_clear(cache) \
- cache.line_action = 0; \
- cache.line_item = 0; \
- 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_
-
-/**
- * A cache intended for re-using memory while loading and processing rules whenever possible.
- *
- * timestamp: The timestamp.
- * range_action: The Range for some Action.
- * ats: Locations.
- * stack: Locations within a items history used as a history stack for circular recursion prevention.
- * comments: Comments associated with a buffer string.
- * delimits: Delimits associated with a buffer string.
- * content_action: The specific Content for some Action.
- * content_actions: Content for some Action.
- * content_items: Content for some Item.
- * object_actions: Objects for some Action.
- * object_items: Objects for some Item.
- * buffer_file: A generic file related buffer.
- * buffer_item: A generic item related buffer.
- * buffer_path: A generic path related buffer.
- * action: A cache for some Action, often used by error printing for reporting where an error happened.
- */
-#ifndef _di_controller_cache_t_
- typedef struct {
- f_time_spec_t timestamp;
-
- f_string_range_t range_action;
-
- f_array_lengths_t ats;
- f_array_lengths_t stack;
-
- f_fss_comments_t comments;
- f_fss_delimits_t delimits;
-
- f_fss_content_t content_action;
- f_fss_contents_t content_actions;
- f_fss_contents_t content_items;
- f_fss_objects_t object_actions;
- f_fss_objects_t object_items;
-
- f_string_dynamic_t buffer_file;
- f_string_dynamic_t buffer_item;
- f_string_dynamic_t buffer_path;
-
- 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, \
- }
-#endif // _di_controller_cache_t_
-
-/**
- * Stores data passed to a thread on thread creation, specifically for rule processing.
- *
- * The thread has different states:
- * - active: The thread is running.
- * - done: The thread has finished executed but has not been cleaned up.
- * - joined: The thread has been cleaned up, this is safe to delete.
- *
- * id: The thread id, which is controlled by pthread functions.
- * id_process: The id representing the rule process this asynchronous thread operates for.
- * state: The state of the asynchronous.
- * action: The action being performed.
- * options: Configuration options for this asynchronous thread.
- * child: The process id of a child process, if one is running (when forking to execute a child process).
- * stack: The execution stack representing all other rule processes (by process id) that called this (to prevent infinite recursion). // @todo is this needed here anymore?
- * cache: A per asynchronous thread cache.
- */
-#ifndef _di_controller_asynchronous_t_
- enum {
- controller_asynchronous_state_active = 1,
- controller_asynchronous_state_done,
- controller_asynchronous_state_joined,
- };
-
- typedef struct {
- f_thread_id_t id;
- f_array_length_t id_process;
-
- uint8_t state;
- uint8_t action;
- uint8_t options;
- pid_t child;
-
- f_array_lengths_t stack;
- controller_cache_t cache;
- } controller_asynchronous_t;
-
- #define controller_asynchronous_t_initialize { \
- f_thread_id_t_initialize, \
- 0, \
- 0, \
- 0, \
- 0, \
- 0, \
- f_array_lengths_t_initialize, \
- controller_cache_t_initialize \
- }
-#endif // _di_controller_asynchronous_t_
-
-/**
- * The asynchronous execution data.
- *
- * array: An array of asynchronous execution data.
- * size: Total amount of allocated space.
- * used: Total number of allocated spaces used.
- */
-#ifndef _di_controller_asynchronouss_t_
- typedef struct {
- controller_asynchronous_t *array;
-
- f_array_length_t size;
- f_array_length_t used;
- } controller_asynchronouss_t;
-
- #define controller_asynchronouss_t_initialize { \
- 0, \
- 0, \
- 0, \
- }
-
- #define controller_macro_asynchronouss_t_clear(asynchronouss) \
- asynchronouss.array = 0; \
- asynchronouss.size = 0; \
- asynchronouss.used = 0;
-#endif // _di_controller_asynchronouss_t_
-
-/**
* A structure for managing threads.
*
* This is essentially data shared globally between threads, about threads.
*
- * As a special case, index 0 of asynchronouss is reserved for use the main thread and is not used by any Rule Processes.
+ * As a special case, index 0 of processs is reserved for use the main thread and is not used by any Rule Processes.
*
- * enabled: TRUE when threads are active, FALSE when inactive and the program is essentially shutting down, no new threads should be started when FALSE.
- * signal: The code of any signal received.
- * id_cleanup: The thread ID representing the cleanup Process.
- * id_control: The thread ID representing the cleanup Process.
- * id_rule: The thread ID representing the cleanup Process.
- * id_signal: The thread ID representing the cleanup Process.
- * lock: A r/w lock for operating on this structure.
- * asynchronouss: All Rule Process thread data.
+ * The "enabled" and "signal" utilize the lock: lock.process.
+ *
+ * enabled: TRUE when threads are active, FALSE when inactive and the program is essentially shutting down, no new threads should be started when FALSE.
+ * signal: The code of any signal received.
+ * id_cleanup: The thread ID representing the Cleanup Process.
+ * id_control: The thread ID representing the Control Process.
+ * id_signal: The thread ID representing the Signal Process.
+ * lock: A r/w lock for operating on this structure.
+ * processs: All Rule Process thread data.
*/
#ifndef _di_controller_thread_t_
typedef struct {
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_lock_t lock;
- controller_asynchronouss_t asynchronouss;
+ controller_processs_t processs;
} controller_thread_t;
#define controller_thread_t_initialize { \
f_thread_id_t_initialize, \
f_thread_id_t_initialize, \
f_thread_id_t_initialize, \
- f_thread_id_t_initialize, \
controller_lock_t_initialize, \
- controller_asynchronouss_t_initialize \
+ controller_processs_t_initialize, \
}
-
- #define controller_macro_thread_t_initialize(lock, asynchronouss) { \
- F_true, \
- 0, \
- f_thread_id_t_initialize, \
- f_thread_id_t_initialize, \
- f_thread_id_t_initialize, \
- f_thread_id_t_initialize. \
- lock, \
- asynchronouss \
- }
-
- #define controller_macro_thread_t_clear(thread) \
- thread.enabled = F_true; \
- thread.signal = 0; \
- 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_asynchronouss_t_clear(thread.asynchronouss)
#endif // _di_controller_data_common_t_
/**
- * A wrapper used for passing all data to each individual asynchronous thread.
+ * A wrapper used for passing a common set of all data, particularly for sharing between threads.
*
- * id_process: The index in the processs array representing the current process.
- * data: All standard program data.
- * setting: All loaded settings.
- * processs: All Rule Process data.
- * thread: All thread related data.
+ * data: All standard program data.
+ * setting: All loaded settings.
+ * processs: All Rule Process data.
+ * thread: All thread related data.
*/
-#ifndef _di_controller_thread_data_t_
+#ifndef _di_controller_main_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.
-
- // @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_thread_cache_cleanup_interval_long 3600 // 1 hour in seconds.
+ #define controller_thread_cache_cleanup_interval_short 180 // 3 minutes in seconds.
typedef struct {
- f_array_length_t id_process;
-
controller_data_t *data;
controller_setting_t *setting;
- controller_processs_t *processs;
controller_thread_t *thread;
- } controller_thread_data_t;
+ } controller_main_t;
- #define controller_thread_data_t_initialize { 0, 0, 0, 0, 0 }
+ #define controller_main_t_initialize { 0, 0, 0 }
- #define controller_macro_thread_data_t_initialize(id_process, data, setting, processs, thread) { \
- id_process, \
+ #define controller_macro_main_t_initialize(data, setting, thread) { \
data, \
setting, \
- processs, \
- thread \
+ thread, \
}
-
- #define controller_macro_thread_data_t_clear(thread_data) \
- thread_data.id_process = 0; \
- thread_data.data = 0; \
- thread_data.setting = 0; \
- thread_data.processs = 0; \
- thread_data.thread = 0;
-#endif // _di_controller_thread_data_t_
-
-/**
- * Fully deallocate all memory for the given asynchronous without caring about return status.
- *
- * @param asynchronous
- * The asynchronous to deallocate.
- *
- * @see f_macro_array_lengths_t_delete_simple()
- *
- * @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 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.
- *
- * @param asynchronouss
- * The asynchronous 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_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 asynchronous array.
- *
- * @param length
- * The new size to use.
- * @param asynchronouss
- * The asynchronous 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_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_
+#endif // _di_controller_main_t_
/**
* Fully deallocate all memory for the given cache without caring about return status.
#endif // _di_controller_error_print_
/**
+ * Perform the initial, required, allocation for the lock.
+ *
+ * @param lock
+ * The lock to allocate.
+ *
+ * @return
+ * F_none on success.
+ *
+ * Errors (with error bit) from f_thread_lock_delete().
+ * Errors (with error bit) from f_thread_mutex_delete().
+ *
+ * @see f_thread_lock_delete()
+ * @see f_thread_mutex_delete()
+ */
+#ifndef _di_controller_lock_create_
+ extern f_status_t controller_lock_create(controller_lock_t *lock) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_lock_create_
+
+/**
+ * Fully deallocate all memory for the given lock without caring about return status.
+ *
+ * @param lock
+ * The lock to deallocate.
+ *
+ * @see f_thread_lock_delete()
+ * @see f_thread_mutex_delete()
+ */
+#ifndef _di_controller_lock_delete_simple_
+ extern void controller_lock_delete_simple(controller_lock_t *lock) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_lock_delete_simple_
+
+/**
* Fully deallocate all memory for the given process without caring about return status.
*
+ * This does not close/cancel the id_thread.
+ * Be sure to properly close and/or detach the thread.
+ *
* @param process
* The process to deallocate.
*
/**
* Fully deallocate all memory for the given processs without caring about return status.
*
+ * This does not close/cancel the id_thread for any process.
+ * Be sure to properly close and/or detach the thread for each process.
+ *
* @param processs
* The process array to deallocate.
*
* @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.
+ * Errors (with error bit) from: controller_process_delete_simple().
+ * Errors (with error bit) from: f_memory_resize().
+ * Errors (with error bit) from: f_thread_condition_create().
+ * Errors (with error bit) from: f_thread_lock_create().
*
+ * @see controller_process_delete_simple()
* @see f_memory_resize()
+ * @see f_thread_condition_create()
+ * @see f_thread_lock_create()
*/
#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_string_dynamic_partial_append_terminated_
#ifndef _di_controller_file_load_
- 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 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_main_t main, controller_cache_t *cache) {
f_status_t status = F_none;
f_file_t file = f_file_t_initialize;
}
if (F_status_is_error(status)) {
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_append", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "f_string_append", F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
return status;
status = f_string_dynamic_terminate_after(&cache->action.name_file);
if (F_status_is_error(status)) {
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
return status;
}
- 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;
+ const f_array_length_t path_length = main.setting->path_setting.used ? main.setting->path_setting.used + f_path_separator_length + cache->action.name_file.used : cache->action.name_file.used;
char path[path_length + 1];
- 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);
+ if (main.setting->path_setting.used) {
+ memcpy(path, main.setting->path_setting.string, main.setting->path_setting.used);
+ memcpy(path + main.setting->path_setting.used + f_path_separator_length, cache->action.name_file.string, cache->action.name_file.used);
- path[thread_data.setting->path_setting.used] = f_path_separator_s[0];
+ path[main.setting->path_setting.used] = f_path_separator_s[0];
}
path[path_length] = 0;
status = f_file_stream_open(path, 0, &file);
if (F_status_is_error(status)) {
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fll_error_file_print(main.data->error, F_status_set_fine(status), "f_file_stream_open", F_true, path, "open", fll_error_file_type_file);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
}
else {
status = f_file_stream_read(file, 1, &cache->buffer_file);
if (F_status_is_error(status)) {
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fll_error_file_print(main.data->error, F_status_set_fine(status), "f_file_stream_read", F_true, path, "read", fll_error_file_type_file);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
}
}
status = f_file_stat(path, F_true, &stat_file);
if (F_status_is_error(status)) {
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fll_error_file_print(main.data->error, F_status_set_fine(status), "f_file_stat", F_true, path, "stat", fll_error_file_type_file);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
}
else {
#endif // _di_controller_file_pid_delete_
#ifndef _di_controller_find_process_
- f_status_t controller_find_process(const f_string_static_t id, const controller_processs_t processs, f_array_length_t *at) {
+ f_status_t controller_find_process(const f_string_static_t alias, const controller_processs_t processs, f_array_length_t *at) {
- if (!id.used) return F_none;
+ if (!alias.used) return F_none;
if (!processs.used) return F_false;
for (f_array_length_t i = 0; i < processs.used; ++i) {
- if (fl_string_dynamic_compare(id, processs.array[i].id_rule) == F_equal_to) {
+ if (fl_string_dynamic_compare(alias, processs.array[i].alias_rule) == F_equal_to) {
*at = i;
return F_true;
}
#endif // _di_controller_get_id_group_
#ifndef _di_controller_perform_ready_
- f_status_t controller_perform_ready(controller_thread_data_t thread_data, controller_cache_t *cache) {
+ f_status_t controller_perform_ready(controller_main_t main, controller_cache_t *cache) {
f_status_t status = F_none;
// only create pid file when not in validate mode.
- if (thread_data.data->parameters[controller_parameter_validate].result == f_console_result_none) {
+ if (main.data->parameters[controller_parameter_validate].result == f_console_result_none) {
- status = controller_file_pid_create(*thread_data.data, thread_data.setting->path_pid);
+ status = controller_file_pid_create(*main.data, main.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) {
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fll_error_file_print(main.data->error, F_status_set_fine(status), "controller_file_pid_create", F_true, main.setting->path_pid.string, "create", fll_error_file_type_file);
- controller_entry_error_print_cache(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(main.data->error, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
return status;
}
- if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->warning.verbosity == f_console_verbosity_debug) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fll_error_file_print(main.data->warning, F_status_set_fine(status), "controller_file_pid_create", F_true, main.setting->path_pid.string, "create", fll_error_file_type_file);
- controller_entry_error_print_cache(thread_data.data->warning, cache->action);
+ controller_entry_error_print_cache(main.data->warning, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
status = F_none;
#endif // _di_controller_perform_ready_
#ifndef _di_controller_preprocess_entry_
- f_status_t controller_preprocess_entry(controller_thread_data_t thread_data, controller_cache_t *cache) {
+ f_status_t controller_preprocess_entry(controller_main_t main, controller_cache_t *cache) {
f_status_t status = F_none;
f_status_t status2 = F_none;
uint8_t error_has = F_false;
- thread_data.setting->ready = controller_setting_ready_no;
+ main.setting->ready = controller_setting_ready_no;
cache->ats.used = 0;
f_macro_array_lengths_t_increase_by(status, cache->ats, controller_default_allocation_step)
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true, thread_data.thread);
+ controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true, main.thread);
return status;
}
cache->ats.array[1] = 0;
cache->ats.used = 2;
- cache->action.line_item = thread_data.setting->entry.items.array[0].line;
+ cache->action.line_item = main.setting->entry.items.array[0].line;
cache->action.name_item.used = 0;
- status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[0].name, &cache->action.name_item);
+ status = controller_string_dynamic_append_terminated(main.setting->entry.items.array[0].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, thread_data.thread);
+ controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main.thread);
return status;
}
for (;;) {
- actions = &thread_data.setting->entry.items.array[cache->ats.array[at_i]].actions;
+ actions = &main.setting->entry.items.array[cache->ats.array[at_i]].actions;
for (; cache->ats.array[at_j] < actions->used; ++cache->ats.array[at_j]) {
- if (thread_data.thread->signal) {
+ if (main.thread->signal) {
return F_signal;
}
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)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true, thread_data.thread);
+ controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true, main.thread);
return status2;
}
if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_ready) {
- if (thread_data.setting->ready == controller_setting_ready_wait) {
- if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.setting->ready == controller_setting_ready_wait) {
+ if (main.data->warning.verbosity == f_console_verbosity_debug) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->warning.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->warning.to.stream, "%s%sMultiple '", main.data->warning.context.before->string, main.data->warning.prefix ? main.data->warning.prefix : f_string_empty_s);
+ fprintf(main.data->warning.to.stream, "%s%s%s%s", main.data->warning.context.after->string, main.data->warning.notable.before->string, controller_string_ready_s, main.data->warning.notable.after->string);
+ fprintf(main.data->warning.to.stream, "%s' entry item actions detected; only the first will be used.%s%c", main.data->warning.context.before->string, main.data->warning.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print_cache(thread_data.data->warning, cache->action);
+ controller_entry_error_print_cache(main.data->warning, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
}
// the pre-process currently only looks for "ready", so once found, pre-process is complete.
- thread_data.setting->ready = controller_setting_ready_wait;
+ main.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;
}
// walk though each items and check to see if the item actually exists (skipping main).
- for (i = 1; i < thread_data.setting->entry.items.used; ++i) {
+ for (i = 1; i < main.setting->entry.items.used; ++i) {
- 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) {
+ if (fl_string_dynamic_compare(main.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 (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe entry item named '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, main.setting->entry.items.array[i].name.string, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s' cannot be executed because recursion is not allowed.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print_cache(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(main.data->error, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
if (F_status_is_error_not(status)) {
f_macro_array_lengths_t_increase_by(status2, cache->ats, controller_default_allocation_step)
if (F_status_is_error(status2)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status2), "f_macro_array_lengths_t_increase_by", F_true, thread_data.thread);
+ controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status2), "f_macro_array_lengths_t_increase_by", F_true, main.thread);
return status2;
}
cache->action.line_action = 0;
cache->action.name_item.used = 0;
- cache->action.line_item = thread_data.setting->entry.items.array[i].line;
+ cache->action.line_item = main.setting->entry.items.array[i].line;
- status2 = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[i].name, &cache->action.name_item);
+ status2 = controller_string_dynamic_append_terminated(main.setting->entry.items.array[i].name, &cache->action.name_item);
if (F_status_is_error(status2)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true, thread_data.thread);
+ controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true, main.thread);
return status2;
}
}
} // for
- 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) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (error_has || i >= main.setting->entry.items.used) {
+ if (i >= main.setting->entry.items.used) {
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe entry item named '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, actions->array[cache->ats.array[at_j]].parameters.array[0].string, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s' does not exist.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print_cache(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(main.data->error, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
if (F_status_is_error_not(status)) {
cache->ats.used -= 2;
cache->ats.array[at_j]++;
- cache->action.line_item = thread_data.setting->entry.items.array[cache->ats.array[at_i]].line;
+ cache->action.line_item = main.setting->entry.items.array[cache->ats.array[at_i]].line;
cache->action.name_item.used = 0;
- status2 = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
+ status2 = controller_string_dynamic_append_terminated(main.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
if (F_status_is_error(status2)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true, thread_data.thread);
+ controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true, main.thread);
return status2;
}
} // for
// if ready was never found in the entry, then default to always ready.
- if (thread_data.setting->ready == controller_setting_ready_no) {
- thread_data.setting->ready = controller_setting_ready_yes;
+ if (main.setting->ready == controller_setting_ready_no) {
+ main.setting->ready = controller_setting_ready_yes;
}
return status;
#endif // _di_controller_preprocess_entry_
#ifndef _di_controller_process_entry_
- f_status_t controller_process_entry(controller_thread_data_t thread_data, controller_cache_t *cache) {
+ f_status_t controller_process_entry(controller_main_t main, controller_cache_t *cache) {
f_status_t status = F_none;
f_array_length_t i = 0;
controller_entry_actions_t *entry_actions = 0;
controller_process_t *process = 0;
- const bool simulate = thread_data.data->parameters[controller_parameter_test].result == f_console_result_found;
+ // an empty stack is used here because each rule here is the first rule run in the rule's scope.
+ const f_array_lengths_t stack = f_array_lengths_t_initialize;
+
+ const bool simulate = main.data->parameters[controller_parameter_test].result == f_console_result_found;
cache->ats.used = 0;
cache->stack.used = 0;
cache->action.name_action.used = 0;
cache->action.name_item.used = 0;
- if (thread_data.setting->ready == controller_setting_ready_yes) {
- status = controller_perform_ready(thread_data, cache);
+ if (main.setting->ready == controller_setting_ready_yes) {
+ status = controller_perform_ready(main, 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)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true, thread_data.thread);
+ controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true, main.thread);
return status;
}
cache->ats.array[1] = 0;
cache->ats.used = 2;
- cache->action.line_item = thread_data.setting->entry.items.array[0].line;
+ cache->action.line_item = main.setting->entry.items.array[0].line;
cache->action.name_item.used = 0;
- status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[0].name, &cache->action.name_item);
+ status = controller_string_dynamic_append_terminated(main.setting->entry.items.array[0].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, thread_data.thread);
+ controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main.thread);
return status;
}
if (simulate) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "Processing entry item rule '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, controller_string_main_s, main.data->context.set.title.after->string);
+ fprintf(main.data->output.stream, "'.%c", f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
- // @todo this function should maintain a read lock on "thread_data.thread->lock.rule", but it must immediately release the read lock before it can do a write lock (which is unfortunate).
- // I would much rather gain the write lock and then release the read lock, but that is likely not possible.
+ f_thread_lock_read(&main.thread->lock.entry);
+
for (;;) {
- entry_actions = &thread_data.setting->entry.items.array[cache->ats.array[at_i]].actions;
+ entry_actions = &main.setting->entry.items.array[cache->ats.array[at_i]].actions;
for (; cache->ats.array[at_j] < entry_actions->used; ++cache->ats.array[at_j]) {
- if (thread_data.thread->signal) {
+ if (main.thread->signal) {
status = F_signal;
break;
}
status = controller_string_dynamic_append_terminated(controller_entry_action_type_name(entry_action->type), &cache->action.name_action);
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, thread_data.thread);
+ controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main.thread);
+
+ f_thread_unlock(&main.thread->lock.entry);
return status;
}
if (entry_action->type == controller_entry_action_type_rule) {
if (simulate) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "The entry item action '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, cache->action.name_action.string, main.data->context.set.title.after->string);
if (entry_action->parameters.used) {
- 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, entry_actions->array[cache->ats.array[at_j]]);
- fprintf(thread_data.data->output.stream, "%s", thread_data.data->context.set.notable.after->string);
+ fprintf(main.data->output.stream, f_string_space_s);
+ fprintf(main.data->output.stream, "%s", main.data->context.set.notable.before->string);
+ controller_entry_action_parameters_print(main.data->output.stream, entry_actions->array[cache->ats.array[at_j]]);
+ fprintf(main.data->output.stream, "%s", main.data->context.set.notable.after->string);
}
- fprintf(thread_data.data->output.stream, "' is %s and is in a %sfailed%s state, skipping execution.%c", entry_action->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]);
+ fprintf(main.data->output.stream, "' is %s and is in a %sfailed%s state, skipping execution.%c", entry_action->code & controller_entry_rule_code_require ? "required" : "optional", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
else if (entry_action->code & controller_entry_rule_code_require) {
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe entry item action '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, cache->action.name_action.string);
if (entry_action->parameters.used) {
- fprintf(thread_data.data->error.to.stream, f_string_space_s);
- controller_entry_action_parameters_print(thread_data.data->error.to.stream, entry_actions->array[cache->ats.array[at_j]]);
+ fprintf(main.data->error.to.stream, f_string_space_s);
+ controller_entry_action_parameters_print(main.data->error.to.stream, entry_actions->array[cache->ats.array[at_j]]);
}
- 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]);
+ fprintf(main.data->error.to.stream, "%s%s' is ", main.data->error.notable.after->string, main.data->error.context.before->string);
+ fprintf(main.data->error.to.stream, "%s%srequired%s", main.data->error.context.after->string, main.data->error.notable.before->string, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s and is in a ", main.data->error.context.before->string);
+ fprintf(main.data->error.to.stream, "%s%sfailed%s", main.data->error.context.after->string, main.data->error.notable.before->string, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s state, skipping execution.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print_cache(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(main.data->error, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
+ f_thread_unlock(&main.thread->lock.entry);
+
return F_status_is_error(F_require);
}
- else if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ else if (main.data->warning.verbosity == f_console_verbosity_debug) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fprintf(main.data->warning.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->warning.to.stream, "%s%sThe entry item action '", main.data->warning.context.before->string, main.data->warning.prefix ? main.data->warning.prefix : f_string_empty_s);
+ fprintf(main.data->warning.to.stream, "%s%s%s", main.data->warning.context.after->string, main.data->warning.notable.before->string, cache->action.name_action.string);
if (entry_action->parameters.used) {
- fprintf(thread_data.data->warning.to.stream, f_string_space_s);
- controller_entry_action_parameters_print(thread_data.data->warning.to.stream, entry_actions->array[cache->ats.array[at_j]]);
+ fprintf(main.data->warning.to.stream, f_string_space_s);
+ controller_entry_action_parameters_print(main.data->warning.to.stream, entry_actions->array[cache->ats.array[at_j]]);
}
- 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]);
+ fprintf(main.data->warning.to.stream, "%s%s' is ", main.data->warning.notable.after->string, main.data->warning.context.before->string);
+ fprintf(main.data->warning.to.stream, "%s%srequired%s", main.data->warning.context.after->string, main.data->warning.notable.before->string, main.data->warning.notable.after->string);
+ fprintf(main.data->warning.to.stream, "%s and is in a ", main.data->warning.context.before->string);
+ fprintf(main.data->warning.to.stream, "%s%sfailed%s", main.data->warning.context.after->string, main.data->warning.notable.before->string, main.data->warning.notable.after->string);
+ fprintf(main.data->warning.to.stream, "%s state, skipping execution.%s%c", main.data->warning.context.before->string, main.data->warning.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print_cache(thread_data.data->warning, cache->action);
+ controller_entry_error_print_cache(main.data->warning, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
}
else {
if (simulate) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "The entry item action '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, cache->action.name_action.string, main.data->context.set.title.after->string);
if (entry_action->parameters.used) {
- 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, entry_actions->array[cache->ats.array[at_j]]);
- fprintf(thread_data.data->output.stream, "%s", thread_data.data->context.set.notable.after->string);
+ fprintf(main.data->output.stream, f_string_space_s);
+ fprintf(main.data->output.stream, "%s", main.data->context.set.notable.before->string);
+ controller_entry_action_parameters_print(main.data->output.stream, entry_actions->array[cache->ats.array[at_j]]);
+ fprintf(main.data->output.stream, "%s", main.data->context.set.notable.after->string);
}
- 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]);
+ fprintf(main.data->output.stream, "' is in a %sfailed%s state, skipping.%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
- else if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ else if (main.data->warning.verbosity == f_console_verbosity_debug) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fprintf(main.data->warning.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->warning.to.stream, "%s%sThe entry item action '", main.data->warning.context.before->string, main.data->warning.prefix ? main.data->warning.prefix : f_string_empty_s);
+ fprintf(main.data->warning.to.stream, "%s%s", main.data->warning.notable.before->string, cache->action.name_action.string);
if (entry_action->parameters.used) {
- fprintf(thread_data.data->warning.to.stream, f_string_space_s);
- controller_entry_action_parameters_print(thread_data.data->warning.to.stream, entry_actions->array[cache->ats.array[at_j]]);
+ fprintf(main.data->warning.to.stream, f_string_space_s);
+ controller_entry_action_parameters_print(main.data->warning.to.stream, entry_actions->array[cache->ats.array[at_j]]);
}
- 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]);
+ fprintf(main.data->warning.to.stream, "%s' is in a ", main.data->warning.notable.after->string);
+ fprintf(main.data->warning.to.stream, "%s%sfailed%s", main.data->warning.context.after->string, main.data->warning.notable.before->string, main.data->warning.notable.after->string);
+ fprintf(main.data->warning.to.stream, "%s state, skipping.%s%c", main.data->warning.context.before->string, main.data->warning.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print_cache(thread_data.data->warning, cache->action);
+ controller_entry_error_print_cache(main.data->warning, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
}
if (entry_action->type == controller_entry_action_type_ready) {
- if (thread_data.setting->ready == controller_setting_ready_wait) {
+ if (main.setting->ready == controller_setting_ready_wait) {
if (simulate) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "Processing entry item action '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, controller_string_ready_s, main.data->context.set.title.after->string);
+ fprintf(main.data->output.stream, "'.%c", f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
else {
- controller_perform_ready(thread_data, cache);
- if (F_status_is_error(status)) return status;
+ controller_perform_ready(main, cache);
+
+ if (F_status_is_error(status)) {
+ f_thread_unlock(&main.thread->lock.entry);
+
+ return status;
+ }
}
- thread_data.setting->ready = controller_setting_ready_yes;
+ main.setting->ready = controller_setting_ready_yes;
}
else if (simulate) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "Ignoring entry item action '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, controller_string_ready_s, main.data->context.set.title.after->string);
+ fprintf(main.data->output.stream, "', state already is ready.%c", f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
}
else if (entry_action->type == controller_entry_action_type_item) {
- if (entry_action->number == 0 || entry_action->number >= thread_data.setting->entry.items.used) {
+ if (entry_action->number == 0 || entry_action->number >= main.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 (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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, entry_action->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]);
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sInvalid entry item index ", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%llu%s", main.data->error.context.after->string, main.data->error.notable.before->string, entry_action->number, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s detected.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print_cache(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(main.data->error, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
+ f_thread_unlock(&main.thread->lock.entry);
+
return F_status_is_error(F_critical);
}
f_macro_array_lengths_t_increase_by(status, cache->ats, controller_default_allocation_step)
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true, thread_data.thread);
+ controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true, main.thread);
+
+ f_thread_unlock(&main.thread->lock.entry);
return status;
}
cache->action.line_action = 0;
cache->action.name_item.used = 0;
- cache->action.line_item = thread_data.setting->entry.items.array[cache->ats.array[at_i]].line;
+ cache->action.line_item = main.setting->entry.items.array[cache->ats.array[at_i]].line;
- status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
+ status = controller_string_dynamic_append_terminated(main.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, thread_data.thread);
+ controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main.thread);
+
+ f_thread_unlock(&main.thread->lock.entry);
return status;
}
if (simulate) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "Processing entry item '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, cache->action.name_item.string, main.data->context.set.title.after->string);
+ fprintf(main.data->output.stream, "'.%c", f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
// exit inner loop to force restarting and start processing the requested item.
}
else if (entry_action->type == controller_entry_action_type_consider || entry_action->type == controller_entry_action_type_rule) {
- status = controller_rules_increase(&thread_data.setting->rules);
+ f_thread_lock_write(&main.thread->lock.rule);
+
+ status = controller_rules_increase(&main.setting->rules);
+
+ f_thread_unlock(&main.thread->lock.rule);
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "controller_rules_increase", F_true, thread_data.thread);
+ controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "controller_rules_increase", F_true, main.thread);
+
+ f_thread_unlock(&main.thread->lock.entry);
return status;
}
const f_array_length_t id_rule_length = entry_action->parameters.array[0].used + entry_action->parameters.array[1].used + 1;
char id_rule_name[id_rule_length + 1];
- const f_string_static_t id_rule = f_macro_string_static_t_initialize(id_rule_name, id_rule_length);
+ const f_string_static_t alias_rule = f_macro_string_static_t_initialize(id_rule_name, id_rule_length);
memcpy(id_rule_name, entry_action->parameters.array[0].string, entry_action->parameters.array[0].used);
memcpy(id_rule_name + entry_action->parameters.array[0].used + 1, entry_action->parameters.array[1].string, entry_action->parameters.array[1].used);
id_rule_name[entry_action->parameters.array[0].used] = f_path_separator_s[0];
id_rule_name[id_rule_length] = 0;
- f_thread_lock_read(&thread_data.thread->lock.rule);
+ f_thread_lock_read(&main.thread->lock.rule);
- at = controller_rule_find_loaded(id_rule, thread_data);
+ at = controller_rule_find_loaded(alias_rule, main);
if (simulate) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]);
- fprintf(thread_data.data->output.stream, "%s entry item rule '", entry_action->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, id_rule.string, thread_data.data->context.set.title.after->string);
- fprintf(thread_data.data->output.stream, "'.%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "%s entry item rule '", entry_action->type == controller_entry_action_type_rule ? "Processing" : "Considering");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, alias_rule.string, main.data->context.set.title.after->string);
+ fprintf(main.data->output.stream, "'.%c", f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
// the rule is not yet loaded, ensure that it is loaded.
- if (at == thread_data.setting->rules.used) {
+ if (at == main.setting->rules.used) {
- f_thread_unlock(&thread_data.thread->lock.rule);
+ f_thread_unlock(&main.thread->lock.rule);
// rule execution will re-use the existing cache, so save the current cache.
const f_array_length_t cache_line_action = cache->action.line_action;
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);
- f_thread_lock_write(&thread_data.thread->lock.rule);
+ f_thread_lock_write(&main.thread->lock.rule);
- status = controller_rule_read(id_rule, thread_data, cache, &thread_data.setting->rules.array[thread_data.setting->rules.used]);
+ status = controller_rule_read(alias_rule, main, cache, &main.setting->rules.array[main.setting->rules.used]);
// restore cache.
memcpy(cache->action.name_action.string, cache_name_action, cache_name_action_used);
if (F_status_is_error(status)) {
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- controller_entry_error_print_cache(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(main.data->error, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
if (!simulate) {
- f_thread_unlock(&thread_data.thread->lock.rule);
+ f_thread_unlock(&main.thread->lock.rule);
break;
}
}
else {
- thread_data.setting->rules.used++;
+ main.setting->rules.used++;
}
- f_thread_unlock(&thread_data.thread->lock.rule);
+ f_thread_unlock(&main.thread->lock.rule);
+ }
+ else {
+ f_thread_unlock(&main.thread->lock.rule);
}
if (F_status_is_error_not(status) && entry_action->type == controller_entry_action_type_rule) {
-
- // rule execution will re-use the existing cache, so save the current cache.
- 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_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, 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);
-
rule_options = 0;
if (simulate) {
if (entry_action->code & controller_entry_rule_code_asynchronous) {
rule_options |= controller_rule_option_asynchronous;
-
- // @todo
- //status = controller_rule_process_asynchronous(id_rule, controller_rule_action_type_start, rule_options, thread_data, cache);
}
- else {
- // @todo
- // status = controller_rule_process(id_rule, controller_rule_action_type_start, rule_options, thread_data, cache);
- }
-
- // restore cache.
- 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);
- 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;
-
- 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;
-
- cache->action.line_action = cache_line_action;
- cache->action.line_item = cache_line_item;
+ status = controller_rule_process_begin(entry_action->code & controller_entry_rule_code_asynchronous, alias_rule, controller_rule_action_type_start, rule_options, stack, main, cache);
if (!simulate || F_status_set_fine(status) == F_memory_not || status == F_child || status == F_signal) {
break;
code = controller_string_stop_s;
}
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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, entry_action->number, thread_data.data->context.set.important.after->string);
- fprintf(thread_data.data->output.stream, "' MegaTime (milliseconds).%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "Processing entry item action '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, controller_string_timeout_s, main.data->context.set.title.after->string);
+ fprintf(main.data->output.stream, "' setting '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.important.before->string, code, main.data->context.set.important.after->string);
+ fprintf(main.data->output.stream, "' to '");
+ fprintf(main.data->output.stream, "%s%llu%s", main.data->context.set.important.before->string, entry_action->number, main.data->context.set.important.after->string);
+ fprintf(main.data->output.stream, "' MegaTime (milliseconds).%c", f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
if (entry_action->code == controller_entry_timeout_code_kill) {
- thread_data.setting->timeout_kill = entry_action->number;
+ main.setting->timeout_kill = entry_action->number;
}
else if (entry_action->code == controller_entry_timeout_code_start) {
- thread_data.setting->timeout_start = entry_action->number;
+ main.setting->timeout_start = entry_action->number;
}
else if (entry_action->code == controller_entry_timeout_code_stop) {
- thread_data.setting->timeout_stop = entry_action->number;
+ main.setting->timeout_stop = entry_action->number;
}
}
else if (entry_action->type == controller_entry_action_type_failsafe) {
- if (entry_action->number == 0 || entry_action->number >= thread_data.setting->entry.items.used) {
+ if (entry_action->number == 0 || entry_action->number >= main.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 (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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, entry_action->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]);
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sInvalid entry item index ", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%llu%s", main.data->error.context.after->string, main.data->error.notable.before->string, entry_action->number, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s detected.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print_cache(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(main.data->error, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
+ f_thread_unlock(&main.thread->lock.entry);
+
return F_status_is_error(F_critical);
}
else {
- thread_data.setting->failsafe_enabled = F_true;
- thread_data.setting->failsafe_rule_id = entry_action->number;
+ main.setting->failsafe_enabled = F_true;
+ main.setting->failsafe_rule_id = entry_action->number;
if (simulate) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "Processing entry item action '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, controller_string_failsafe_s, main.data->context.set.title.after->string);
+ fprintf(main.data->output.stream, "' setting value to '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.important.before->string, main.setting->entry.items.array[main.setting->failsafe_rule_id].name.string, main.data->context.set.important.after->string);
+ fprintf(main.data->output.stream, "'.%c", f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
}
}
} // for
- if (thread_data.thread->signal) {
+ if (main.thread->signal) {
status = F_signal;
}
cache->ats.used -= 2;
cache->ats.array[at_j]++;
- cache->action.line_item = thread_data.setting->entry.items.array[cache->ats.array[at_i]].line;
+ cache->action.line_item = main.setting->entry.items.array[cache->ats.array[at_i]].line;
cache->action.name_item.used = 0;
- status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
+ status = controller_string_dynamic_append_terminated(main.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, thread_data.thread);
+ controller_entry_error_print(main.data->error, cache->action, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main.thread);
break;
}
}
} // for
+ f_thread_unlock(&main.thread->lock.entry);
+
if (status == F_child || status == F_signal) {
return status;
}
if (F_status_is_error_not(status) && simulate) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
return status;
* The length of the prefix path.
* @param path_suffix_length
* The length of the suffix path.
- * @param thread_data
- * The thread data.
+ * @param main
+ * The main data.
* @param cache
* The following within the cache is updated:
* - name_file: The partial path of the file is inserted.
* @see f_string_dynamic_terminate_after()
*/
#ifndef _di_controller_file_load_
- 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;
+ 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_main_t main, controller_cache_t *cache) f_gcc_attribute_visibility_internal;
#endif // _di_controller_file_load_
/**
*
* This does not do any locking or unlocking for the processs data, be sure to lock appropriately before and after calling this.
*
- * @param id
- * The (rule) id to find.
+ * @param alias
+ * The Rule alias to find.
* @param processs
* The array of processes to.
* @param at
* F_true if there is a process found (address is stored in "at").
*/
#ifndef _di_controller_find_process_
- f_status_t controller_find_process(const f_string_static_t id, const controller_processs_t processs, f_array_length_t *at) f_gcc_attribute_visibility_internal;
+ f_status_t controller_find_process(const f_string_static_t alias, const controller_processs_t processs, f_array_length_t *at) f_gcc_attribute_visibility_internal;
#endif // _di_controller_find_process_
/**
*
* This does not do any locking or unlocking for the setting data, be sure to lock appropriately before and after calling this.
*
- * @param thread_data
- * The thread data.
+ * @param main
+ * The main data.
* @param cache
* The cache.
*
* @see controller_file_pid_create()
*/
#ifndef _di_controller_perform_ready_
- extern f_status_t controller_perform_ready(controller_thread_data_t thread_data, controller_cache_t *cache) f_gcc_attribute_visibility_internal;
+ extern f_status_t controller_perform_ready(controller_main_t main, 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 main
+ * The main data.
* @param cache
* The main/global cache to use.
*
* @see f_string_dynamic_terminate_after()
*/
#ifndef _di_controller_preprocess_entry_
- extern f_status_t controller_preprocess_entry(controller_thread_data_t thread_data, controller_cache_t *cache) f_gcc_attribute_visibility_internal;
+ extern f_status_t controller_preprocess_entry(controller_main_t main, 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 main
+ * The main data.
* @param cache
* The main/global cache to use.
*
* @see controller_string_dynamic_append_terminated()
*/
#ifndef _di_controller_process_entry_
- extern f_status_t controller_process_entry(controller_thread_data_t thread_data, controller_cache_t *cache) f_gcc_attribute_visibility_internal;
+ extern f_status_t controller_process_entry(controller_main_t main, controller_cache_t *cache) f_gcc_attribute_visibility_internal;
#endif // _di_controller_process_entry_
/**
#endif // _di_controller_entry_actions_increase_by_
#ifndef _di_controller_entry_actions_read_
- 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 controller_entry_actions_read(const f_string_range_t content_range, controller_main_t main, controller_cache_t *cache, controller_entry_actions_t *actions) {
f_status_t status = F_none;
f_status_t status_action = F_none;
}
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "fll_fss_extended_read", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "fll_fss_extended_read", F_true);
return status;
}
status = fl_fss_apply_delimit(cache->delimits, &cache->buffer_file);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true);
return status;
}
status = controller_entry_actions_increase_by(cache->object_actions.used, actions);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_entry_actions_increase_by", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "controller_entry_actions_increase_by", F_true);
return status;
}
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(thread_data.data->error, F_status_set_fine(status), "f_fss_count_lines", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "f_fss_count_lines", F_true);
break;
}
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(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_rip_nulless_terminated", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "controller_string_dynamic_rip_nulless_terminated", F_true);
break;
}
actions->array[actions->used].type = controller_entry_action_type_timeout;
}
else {
- 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_cache(thread_data.data->warning, cache->action);
+ if (main.data->warning.verbosity == f_console_verbosity_debug) {
+ fprintf(main.data->warning.to.stream, "%s%sUnknown entry item action '", main.data->warning.context.before->string, main.data->warning.prefix ? main.data->warning.prefix : f_string_empty_s);
+ fprintf(main.data->warning.to.stream, "%s%s", main.data->warning.context.after->string, main.data->warning.notable.before->string);
+ f_print_dynamic(main.data->warning.to.stream, cache->action.name_action);
+ fprintf(main.data->warning.to.stream, "%s", main.data->warning.notable.after->string);
+ fprintf(main.data->warning.to.stream, "%s'.%s%c", main.data->warning.context.before->string, main.data->warning.context.after->string, f_string_eol_s[0]);
+
+ controller_entry_error_print_cache(main.data->warning, cache->action);
}
continue;
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 (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 (main.data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe entry item action '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, cache->action.name_action.string, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s' requires ", main.data->error.context.before->string);
if (action->type == controller_entry_action_type_failsafe || action->type == controller_entry_action_type_item) {
- 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]);
+ fprintf(main.data->error.to.stream, "%s%s%llu%s", main.data->error.context.after->string, main.data->error.notable.before->string, cache->action.line_action, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s or more parameters.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
}
else {
uint8_t parameters = 0;
parameters = 2;
}
- 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]);
+ fprintf(main.data->error.to.stream, "exactly ", main.data->error.context.before->string);
+ fprintf(main.data->error.to.stream, "%s%s%u%s", main.data->error.context.after->string, main.data->error.notable.before->string, parameters, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s parameters.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
}
}
}
status = f_string_dynamics_increase_by(allocate, &action->parameters);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamics_increase_by", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "f_string_dynamics_increase_by", F_true);
action->status = status;
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(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true);
action->status = status;
status = fll_path_canonical(action->parameters.array[0].string, &cache->buffer_path);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "fll_path_canonical", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "fll_path_canonical", F_true);
action->status = status;
status_action = action->status;
}
- 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]);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe entry item action must not have an empty string for a path (the first parameter).%s%c", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s, main.data->error.context.after->string, f_string_eol_s[0]);
}
}
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(thread_data.data->error, F_status_set_fine(status), "f_file_name_base", F_true);
+ fll_error_print(main.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;
else {
if (fl_string_dynamic_compare(action->parameters.array[1], cache->buffer_path) == F_equal_to_not) {
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
+ if (main.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(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true);
action->status = status;
break;
}
- 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]);
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe entry item action second parameter '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, action->parameters.array[1].string, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s' must be a base path name, such as '", main.data->error.context.before->string);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, cache->buffer_path.string, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s'.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
}
action->status = F_status_set_error(F_parameter);
status_action = action->status;
}
- 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]);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe entry item action must not have an empty string for a rule name (the second parameter).%s%c", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s, main.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]);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe entry item action third parameter (and beyond) must be one of '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, controller_string_asynchronous_s, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s', '", main.data->error.context.before->string);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, controller_string_require_s, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s', or '", main.data->error.context.before->string);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, controller_string_wait_s, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s' but instead has '", main.data->error.context.before->string);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, action->parameters.array[j].string, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s'.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
}
}
} // for
status_action = action->status;
}
- 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]);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe entry item action may not specify the reserved item '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, controller_string_main_s, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s'.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
}
}
}
status_action = action->status;
}
- 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]);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe entry item action must have one of '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, controller_string_kill_s, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s', '", main.data->error.context.before->string);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, controller_string_start_s, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s', or '", main.data->error.context.before->string);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, controller_string_stop_s, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s' but instead has '", main.data->error.context.before->string);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, action->parameters.array[0].string, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s'.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
}
}
}
if (F_status_set_fine(status) == F_memory_not) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "fl_conversion_string_to_number_unsigned", F_true);
status_action = status;
break;
}
- 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]);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe entry item action parameter '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, action->parameters.array[1].string, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s' is not a valid supported number.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
}
}
}
#endif // _di_controller_entry_items_increase_by_
#ifndef _di_controller_entry_read_
- 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 controller_entry_read(const f_string_static_t entry_name, controller_main_t main, controller_cache_t *cache) {
f_status_t status = F_none;
// @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;
+ main.setting->entry.status = F_known_not;
+ main.setting->entry.items.used = 0;
cache->action.line_action = 0;
cache->action.line_item = 0;
cache->action.name_action.used = 0;
cache->action.name_item.used = 0;
- 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);
+ status = controller_file_load(controller_string_entries_s, entry_name, controller_string_entry_s, controller_string_entries_length, controller_string_entry_length, main, cache);
if (F_status_is_error_not(status)) {
if (cache->buffer_file.used) {
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)) {
- controller_error_print(thread_data.data->error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true, thread_data.thread);
+ controller_error_print(main.data->error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true, main.thread);
}
else {
status = fl_fss_apply_delimit(cache->delimits, &cache->buffer_file);
if (F_status_is_error(status)) {
- controller_error_print(thread_data.data->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true, thread_data.thread);
+ controller_error_print(main.data->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true, main.thread);
}
}
}
else {
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe entry file is empty.%s%c", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s, main.data->error.context.after->string, f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
status = F_status_set_error(F_data_not);
}
if (F_status_is_error_not(status) && cache->object_items.used) {
- status = controller_entry_items_increase_by(cache->object_items.used, &thread_data.setting->entry.items);
+ status = controller_entry_items_increase_by(cache->object_items.used, &main.setting->entry.items);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_entry_items_increase_by", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "controller_entry_items_increase_by", F_true);
}
else {
for (; i < cache->object_items.used; ++i) {
- if (thread_data.thread->signal) {
+ if (main.thread->signal) {
return F_signal;
}
cache->action.name_action.used = 0;
cache->action.name_item.used = 0;
- status = controller_entry_items_increase_by(controller_default_allocation_step, &thread_data.setting->entry.items);
+ status = controller_entry_items_increase_by(controller_default_allocation_step, &main.setting->entry.items);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_entry_items_increase_by", F_true);
+ fll_error_print(main.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(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_partial_append_terminated", F_true);
+ fll_error_print(main.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(thread_data.data->error, F_status_set_fine(status), "f_fss_count_lines", F_true);
+ fll_error_print(main.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 < thread_data.setting->entry.items.used; ++j) {
+ for (j = (code & 0x1) ? 1 : 0; j < main.setting->entry.items.used; ++j) {
- 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) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (fl_string_dynamic_compare(main.setting->entry.items.array[j].name, cache->action.name_item) == F_equal_to) {
+ if (main.data->warning.verbosity == f_console_verbosity_debug) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->warning.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->warning.to.stream, "%s%sIgnoring duplicate entry item '", main.data->warning.context.before->string, main.data->warning.prefix ? main.data->warning.prefix : f_string_empty_s);
+ fprintf(main.data->warning.to.stream, "%s%s%s%s", main.data->warning.context.after->string, main.data->warning.notable.before->string, cache->action.name_file.string, main.data->warning.notable.after->string);
+ fprintf(main.data->warning.to.stream, "%s'.%s%c", main.data->warning.context.before->string, main.data->warning.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print_cache(thread_data.data->warning, cache->action);
+ controller_entry_error_print_cache(main.data->warning, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
code |= 0x2;
at = 0;
- if (!thread_data.setting->entry.items.used) {
- thread_data.setting->entry.items.used = 1;
+ if (!main.setting->entry.items.used) {
+ main.setting->entry.items.used = 1;
}
}
- else if (thread_data.setting->entry.items.used) {
- at = thread_data.setting->entry.items.used++;
+ else if (main.setting->entry.items.used) {
+ at = main.setting->entry.items.used++;
}
else {
// skip position 0, which is reserved for "main".
- thread_data.setting->entry.items.array[0].name.used = 0;
+ main.setting->entry.items.array[0].name.used = 0;
at = 1;
- thread_data.setting->entry.items.used = 2;
+ main.setting->entry.items.used = 2;
}
- thread_data.setting->entry.items.array[at].line = cache->action.line_item;
+ main.setting->entry.items.array[at].line = cache->action.line_item;
- status = controller_string_dynamic_append_terminated(cache->action.name_item, &thread_data.setting->entry.items.array[at].name);
+ status = controller_string_dynamic_append_terminated(cache->action.name_item, &main.setting->entry.items.array[at].name);
if (F_status_is_error(status)) {
- controller_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, thread_data.thread);
+ controller_error_print(main.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main.thread);
break;
}
- status = controller_entry_actions_read(*range, thread_data, cache, &thread_data.setting->entry.items.array[at].actions);
+ status = controller_entry_actions_read(*range, main, cache, &main.setting->entry.items.array[at].actions);
if (F_status_is_error(status)) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- controller_entry_error_print_cache(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(main.data->error, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
if (F_status_set_fine(status) == F_memory_not) {
break;
cache->action.name_item.used = 0;
if (!(code & 0x1)) {
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe required entry item '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, controller_string_main_s, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s' was not found.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
status = F_status_set_error(F_found_not);
// 0x1 = missing or not, 0x2 = one or more missing.
uint8_t missing = 0;
- for (i = 0; i < thread_data.setting->entry.items.used; ++i) {
+ for (i = 0; i < main.setting->entry.items.used; ++i) {
- for (j = 0; j < thread_data.setting->entry.items.array[i].actions.used; ++j) {
+ for (j = 0; j < main.setting->entry.items.array[i].actions.used; ++j) {
- if (thread_data.thread->signal) {
+ if (main.thread->signal) {
return F_signal;
}
- action = &thread_data.setting->entry.items.array[i].actions.array[j];
+ action = &main.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;
if (action->type == controller_entry_action_type_failsafe || action->type == controller_entry_action_type_item) {
missing |= 0x1;
- for (k = 0; k < thread_data.setting->entry.items.used; ++k) {
+ for (k = 0; k < main.setting->entry.items.used; ++k) {
- if (fl_string_dynamic_compare(action->parameters.array[0], thread_data.setting->entry.items.array[k].name) == F_equal_to) {
+ if (fl_string_dynamic_compare(action->parameters.array[0], main.setting->entry.items.array[k].name) == F_equal_to) {
if (missing & 0x1) {
missing -= 0x1;
}
missing |= 0x2;
cache->action.line_action = action->line;
- cache->action.line_item = thread_data.setting->entry.items.array[i].line;
+ cache->action.line_item = main.setting->entry.items.array[i].line;
- status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[i].name, &cache->action.name_item);
+ status = controller_string_dynamic_append_terminated(main.setting->entry.items.array[i].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- controller_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, thread_data.thread);
+ controller_error_print(main.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, main.thread);
break;
}
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe required entry item '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, action->parameters.array[0].string, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s' does not exist.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print_cache(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(main.data->error, cache->action);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
action->number = 0;
action->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);
+ // @fixme review how main.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).
+ //main.setting->entry.status = controller_status_simplify(F_found_not);
cache->action.name_action.used = 0;
cache->action.name_item.used = 0;
// the error is already fully printed and the entry status is already assigned, so immediately exit.
if (missing & 0x2) {
- // @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;
+ // @fixme review how main.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 main.setting->entry.status;
}
}
}
}
if (F_status_is_error(status)) {
- controller_entry_error_print_cache(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(main.data->error, cache->action);
- thread_data.setting->entry.status = controller_status_simplify(F_status_set_fine(status));
+ main.setting->entry.status = controller_status_simplify(F_status_set_fine(status));
}
else {
- thread_data.setting->entry.status = F_none;
+ main.setting->entry.status = F_none;
}
- return thread_data.setting->entry.status;
+ return main.setting->entry.status;
}
#endif // _di_controller_entry_read_
*
* @param content_range
* The range in the list buffer representing the content.
- * @param thread_data
- * The thread data.
+ * @param main
+ * The main data.
* @param cache
* A structure for containing and caching relevant data.
* @param actions
* @see fll_fss_extended_read()
*/
#ifndef _di_controller_entry_actions_read_
- 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;
+ extern f_status_t controller_entry_actions_read(const f_string_range_t content_range, controller_main_t main, controller_cache_t *cache, controller_entry_actions_t *actions) f_gcc_attribute_visibility_internal;
#endif // _di_controller_entry_actions_read_
/**
* 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 main
+ * The main data.
* @param cache
* The cache for the specific thread.
- * This should be the cache thread_data.thread->asynchronouss.array[thread_data.id].cache.
+ * This should be the cache main.thread->asynchronouss.array[main.id].cache.
*
* @return
* F_none on success.
* @see fll_fss_basic_list_read()
*/
#ifndef _di_controller_entry_read_
- 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;
+ extern f_status_t controller_entry_read(const f_string_static_t entry_name, controller_main_t main, controller_cache_t *cache) f_gcc_attribute_visibility_internal;
#endif // _di_controller_entry_read_
#ifdef __cplusplus
}
#endif // _di_controller_rule_action_method_name_
+#ifndef _di_controller_rule_find_
+ f_status_t controller_rule_find(const f_string_static_t alias, const controller_rules_t rules, f_array_length_t *at) {
+
+ if (!alias.used) return F_none;
+ if (!rules.used) return F_false;
+
+ for (f_array_length_t i = 0; i < rules.used; ++i) {
+
+ if (fl_string_dynamic_compare(alias, rules.array[i].alias) == F_equal_to) {
+ *at = i;
+ return F_true;
+ }
+ } // for
+
+ return F_false;
+ }
+#endif // _di_controller_rule_find_
+
#ifndef _di_controller_rule_parameters_read_
f_status_t controller_rule_parameters_read(const controller_data_t data, const f_string_static_t buffer, f_fss_object_t *object, f_fss_content_t *content, f_string_dynamics_t *parameters) {
+
f_status_t status = F_none;
parameters->used = 0;
if (object && object->start <= object->start) {
+
status = f_string_dynamics_increase(parameters);
if (F_status_is_error(status)) {
}
if (content && content->used) {
+
for (f_array_length_t i = 0; i < content->used; ++i) {
if (content->array[i].start > content->array[i].start) continue;
#ifndef _di_controller_rule_action_read_
f_status_t controller_rule_action_read(const controller_data_t data, const uint8_t type, const uint8_t method, controller_cache_t *cache, controller_rule_item_t *item, controller_rule_actions_t *actions, f_string_range_t *range) {
+
f_status_t status = F_none;
if (method == controller_rule_action_method_extended_list) {
fll_error_print(data.error, F_status_set_fine(status), "f_string_dynamics_increase", F_true);
}
else {
+
actions->array[actions->used].type = type;
actions->array[actions->used].line = cache->action.line_action;
actions->array[actions->used].parameters.used = 0;
fll_error_print(data.error, F_status_set_fine(status), "fll_fss_extended_read", F_true);
}
else {
+
status = fl_fss_apply_delimit(cache->delimits, &cache->buffer_item);
if (F_status_is_error(status)) {
fll_error_print(data.error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true);
}
else {
+
f_array_length_t i = 0;
f_array_length_t j = 0;
for (; i < cache->object_actions.used; ++i) {
-
status = controller_rule_actions_increase_by(controller_default_allocation_step, actions);
if (F_status_is_error(status)) {
}
}
else {
+
cache->content_action.used = 0;
cache->delimits.used = 0;
actions->array[actions->used].status = F_known_not;
for (f_array_length_t i = 0; i < cache->content_action.used; ++i) {
-
status = f_string_dynamic_partial_mash_nulless(f_string_space_s, f_string_space_length, cache->buffer_item, cache->content_action.array[i], &actions->array[actions->used].parameters.array[0]);
if (F_status_is_error(status)) break;
} // for
fll_error_print(data.error, F_status_set_fine(status), "f_fss_count_lines", F_true);
}
else {
+
actions->array[actions->used].type = type;
actions->array[actions->used].line += ++item->line;
actions->array[actions->used].parameters.used = 0;
#ifndef _di_controller_rule_copy_
f_status_t controller_rule_copy(const controller_rule_t source, controller_rule_t *destination) {
+
f_status_t status = F_none;
destination->timeout_kill = source.timeout_kill;
destination->timestamp.seconds = source.timestamp.seconds;
destination->timestamp.nanoseconds = source.timestamp.nanoseconds;
- destination->id.used = 0;
+ destination->alias.used = 0;
destination->name.used = 0;
destination->path.used = 0;
destination->script.used = 0;
destination->items.used = 0;
- if (source.id.used) {
- status = f_string_dynamic_append(source.id, &destination->id);
+ if (source.alias.used) {
+ status = f_string_dynamic_append(source.alias, &destination->alias);
if (F_status_is_error(status)) return status;
}
if (status == F_control_group || status == F_limit || status == F_processor || status == F_schedule) {
fprintf(output.to.stream, "%s' failed due to a failure to setup the '", output.context.before->string);
-
fprintf(output.to.stream, "%s%s", output.context.after->string, output.notable.before->string);
+
if (status == F_control_group) {
fprintf(output.to.stream, "%s", controller_string_control_group_s);
}
else if (status == F_schedule) {
fprintf(output.to.stream, "%s", controller_string_scheduler_s);
}
+
fprintf(output.to.stream, "%s", output.notable.after->string);
fprintf(output.to.stream, "%s'.%s%c", output.context.before->string, output.context.after->string, f_string_eol_s[0]);
}
#endif // _di_controller_rule_error_print_need_want_wish_
#ifndef _di_controller_rule_execute_
- 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 controller_rule_execute(const uint8_t type, const uint8_t options, controller_main_t main, controller_cache_t *cache, controller_rule_t *rule) {
+
f_status_t status = F_none;
f_status_t success = F_false;
status = fll_control_group_prepare(rule->control_group);
if (F_status_is_error(status)) {
- controller_error_print(thread_data.data->error, F_status_set_fine(status), "fll_control_group_prepare", F_true, thread_data.thread);
+ controller_error_print(main.data->error, F_status_set_fine(status), "fll_control_group_prepare", F_true, main.thread);
rule->status = F_status_set_error(F_failure);
return status;
status = fl_environment_load_names(rule->environment, &environment);
if (F_status_is_error(status)) {
- controller_error_print(thread_data.data->error, F_status_set_fine(status), "fl_environment_load_names", F_true, thread_data.thread);
+ controller_error_print(main.data->error, F_status_set_fine(status), "fl_environment_load_names", F_true, main.thread);
rule->status = F_status_set_error(F_failure);
return status;
for (i = 0; i < rule->items.used; ++i) {
- if (thread_data.thread->signal) {
+ if (main.thread->signal) {
status = F_signal;
break;
}
for (j = 0; j < rule->items.array[i].actions.used; ++j) {
- if (thread_data.thread->signal) {
+ if (main.thread->signal) {
status = F_signal;
break;
}
execute_set.parameter.option |= fl_execute_parameter_option_path;
}
- 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);
+ 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, main, rule);
if (status == F_child) break;
success = F_true;
}
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 (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(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);
+ 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, main, rule);
if (status == F_child) break;
execute_set.parameter.option |= fl_execute_parameter_option_path;
}
- 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);
+ 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, main, rule);
if (status == F_child) break;
}
else {
- if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->warning.verbosity == f_console_verbosity_debug) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->warning.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->warning.to.stream, "%s%sAction type is unknown, ignoring.%s%c", main.data->warning.context.before->string, main.data->warning.prefix ? main.data->warning.prefix : f_string_empty_s, main.data->warning.context.after->string, f_string_eol_s[0]);
- controller_rule_error_print(thread_data.data->warning, cache->action, F_true);
+ controller_rule_error_print(main.data->warning, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
rule->items.array[i].actions.array[j].status = F_ignore;
#endif // _di_controller_rule_execute_
#ifndef _di_controller_rule_execute_foreground_
- 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 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_main_t main, controller_rule_t *rule) {
f_status_t status = F_none;
int result = 0;
pid_t id_process = 0;
if (options & controller_rule_option_simulate) {
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
-
- 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);
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "Simulating execution of '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.title.string, program ? program : arguments.used && arguments.array[0].used ? arguments.array[0].string : f_string_empty_s, main.data->context.reset.string);
+ fprintf(main.data->output.stream, "' with the arguments: '%s", main.data->context.important.string);
for (f_array_length_t i = program ? 0 : 1; i < arguments.used; ++i) {
- fprintf(thread_data.data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string);
+ fprintf(main.data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string);
} // for
- 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]);
+ fprintf(main.data->output.stream, "%s' from '", main.data->context.reset.string);
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.notable.string, rule->name.used ? rule->name.string : f_string_empty_s, main.data->context.reset.string);
+ fprintf(main.data->output.stream, "%s'.%c", main.data->context.reset.string, f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
// sleep for less than a second to better show simulation of synchronous vs asynchronous.
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.
- thread_data.thread->asynchronouss.array[thread_data.id].child = id_process;
+ main.thread->asynchronouss.array[main.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.
- thread_data.thread->asynchronouss.array[thread_data.id].child = 0;
+ main.thread->asynchronouss.array[main.id].child = 0;
// this must explicitly check for 0 (as opposed to checking (!result)).
if (!WIFEXITED(result)) {
if (F_status_is_error(status)) {
status = F_status_set_fine(status);
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.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.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(main.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.data->error, F_false, program);
+ controller_rule_error_print_execute_not_found(main.data->error, F_false, program);
}
else {
- fll_error_print(thread_data.data->error, status, "fll_execute_program", F_true);
+ fll_error_print(main.data->error, status, "fll_execute_program", F_true);
}
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
status = F_status_set_error(status);
}
#endif // _di_controller_rule_execute_foreground_
#ifndef _di_controller_rule_execute_pid_with_
- 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 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_main_t main, controller_rule_t *rule) {
f_status_t status = F_none;
int result = 0;
if (options & controller_rule_option_simulate) {
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
- 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);
+ f_thread_mutex_lock(&main.thread->lock.print);
+
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "Simulating execution of '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.title.string, program ? program : arguments.used && arguments.array[0].used ? arguments.array[0].string : f_string_empty_s, main.data->context.reset.string);
+ fprintf(main.data->output.stream, "' with the arguments: '%s", main.data->context.important.string);
for (f_array_length_t i = program ? 0 : 1; i < arguments.used; ++i) {
- fprintf(thread_data.data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string);
+ fprintf(main.data->output.stream, "%s%s", (program && i || !program && i > 1) ? f_string_space_s : "", arguments.array[i].string);
} // for
- 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]);
+ fprintf(main.data->output.stream, "%s' from '", main.data->context.reset.string);
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.notable.string, rule->name.used ? rule->name.string : f_string_empty_s, main.data->context.reset.string);
+ fprintf(main.data->output.stream, "%s'.%c", main.data->context.reset.string, f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
// sleep for less than a second to better show simulation of synchronous vs asynchronous.
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.
- thread_data.thread->asynchronouss.array[thread_data.id].child = id_process;
+ main.thread->asynchronouss.array[main.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.
- thread_data.thread->asynchronouss.array[thread_data.id].child = 0;
+ main.thread->asynchronouss.array[main.id].child = 0;
// this must explicitly check for 0 (as opposed to checking (!result)).
if (!WIFEXITED(result)) {
}
if (F_status_is_error(status)) {
+
status = F_status_set_fine(status);
if (status == F_child || status == F_capability || status == F_group || status == F_nice || status == F_user) {
}
if (F_status_is_error(status)) {
+
status = F_status_set_fine(status);
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.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.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(main.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.data->error, F_false, program);
+ controller_rule_error_print_execute_not_found(main.data->error, F_false, program);
}
else {
- fll_error_print(thread_data.data->error, status, "fll_execute_program", F_true);
+ fll_error_print(main.data->error, status, "fll_execute_program", F_true);
}
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
return F_status_set_error(status);
}
}
#endif // _di_controller_rule_execute_pid_with_
-// @todo consider changing this to accept "at" as an argument and returning status so that error status can be returned.
-#ifndef _di_controller_rule_find_loaded_
- 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 = thread_data.setting->rules.used;
-
- for (; i; --i) {
- if (fl_string_dynamic_compare(rule_id, thread_data.setting->rules.array[i].id) == F_equal_to) return i;
- } // for
-
- return thread_data.setting->rules.used;
- }
-#endif // _di_controller_rule_find_loaded_
-
#ifndef _di_controller_rule_id_construct_
- f_status_t controller_rule_id_construct(const controller_data_t data, const f_string_static_t source, const f_string_range_t directory, const f_string_range_t basename, f_string_dynamic_t *id) {
+ f_status_t controller_rule_id_construct(const controller_data_t data, const f_string_static_t source, const f_string_range_t directory, const f_string_range_t basename, f_string_dynamic_t *alias) {
+
f_status_t status = F_none;
- id->used = 0;
+ alias->used = 0;
- status = f_string_dynamic_partial_append_nulless(source, directory, id);
+ status = f_string_dynamic_partial_append_nulless(source, directory, alias);
if (F_status_is_error(status)) {
fll_error_print(data.error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true);
return status;
}
- status = f_string_append(f_path_separator_s, f_path_separator_length, id);
+ status = f_string_append(f_path_separator_s, f_path_separator_length, alias);
if (F_status_is_error(status)) {
fll_error_print(data.error, F_status_set_fine(status), "f_string_append", F_true);
return status;
}
- status = f_string_dynamic_partial_append_nulless(source, basename, id);
+ status = f_string_dynamic_partial_append_nulless(source, basename, alias);
if (F_status_is_error(status)) {
fll_error_print(data.error, F_status_set_fine(status), "f_string_dynamic_partial_append_nulless", F_true);
return status;
}
- status = f_string_dynamic_terminate_after(id);
+ status = f_string_dynamic_terminate_after(alias);
if (F_status_is_error(status)) {
fll_error_print(data.error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true);
#ifndef _di_controller_rule_item_read_
f_status_t controller_rule_item_read(const controller_data_t data, controller_cache_t *cache, controller_rule_item_t *item) {
+
f_status_t status = F_none;
f_string_range_t range = f_macro_string_range_t_initialize(cache->buffer_item.used);
if (multiple) {
if (type == controller_rule_action_type_create || type == controller_rule_action_type_group || type == controller_rule_action_type_use || type == controller_rule_action_type_user) {
+
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%sFSS Extended List is not allowed for the rule item action '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s);
#ifndef _di_controller_rule_path_
f_status_t controller_rule_path(const controller_data_t data, const controller_setting_t setting, const f_string_static_t path_directory, const f_string_static_t path_name, f_string_dynamic_t *path) {
+
f_status_t status = F_none;
path->used = 0;
#endif // _di_controller_rule_path_
#ifndef _di_controller_rule_process_
- f_status_t controller_rule_process(const controller_rule_t rule, const f_array_length_t at_process, const uint8_t action, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache) {
-
- // @todo need to update accordingly with new parameters "rule" and "at_process".
+ f_status_t controller_rule_process(const controller_rule_t rule, const uint8_t action, const uint8_t options, const controller_main_t main, controller_process_t *process) {
switch (action) {
case controller_rule_action_type_freeze:
default:
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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]);
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sUnsupported action type '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, controller_rule_action_type_name(action), main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s' while attempting to execute rule.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
- controller_rule_error_print(thread_data.data->error, cache->action, F_true);
+ controller_rule_error_print(main.data->error, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
return F_status_set_error(F_parameter);
}
- if (index >= thread_data.setting->rules.used) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
-
- 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_data.thread->lock.print);
-
- return F_status_set_error(F_parameter);
- }
-
f_status_t status = F_none;
- 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_data.thread->lock.print);
-
- 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_data.thread->lock.print);
-
- return status;
- }
-
- f_array_length_t i = 0;
-
- for (; i < thread_data.thread->asynchronouss.array[thread_data.id].stack.used; ++i) {
-
- 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->lock.print);
-
- 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.data->error, cache->action, F_true);
-
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
- }
-
- // never continue on recursion errors even in simulate mode.
- return F_status_set_error(F_recurse);
- }
- }
-
cache->action.name_action.used = 0;
cache->action.name_item.used = 0;
cache->action.name_file.used = 0;
}
if (F_status_is_error(status)) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fll_error_print(main.data->error, F_status_set_fine(status), "f_string_append", F_true);
+ controller_rule_error_print(main.data->error, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
return status;
}
- status = f_string_dynamic_append(thread_data.setting->rules.array[index].id, &cache->action.name_file);
+ status = f_string_dynamic_append(rule.alias, &cache->action.name_file);
if (F_status_is_error(status)) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fll_error_print(main.data->error, F_status_set_fine(status), "f_string_dynamic_append", F_true);
+ controller_rule_error_print(main.data->error, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
return status;
}
}
if (F_status_is_error(status)) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fll_error_print(main.data->error, F_status_set_fine(status), "f_string_append", F_true);
+ controller_rule_error_print(main.data->error, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
return status;
}
status = f_string_dynamic_terminate_after(&cache->action.name_file);
if (F_status_is_error(status)) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ fll_error_print(main.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true);
+ controller_rule_error_print(main.data->error, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
return status;
}
- 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_data.setting->rules.array[index];
-
- 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);
+ if ((options & controller_rule_option_simulate) && main.data->parameters[controller_parameter_validate].result == f_console_result_found) {
+ controller_rule_simulate(rule, controller_rule_action_type_start, options, main, cache);
}
+ f_array_length_t i = 0;
+
{
f_array_length_t j = 0;
f_array_length_t k = 0;
- f_array_length_t at = 0;
+ f_array_length_t id_rule = 0;
+ f_array_length_t id_process = 0;
+
+ controller_rule_t *rule_other = 0;
+ controller_process_t *process_other = 0;
f_string_dynamics_t * const dynamics[] = {
&rule->need,
"wished for",
};
+ // i==0 is need, i==1 is want, i==2 is wish.
+ // loop through all dependencies: wait for depedency, execute dependency, fail due to missing required dependency, or skip unrequired missing dependencies.
for (i = 0; i < 3; ++i) {
for (j = 0; j < dynamics[i]->used; ++j) {
- at = controller_rule_find_loaded(*thread_data.data, *thread_data.setting, dynamics[i]->array[j]);
- if (at == thread_data.setting->rules.used) {
+ f_thread_lock_read(&main.thread->lock.rule);
+
+ status = controller_find_process(dynamics[i]->array[j], *main.thread->processs, &id_process);
+
+ if (status == F_true) {
+ status = controller_rule_find(dynamics[i]->array[j], main.setting->rules, &id_rule);
+ }
+
+ if (status != F_true) {
+ id_rule = main.setting->rules.used;
+
if (i == 0) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- controller_rule_error_print_need_want_wish(thread_data.data->error, strings[i], dynamics[i]->array[j].string, "was not found");
+ controller_rule_error_print_need_want_wish(main.data->error, strings[i], dynamics[i]->array[j].string, "was not found");
+ controller_rule_error_print(main.data->error, cache->action, F_true);
+
+ f_thread_mutex_unlock(&main.thread->lock.print);
status = F_status_set_error(F_found_not);
- controller_rule_error_print(thread_data.data->error, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ if (!(options & controller_rule_option_simulate)) {
+ f_thread_unlock(&main.thread->lock.rule);
- if (!(options & controller_rule_option_simulate)) break;
+ break;
+ }
}
else {
- if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->warning.verbosity == f_console_verbosity_debug) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ controller_rule_error_print_need_want_wish(main.data->warning, strings[i], dynamics[i]->array[j].string, "was not found");
+ controller_rule_error_print(main.data->warning, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
}
}
- if (F_status_is_error_not(status) && at < thread_data.setting->rules.used) {
+ if (status == F_true && id_rule < main.setting->rules.used) {
+ f_thread_lock_read(&main.thread->lock.process);
- f_thread_mutex_lock(&thread_data.setting->rules.array[at].lock);
+ process_other = &main.thread->processs->array[id_process];
- 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
+ f_thread_lock_read(&process_other->active);
+ f_thread_lock_read(&process_other->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);
+ if (process_other->status == F_known_not && (process_other->state == controller_process_state_active || process_other->state == controller_process_state_busy)) {
+ f_thread_unlock(&process_other->lock);
+ f_thread_condition_wait(&process_other->wait, &process_other->running);
- status = F_signal;
- break;
+ // always pass the signal along when done waiting.
+ f_thread_condition_signal(&process->wait);
+ f_thread_mutex_unlock(&process->running);
+ }
+ else {
+ f_thread_unlock(&process_other->lock);
}
- // when the status is unknown, then the rule has not been executed, so attempt to execute it.
- if (thread_data.setting->rules.array[at].status == F_known_not) {
-
- 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_data.thread->lock.print);
-
- 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_data.thread->lock.print);
-
- 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 = cache->action.line_action;
- const f_array_length_t cache_line_item = cache->action.line_item;
+ if (!main.thread->enabled) {
+ f_thread_unlock(&main.thread->lock.process);
+ f_thread_unlock(&process_other->active);
+ f_thread_unlock(&main.thread->lock.rule);
- 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;
+ status = F_signal;
+ break;
+ }
- char cache_name_action[cache_name_action_used];
- char cache_name_item[cache_name_item_used];
- char cache_name_file[cache_name_file_used];
+ f_thread_unlock(&main.thread->lock.process);
- 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);
+ rule_other = &main.setting->rules.array[id_rule];
- // @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.
+ // attempt to (synchronously) execute the rule when the status is unknown (the rule has not yet been run).
+ if (rule_other->status == F_known_not) {
- // 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);
+ status = controller_rule_process_begin(F_false, rule_other->alias, action, options & controller_rule_option_asynchronous ? options - controller_rule_option_asynchronous : options, process->stack, main, cache);
if (status == F_child || status == F_signal) {
- f_thread_condition_signal(&thread_data.setting->rules.array[at].wait);
- f_thread_mutex_unlock(&thread_data.setting->rules.array[at].lock);
+ f_thread_unlock(&process_other->active);
+ f_thread_unlock(&main.thread->lock.rule);
break;
}
- // restore cache.
- 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);
-
- cache->action.name_action.string[cache_name_action_used] = 0;
- cache->action.name_item.string[cache_name_item_used] = 0;
-
- 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;
-
- 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(&main.thread->lock.print);
- f_thread_mutex_lock(&thread_data.thread->lock.print);
-
- 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);
+ controller_rule_error_print_need_want_wish(main.data->error, strings[i], rule_other->alias.string, "failed during execution");
+ controller_rule_error_print(main.data->error, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
if (!(options & controller_rule_option_simulate) || F_status_set_fine(status) == F_memory_not) {
- f_thread_condition_signal(&thread_data.setting->rules.array[at].wait);
- f_thread_mutex_unlock(&thread_data.setting->rules.array[at].lock);
+ f_thread_unlock(&process_other->active);
+ f_thread_unlock(&main.thread->lock.rule);
break;
}
}
else {
- if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->warning.verbosity == f_console_verbosity_debug) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ controller_rule_error_print_need_want_wish(main.data->warning, strings[i], rule_other->alias.string, "failed during execution");
+ controller_rule_error_print(main.data->warning, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
}
}
}
- 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_data.setting->rules.array[at].status)) {
+ f_thread_unlock(&process_other->active);
+ if (F_status_is_error(rule_other->status)) {
if (i == 0 || i == 1) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
- controller_rule_error_print_need_want_wish(thread_data.data->error, strings[i], dynamics[i]->array[j].string, "is in a failed state");
+ controller_rule_error_print_need_want_wish(main.data->error, strings[i], rule_other->alias.string, "is in a failed state");
status = F_status_set_error(F_found_not);
- controller_rule_error_print(thread_data.data->error, cache->action, F_true);
+ controller_rule_error_print(main.data->error, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
- if (!(options & controller_rule_option_simulate)) break;
+ if (!(options & controller_rule_option_simulate)) {
+ f_thread_unlock(&main.thread->lock.rule);
+ break;
+ }
}
else {
- if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (main.data->warning.verbosity == f_console_verbosity_debug) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- 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);
+ controller_rule_error_print_need_want_wish(main.data->warning, strings[i], rule_other->alias.string, "is in a failed state");
+ controller_rule_error_print(main.data->warning, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
}
}
}
+
+ f_thread_unlock(&main.thread->lock.rule);
} // for
if (status == F_child || status == F_signal) break;
return status;
}
- if (!thread_data.enabled) {
+ if (!main.thread->enabled) {
return F_signal;
}
- // @fixme changing design, "wait" will be a distinct thing not associated with individual rules. this will be in its own process function.
if (!(options & controller_rule_option_wait) && F_status_is_error_not(status)) {
- controller_rule_wait_all(thread);
+ controller_rule_wait_all(main);
- if (!thread_data.enabled) {
+ if (!main.thread->enabled) {
return F_signal;
}
}
f_array_length_t j = 0;
- for (i = 0; i < rule->items.used; ++i) {
+ for (i = 0; i < rule.items.used; ++i) {
- for (j = 0; j < rule->items.array[i].actions.used; ++j) {
+ for (j = 0; j < rule.items.array[i].actions.used; ++j) {
- if (rule->items.array[i].actions.array[j].type == action) {
+ if (rule.items.array[i].actions.array[j].type == action) {
missing = F_false;
break;
}
} // for
if (missing) {
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
-
- 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]);
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe rule '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, rule.name.used ? rule.name.string : f_string_empty_s, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s' has no '", main.data->error.context.before->string);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, controller_rule_action_type_name(action).string, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s' action to execute.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
- controller_rule_error_print(thread_data.data->error, cache->action, F_true);
+ controller_rule_error_print(main.data->error, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
status = F_status_set_error(F_parameter);
}
if (F_status_is_error_not(status)) {
- // @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);
+ // @todo make sure to update this function.
+ status = controller_rule_execute(rule, action, options, main, process);
if (status == F_child) {
return F_child;
}
- if (!thread_data.enabled) {
+ if (!main.thread->enabled) {
return F_signal;
}
if (F_status_is_error(status)) {
- controller_rule_error_print_locked(thread_data.data->error, cache->action, F_true, thread);
+ controller_rule_error_print_locked(main.data->error, cache->action, F_true, thread);
}
}
}
- // remove this rule off the stack.
- thread_data.thread->asynchronouss.array[thread_data.id].stack.used--;
-
if (F_status_is_error(status)) {
return status;
}
}
#endif // _di_controller_rule_process_
-#ifndef _di_controller_rule_process_do_
- f_status_t controller_rule_process_do(const controller_rule_t rule, const f_array_length_t at_process, const uint8_t action, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache) {
+#ifndef _di_controller_rule_process_begin_
+ f_status_t controller_rule_process_begin(const bool asynchronous, const f_string_static_t alias_rule, const uint8_t action, const uint8_t options, const f_array_lengths_t stack, const controller_main_t main, controller_cache_t *cache) {
+
+ f_thread_lock_read(&main.thread->lock.process);
+
+ if (!main.thread->enabled) {
+ f_thread_mutex_unlock(&main.thread->lock.process);
+
+ return F_signal;
+ }
+
+ f_status_t status = F_none;
- f_array_length_t at_process = 0;
+ controller_process_t *process = 0;
- f_thread_lock_read(&thread_data.thread->lock.process);
+ {
+ f_array_length_t id_process = 0;
- if (controller_find_process(rule_id, *thread_data.processs, &at_process) == F_false) {
- f_thread_unlock(&thread_data.thread->lock.process);
- f_thread_lock_write(&thread_data.thread->lock.process);
+ if (controller_find_process(alias_rule, *main.thread->processs, &id_process) != F_true) {
+ status = F_status_set_error(F_found_not);
+ }
- status = controller_processs_increase(thread_data.processs);
+ f_thread_unlock(&main.thread->lock.process);
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "controller_processs_increase", F_true, thread_data.thread);
+
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&thread_main->thread->lock.print);
+
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "The entry item rule '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, alias_rule.string, main.data->context.set.title.after->string);
+ fprintf(main.data->output.stream, "' is no longer loaded.%c", f_string_eol_s[0]);
+
+ controller_entry_error_print_cache(main.data->error, cache->action);
+
+ f_thread_mutex_unlock(&main.thread->lock.print);
+ }
+
+ return status;
}
- else {
- at_process = thread_data.processs->used;
+
+ f_thread_lock_write(&main.thread->processs->array[id_process].lock);
+
+ process = &main.thread->processs->array[id_process];
+
+ // if the process is already running, then there is nothing to do.
+ if (process->state == controller_process_state_active || process->state == controller_process_state_busy) {
+ f_thread_unlock(&process->lock);
+
+ return F_busy;
}
+
+ f_thread_lock_read(&process->active);
+
+ // the thread is done, so detach/close the thread.
+ if (process->state == controller_process_state_done) {
+ f_thread_detach(process->id_thread);
+ }
+
+ process->id = id_process;
}
- f_thread_unlock(&thread_data.thread->lock.process);
+ process->main.data = main.data;
+ process->main.setting = main.setting;
+ process->main.thread = main.thread;
- if (F_status_is_error_not(status)) {
+ process->state = controller_process_state_active;
+ process->action = action;
+ process->options = options;
- // retrieve a copy of the rule and use that for the lifespan of the rule's execution within the designated process.
- controller_rule_t rule = controller_rule_t_initialize;
+ f_macro_time_spec_t_clear(process->cache.timestamp)
+ f_macro_string_range_t_clear(process->cache.range_action)
+
+ process->cache.ats.used = 0;
+ process->cache.stack.used = 0;
+ process->cache.comments.used = 0;
+ process->cache.delimits.used = 0;
+ process->cache.content_action.used = 0;
+ process->cache.content_actions.used = 0;
+ process->cache.content_items.used = 0;
+ process->cache.object_actions.used = 0;
+ process->cache.object_items.used = 0;
+ process->cache.buffer_file.used = 0;
+ process->cache.buffer_item.used = 0;
+ process->cache.buffer_path.used = 0;
+ process->cache.action.used = 0;
+ process->cache.line_action = process_data.thread->cache_action->line_action;
+ process->cache.line_item = process_data.thread->cache_action->line_item;
- status = controller_rule_copy(thread_data.setting->rules.array[at], &rule);
+ process->stack.used = 0;
- f_thread_unlock(&thread_data.thread->lock.rule);
+ process->main_data = (void *) &main->data;
+ process->main_setting = (void *) &main->setting;
+ process->main_thread = (void *) &main->thread;
+
+ if (F_status_is_error_not(status) && stack.used) {
+ if (process->stack.used < stack.used) {
+ status = f_type_array_lengths_resize(process->stack.used, &process->stack);
+ }
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "controller_rule_copy", F_true, thread_data.thread);
+ controller_entry_error_print(process_data.data->error, process->cache->action, F_status_set_fine(status), "f_type_array_lengths_resize", F_true, process_data.thread);
}
else {
- status = controller_rule_process(rule, at_process, controller_rule_action_type_start, rule_options, thread_data, cache);
+ for (f_array_length_t i = 0; i < stack.used; ++i) {
+ process->stack.array[process->stack.used++] = stack.array[i];
+ } // for
+ }
+ }
+
+ if (F_status_is_error_not(status)) {
+ status = f_string_dynamic_append(process_data.thread->cache_action.name_action, &process->cache.action.name_action);
- controller_rule_delete_simple(&rule);
+ if (F_status_is_error_not(status)) {
+ status = f_string_dynamic_append(process_data.thread->cache_action.name_file, &process->cache.action.name_file);
+ }
- if (F_status_is_error(status)) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ if (F_status_is_error_not(status)) {
+ status = f_string_dynamic_append(process_data.thread->cache_action.name_item, &process->cache.action.name_item);
+ }
+ else {
+ controller_entry_error_print(process_data.data->error, process->cache->action, F_status_set_fine(status), "f_string_dynamic_append", F_true, process_data.thread);
+ }
+ }
- controller_entry_error_print_cache(thread_data.data->error, cache->action);
+ f_thread_unlock(&process->lock);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ if (F_status_is_error_not(status)) {
+ if (asynchronous) {
+ status = f_thread_create(0, &process->id_thread, controller_thread_process, (void *) &process);
+
+ if (F_status_is_error(status)) {
+ controller_entry_error_print(process_data.data->error, process->cache->action, F_status_set_fine(status), "f_thread_create", F_true, process_data.thread);
}
}
+ else {
+ status = controller_rule_process_do(F_false, process);
+ }
}
- }
-#endif // _di_controller_rule_process_do_
-#ifndef _di_controller_rule_process_asynchronous_
- f_status_t controller_rule_process_asynchronous(const f_string_static_t id_rule, const uint8_t action, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache) {
+ f_thread_unlock(&process->active);
- f_thread_lock_read(&thread_data.lock.asynchronous);
+ if (F_status_is_error(status)) {
+ return status;
+ }
- if (!thread_data.thread->enabled) {
- f_thread_mutex_unlock(&thread_data.lock.asynchronous);
+ return F_none;
+ }
+#endif // _di_controller_rule_process_begin_
- return F_signal;
- }
+#ifndef _di_controller_rule_process_do_
+ f_status_t controller_rule_process_do(const bool asynchronous, controller_process_t *process) {
- f_thread_mutex_unlock(&thread_data.lock.asynchronous);
- f_thread_lock_write(&thread_data.lock.asynchronous);
+ f_thread_lock_read(&process->lock);
- f_status_t status = controller_asynchronouss_increase(&thread_data.thread->asynchronouss);
+ controller_main_t main = controller_macro_main_t_initialize((controller_data_t *) process->main_data, (controller_setting_t *) process->main_setting(controller_thread_t *) process->main_thread);
- if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "controller_asynchronouss_increase", F_true, thread_data.thread);
+ f_thread_lock_read(&main.thread->lock.process);
- f_thread_mutex_unlock(&thread_data.thread->lock.asynchronous);
+ if (!main.thread->enabled) {
+ f_thread_unlock(&process->lock);
+ f_thread_unlock(&main.thread->lock.process);
- return status;
+ return F_signal;
}
- controller_asynchronous_t *asynchronous = &thread_data.thread->asynchronouss.array[thread_data.thread->asynchronouss.used++];
+ f_thread_unlock(&main.thread->lock.process);
+ f_thread_lock_read(&process->active);
+ f_thread_mutex_lock(&process->running);
- f_thread_lock_read(&thread_data.lock.process);
+ f_status_t status = F_none;
+ f_array_length_t id_rule = 0;
- if (controller_find_process(id_rule, *thread_data.processs, &asynchronous->id_process) == F_true) {
+ f_thread_lock_read(&main.thread->lock.rule);
- // use read locks to designate that the process is in use.
- f_thread_lock_read(&thread_data.processs->array[asynchronous->id_process].lock);
- }
- else {
+ if (controller_rule_find(process->alias_rule, main.setting->rules, &id_rule) == F_true) {
+ controller_rule_t rule = controller_rule_t_initialize;
- status = F_status_set_error(F_failure);
+ status = controller_rule_copy(main.setting->rules.array[id_rule], &rule);
- if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_main->thread->lock.print);
+ f_thread_unlock(&main.thread->lock.rule);
- fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]);
- fprintf(thread_data.data->output.stream, "The entry item rule '");
- fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.set.title.before->string, id_rule.string, thread_data.data->context.set.title.after->string);
- fprintf(thread_data.data->output.stream, "' is no longer loaded.%c", f_string_eol_s[0]);
+ if (F_status_is_error(status)) {
+ controller_entry_error_print(main.data->error, process->cache->action, F_status_set_fine(status), "controller_rule_copy", F_true, main.thread);
+ }
+ else {
+ for (f_array_length_t i = 0; i < process->stack.used; ++i) {
- controller_entry_error_print_cache(thread_data.data->error, cache->action);
+ if (process->stack.array[i] == id_rule) {
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
- }
- }
+ fprintf(main.data->error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->error.to.stream, "%s%sThe rule '", main.data->error.context.before->string, main.data->error.prefix ? main.data->error.prefix : f_string_empty_s);
+ fprintf(main.data->error.to.stream, "%s%s%s%s", main.data->error.context.after->string, main.data->error.notable.before->string, process->alias_rule.string, main.data->error.notable.after->string);
+ fprintf(main.data->error.to.stream, "%s' is already on the execution dependency stack, this recursion is prohibited.%s%c", main.data->error.context.before->string, main.data->error.context.after->string, f_string_eol_s[0]);
- f_thread_unlock(&thread_data.lock.process);
+ controller_rule_error_print(main.data->error, cache->action, F_true);
- if (F_status_is_error_not(status)) {
+ f_thread_mutex_unlock(&main.thread->lock.print);
+ }
- asynchronous->state = controller_asynchronous_state_active;
- asynchronous->action = action;
- asynchronous->options = options;
- asynchronous->thread_data.thread = (void *) thread_data.thread;
- //asynchronous->stack.used = 0; // @todo stack should be passed along each call!, might be better to make this a pointer. Maybe make this a id of process id?
-
- f_macro_time_spec_t_clear(asynchronous->cache.timestamp)
- f_macro_string_range_t_clear(asynchronous->cache.range_action)
-
- asynchronous->cache.ats.used = 0;
- asynchronous->cache.stack.used = 0;
- asynchronous->cache.comments.used = 0;
- asynchronous->cache.delimits.used = 0;
- asynchronous->cache.content_action.used = 0;
- asynchronous->cache.content_actions.used = 0;
- asynchronous->cache.content_items.used = 0;
- asynchronous->cache.object_actions.used = 0;
- asynchronous->cache.object_items.used = 0;
- asynchronous->cache.buffer_file.used = 0;
- asynchronous->cache.buffer_item.used = 0;
- asynchronous->cache.buffer_path.used = 0;
- asynchronous->cache.action.used = 0;
- asynchronous->cache.line_action = thread_data.thread->cache_action->line_action;
- asynchronous->cache.line_item = thread_data.thread->cache_action->line_item;
+ // never continue on circular recursion errors even in simulate mode.
+ status = F_status_set_error(F_recurse);
- if (F_status_is_error_not(status)) {
- status = f_string_dynamic_append(thread_data.thread->cache_action->name_action, &asynchronous->cache.name_action);
+ break;
+ }
+ } // for
if (F_status_is_error_not(status)) {
- status = f_string_dynamic_append(thread_data.thread->cache_action->name_file, &asynchronous->cache.name_file);
- }
+ f_thread_unlock(&process->lock);
+ f_thread_lock_write(&process->lock);
- if (F_status_is_error_not(status)) {
- status = f_string_dynamic_append(thread_data.thread->cache_action->name_item, &asynchronous->cache.name_item);
- }
- else {
- controller_entry_error_print(thread_data.data->error, asynchronous->cache->action, F_status_set_fine(status), "f_string_dynamic_append", F_true, thread_data.thread);
+ status = f_type_array_lengths_increase(&process->stack);
+
+ if (F_status_is_error(status)) {
+ controller_entry_error_print(process_data.data->error, process->cache->action, F_status_set_fine(status), "f_type_array_lengths_increase", F_true, process_data.thread);
+ }
+ else {
+ process->stack.array[process->stack.used++] = id_rule;
+ }
+
+ f_thread_unlock(&process->lock);
+ f_thread_lock_read(&process->lock);
}
}
if (F_status_is_error_not(status)) {
- status = f_thread_create(0, &asynchronous->id, controller_thread_asynchronous_process, (void *) asynchronous);
+ status = controller_rule_process(rule, controller_rule_action_type_start, rule_options, main, process);
+
+ if (F_status_is_error(status)) {
+ f_thread_mutex_lock(&main.thread->lock.print);
+
+ controller_entry_error_print_cache(main.data->error, process->cache->action);
+
+ f_thread_mutex_unlock(&main.thread->lock.print);
+ }
}
}
+ else {
+ f_thread_unlock(&main.thread->lock.rule);
- if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, asynchronous->cache->action, F_status_set_fine(status), "f_thread_create", F_true, thread_data.thread);
+ status = F_status_set_error(F_found_not);
+
+ if (main.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&main.thread->lock.print);
- controller_asynchronous_delete_simple(asynchronous);
+ fprintf(main.data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(main.data->output.stream, "The entry item rule '");
+ fprintf(main.data->output.stream, "%s%s%s", main.data->context.set.title.before->string, process->alias_rule.string, main.data->context.set.title.after->string);
+ fprintf(main.data->output.stream, "' is no longer loaded.%c", f_string_eol_s[0]);
- thread_data.thread->asynchronouss.used--;
+ controller_entry_error_print_cache(main.data->error, process->cache->action);
+
+ f_thread_mutex_unlock(&main.thread->lock.print);
+ }
}
- f_thread_unlock(&thread_data->lock.asynchronous);
+ f_thread_unlock(&process->lock);
+ f_thread_lock_write(&process->lock);
- if (F_status_is_error(status)) {
- return status;
+ if (asynchronous) {
+ process->state = controller_asynchronous_state_done;
+ }
+ else {
+ process->state = controller_asynchronous_state_idle;
}
- return F_none;
+ --process->stack.used;
+
+ // inform all things waiting that the process has finished running.
+ f_thread_condition_signal(&process->wait);
+ f_thread_mutex_unlock(&process->running);
+
+ f_thread_unlock(&process->active);
+ f_thread_unlock(&process->lock);
+
+ return status;
}
-#endif // _di_controller_rule_process_asynchronous_
+#endif // _di_controller_rule_process_do_
#ifndef _di_controller_rule_read_
- 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 controller_rule_read(const f_string_static_t rule_id, controller_main_t main, controller_cache_t *cache, controller_rule_t *rule) {
f_status_t status = F_none;
bool for_item = F_true;
f_macro_time_spec_t_clear(rule->timestamp);
- rule->id.used = 0;
+ rule->alias.used = 0;
rule->name.used = 0;
rule->path.used = 0;
rule->script.used = 0;
cache->action.name_file.used = 0;
cache->action.name_item.used = 0;
- status = f_string_dynamic_append_nulless(rule_id, &rule->id);
+ status = f_string_dynamic_append_nulless(rule_id, &rule->alias);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "f_string_dynamic_append_nulless", F_true);
}
else {
- status = f_string_dynamic_terminate_after(&rule->id);
+
+ status = f_string_dynamic_terminate_after(&rule->alias);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true);
}
else {
- 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);
+ status = controller_file_load(controller_string_rules_s, rule->alias, controller_string_rule_s, controller_string_rules_length, controller_string_rule_length, main, cache);
}
}
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(thread_data.data->error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true);
+ fll_error_print(main.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(thread_data.data->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true);
}
}
}
status = controller_rule_items_increase_by(cache->object_items.used, &rule->items);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_rule_items_increase_by", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "controller_rule_items_increase_by", F_true);
}
else {
f_array_length_t i = 0;
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(thread_data.data->error, F_status_set_fine(status), "f_fss_count_lines", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "f_fss_count_lines", F_true);
break;
}
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(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_rip_nulless_terminated", F_true);
+ fll_error_print(main.data->error, F_status_set_fine(status), "controller_string_dynamic_rip_nulless_terminated", F_true);
break;
}
rule->items.array[rule->items.used].type = controller_rule_item_type_service;
}
else {
- 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);
+ if (main.data->warning.verbosity == f_console_verbosity_debug) {
+ fprintf(main.data->warning.to.stream, "%s%sUnknown rule item '", main.data->warning.context.before->string, main.data->warning.prefix ? main.data->warning.prefix : f_string_empty_s);
+ fprintf(main.data->warning.to.stream, "%s%s", main.data->warning.context.after->string, main.data->warning.notable.before->string);
+ f_print_dynamic(main.data->warning.to.stream, cache->action.name_item);
+ fprintf(main.data->warning.to.stream, "%s", main.data->warning.notable.after->string);
+ fprintf(main.data->warning.to.stream, "%s'.%s%c", main.data->warning.context.before->string, main.data->warning.context.after->string, f_string_eol_s[0]);
+
+ controller_rule_error_print(main.data->warning, cache->action, F_true);
}
continue;
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(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_partial_append", F_true);
+ fll_error_print(main.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(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true);
+ fll_error_print(main.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(thread_data, cache, &rule->items.array[rule->items.used]);
+ status = controller_rule_item_read(*main.data, cache, &rule->items.array[rule->items.used]);
if (F_status_is_error(status)) break;
rule->items.used++;
else {
for_item = F_false;
- status = controller_rule_setting_read(thread_data, cache, rule);
+ status = controller_rule_setting_read(*main.data, *main.setting, cache, rule);
if (F_status_is_error(status)) {
if (F_status_set_fine(status) == F_memory_not) {
}
if (F_status_is_error(status)) {
- controller_rule_error_print(thread_data.data->error, cache->action, for_item);
+ controller_rule_error_print(main.data->error, cache->action, for_item);
rule->status = controller_status_simplify(F_status_set_fine(status));
return F_false;
#ifndef _di_controller_rule_setting_read_
f_status_t controller_rule_setting_read(const controller_data_t data, const controller_setting_t setting, controller_cache_t *cache, controller_rule_t *rule) {
+
f_status_t status = F_none;
f_status_t status_return = F_none;
// @todo use sched_getaffinity() to get the available cpus and do not add an invalid cpu to the affinity array.
if (!cache->content_actions.array[i].used) {
-
if (data.error.verbosity != f_console_verbosity_quiet) {
// get the current line number within the settings item.
status = F_status_set_fine(status);
if (status == F_data_not || status == F_number || status == F_number_overflow || status == F_number_underflow) {
-
if (data.error.verbosity != f_console_verbosity_quiet) {
+
if (status == F_number_overflow || status == F_number_underflow) {
fprintf(data.error.to.stream, "%c", f_string_eol_s[0]);
fprintf(data.error.to.stream, "%s%sRule setting has an unsupported number '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s);
if (type == controller_rule_setting_type_define || type == controller_rule_setting_type_parameter) {
if (cache->content_actions.array[i].used != 2) {
-
if (data.error.verbosity != f_console_verbosity_quiet) {
// get the current line number within the settings item.
if (type == controller_rule_setting_type_control_group) {
if (cache->content_actions.array[i].used < 2 || rule->has & controller_rule_has_control_group) {
-
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%sRule setting requires two or more Content.%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 (type == controller_rule_setting_type_limit) {
-
if (cache->content_actions.array[i].used != 3) {
if (data.error.verbosity != f_console_verbosity_quiet) {
f_number_signed_t number = 0;
for (j = 1; j < 3; ++j, number = 0) {
+
status = fl_conversion_string_to_number_signed(cache->buffer_item.string, &number, cache->content_actions.array[i].array[j]);
if (F_status_is_error(status)) {
}
if (type == controller_rule_setting_type_name || type == controller_rule_setting_type_path || type == controller_rule_setting_type_script) {
+
if (type == controller_rule_setting_type_name) {
setting_value = &rule->name;
}
}
if (setting_value->used || cache->content_actions.array[i].used != 1) {
-
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%sRule setting requires exactly one Content.%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 (type == controller_rule_setting_type_name || type == controller_rule_setting_type_script) {
-
status = controller_string_dynamic_rip_nulless_terminated(cache->buffer_item, cache->content_actions.array[i].array[0], setting_value);
if (F_status_is_error(status)) {
status = controller_validate_has_graph(*setting_value);
if (status == F_false || F_status_set_fine(status) == F_complete_not_utf) {
- if (status == F_false) {
+ if (status == F_false) {
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%sRule setting has an invalid name '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s);
if (type == controller_rule_setting_type_scheduler) {
if (cache->content_actions.array[i].used < 1 || cache->content_actions.array[i].used > 2 || rule->has & controller_rule_has_scheduler) {
-
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%sRule setting requires either one or two Content.%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]);
status = f_capability_from_text(cache->action.generic.string, &rule->capability);
if (F_status_is_error(status) && F_status_set_fine(status) != F_supported_not) {
-
if (F_status_set_fine(status) == F_memory_not) {
fll_error_print(data.error, F_status_set_fine(status), "f_capability_from_text", F_true);
#endif // _di_controller_rule_setting_read_
#ifndef _di_controller_rule_simulate_
- 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) {
+ void controller_rule_simulate(const controller_rule_t rule, const uint8_t action, const uint8_t options, const controller_main_t main, controller_cache_t *cache) {
- controller_data_t *data = thread_data.thread->data;
- controller_setting_t *setting = thread_data.thread->setting;
+ const controller_data_t *data = main.data;
- f_thread_mutex_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&main.thread->lock.print);
switch (action) {
case controller_rule_action_type_kill:
controller_rule_error_print(data->error, cache->action, F_true);
}
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
return;
}
- const controller_rule_t *rule = &setting->rules.array[index];
-
f_array_length_t i = 0;
f_array_length_t j = 0;
{
bool missing = F_true;
- for (; i < rule->items.used; ++i) {
+ for (; i < rule.items.used; ++i) {
- for (j = 0; j < rule->items.array[i].actions.used; ++j) {
+ for (j = 0; j < rule.items.array[i].actions.used; ++j) {
- if (rule->items.array[i].actions.array[j].type == action) {
+ if (rule.items.array[i].actions.array[j].type == action) {
missing = F_false;
break;
}
if (missing) {
fprintf(data->output.stream, "%c", f_string_eol_s[0]);
fprintf(data->output.stream, "Rule '");
- fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, rule->name.used ? rule->name.string : f_string_empty_s, data->context.set.title.after->string);
+ fprintf(data->output.stream, "%s%s%s", data->context.set.title.before->string, rule.name.used ? rule.name.string : f_string_empty_s, data->context.set.title.after->string);
fprintf(data->output.stream, "' has no '");
fprintf(data->output.stream, "%s%s%s", data->context.set.important.before->string, controller_rule_action_type_name(action).string, data->context.set.important.after->string);
fprintf(data->output.stream, "' action to execute and would '");
}
fprintf(data->output.stream, "%c", f_string_eol_s[0]);
- fprintf(data->output.stream, "Rule %s%s%s {%c", data->context.set.title.before->string, rule->id.used ? rule->id.string : f_string_empty_s, data->context.set.title.after->string, f_string_eol_s[0]);
- fprintf(data->output.stream, " %s%s%s %s%c", data->context.set.important.before->string, controller_string_name_s, data->context.set.important.after->string, rule->name.used ? rule->name.string : f_string_empty_s, f_string_eol_s[0]);
+ fprintf(data->output.stream, "Rule %s%s%s {%c", data->context.set.title.before->string, rule.alias.used ? rule.alias.string : f_string_empty_s, data->context.set.title.after->string, f_string_eol_s[0]);
+ fprintf(data->output.stream, " %s%s%s %s%c", data->context.set.important.before->string, controller_string_name_s, data->context.set.important.after->string, rule.name.used ? rule.name.string : f_string_empty_s, f_string_eol_s[0]);
fprintf(data->output.stream, " %s%s%s %s%c", data->context.set.important.before->string, controller_string_how_s, data->context.set.important.after->string, options & controller_rule_option_asynchronous ? controller_string_asynchronous : controller_string_synchronous_s, f_string_eol_s[0]);
fprintf(data->output.stream, " %s%s%s %s%c", data->context.set.important.before->string, controller_string_wait_s, data->context.set.important.after->string, options & controller_rule_option_wait ? controller_string_yes : controller_string_no_s, f_string_eol_s[0]);
if (f_capability_supported()) {
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) {
+ if (rule.capability) {
cache->action.generic.used = 0;
- if (F_status_is_error_not(f_capability_to_text(rule->capability, &cache->action.generic))) {
+ if (F_status_is_error_not(f_capability_to_text(rule.capability, &cache->action.generic))) {
fprintf(data->output.stream, "%s", cache->action.generic.string);
}
}
}
fprintf(data->output.stream, " %s%s%s", data->context.set.important.before->string, controller_string_control_group_s, data->context.set.important.after->string);
- if (rule->has & controller_rule_has_control_group) {
- fprintf(data->output.stream, " %s", rule->control_group.as_new ? controller_string_new_s : controller_string_existing_s);
- for (i = 0; i < rule->control_group.groups.used; ++i) {
+ if (rule.has & controller_rule_has_control_group) {
+ fprintf(data->output.stream, " %s", rule.control_group.as_new ? controller_string_new_s : controller_string_existing_s);
+
+ for (i = 0; i < rule.control_group.groups.used; ++i) {
- if (rule->control_group.groups.array[i].used) {
+ if (rule.control_group.groups.array[i].used) {
fprintf(data->output.stream, f_string_space_s);
- f_print_dynamic(data->output.stream, rule->control_group.groups.array[i]);
+ f_print_dynamic(data->output.stream, rule.control_group.groups.array[i]);
}
} // for
}
- fprintf(data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(data->output.stream, "%c", f_string_eol_s[0]);
fprintf(data->output.stream, " %s%s%s", data->context.set.important.before->string, controller_string_nice_s, data->context.set.important.after->string);
- if (rule->has & controller_rule_has_nice) {
- fprintf(data->output.stream, " %i", rule->nice);
+
+ if (rule.has & controller_rule_has_nice) {
+ fprintf(data->output.stream, " %i", rule.nice);
}
- fprintf(data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(data->output.stream, "%c", f_string_eol_s[0]);
fprintf(data->output.stream, " %s%s%s", data->context.set.important.before->string, controller_string_scheduler_s, data->context.set.important.after->string);
- if (rule->has & controller_rule_has_scheduler) {
+
+ if (rule.has & controller_rule_has_scheduler) {
f_string_t policy = "";
- if (rule->scheduler.policy == SCHED_BATCH) {
+ if (rule.scheduler.policy == SCHED_BATCH) {
policy = controller_string_batch_s;
}
- else if (rule->scheduler.policy == SCHED_DEADLINE) {
+ else if (rule.scheduler.policy == SCHED_DEADLINE) {
policy = controller_string_deadline_s;
}
- else if (rule->scheduler.policy == SCHED_FIFO) {
+ else if (rule.scheduler.policy == SCHED_FIFO) {
policy = controller_string_fifo_s;
}
- else if (rule->scheduler.policy == SCHED_IDLE) {
+ else if (rule.scheduler.policy == SCHED_IDLE) {
policy = controller_string_idle_s;
}
- else if (rule->scheduler.policy == SCHED_OTHER) {
+ else if (rule.scheduler.policy == SCHED_OTHER) {
policy = controller_string_other_s;
}
- else if (rule->scheduler.policy == SCHED_RR) {
+ else if (rule.scheduler.policy == SCHED_RR) {
policy = controller_string_round_robin_s;
}
- fprintf(data->output.stream, " %s %i", policy, rule->scheduler.priority);
+ fprintf(data->output.stream, " %s %i", policy, rule.scheduler.priority);
}
- fprintf(data->output.stream, "%c", f_string_eol_s[0]);
-
- fprintf(data->output.stream, " %s%s%s %s%c", data->context.set.important.before->string, controller_string_script_s, data->context.set.important.after->string, rule->script.used ? rule->script.string : f_string_empty_s, f_string_eol_s[0]);
+ fprintf(data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(data->output.stream, " %s%s%s %s%c", data->context.set.important.before->string, controller_string_script_s, data->context.set.important.after->string, rule.script.used ? rule.script.string : f_string_empty_s, f_string_eol_s[0]);
fprintf(data->output.stream, " %s%s%s", data->context.set.important.before->string, controller_string_user_s, data->context.set.important.after->string);
- if (rule->has & controller_rule_has_user) {
- fprintf(data->output.stream, " %i", rule->user);
+
+ if (rule.has & controller_rule_has_user) {
+ fprintf(data->output.stream, " %i", rule.user);
}
- fprintf(data->output.stream, "%c", f_string_eol_s[0]);
+ fprintf(data->output.stream, "%c", f_string_eol_s[0]);
fprintf(data->output.stream, " %s%s%s {%c", data->context.set.important.before->string, controller_string_affinity_s, data->context.set.important.after->string, f_string_eol_s[0]);
- for (i = 0; i < rule->affinity.used; ++i) {
- fprintf(data->output.stream, " %i%c", rule->affinity.array[i], f_string_eol_s[0]);
+ for (i = 0; i < rule.affinity.used; ++i) {
+ fprintf(data->output.stream, " %i%c", rule.affinity.array[i], f_string_eol_s[0]);
} // for
fprintf(data->output.stream, " }%c", f_string_eol_s[0]);
-
fprintf(data->output.stream, " %s%s%s {%c", data->context.set.important.before->string, controller_string_define_s, data->context.set.important.after->string, f_string_eol_s[0]);
- for (i = 0; i < rule->define.used; ++i) {
+ for (i = 0; i < rule.define.used; ++i) {
- if (rule->define.array[i].name.used && rule->define.array[i].value.used) {
- fprintf(data->output.stream, " %s %s=%s %s%c", rule->define.array[i].name.string, data->context.set.important.before->string, data->context.set.important.after->string, rule->define.array[i].value.string, f_string_eol_s[0]);
+ if (rule.define.array[i].name.used && rule.define.array[i].value.used) {
+ fprintf(data->output.stream, " %s %s=%s %s%c", rule.define.array[i].name.string, data->context.set.important.before->string, data->context.set.important.after->string, rule.define.array[i].value.string, f_string_eol_s[0]);
}
} // for
fprintf(data->output.stream, " }%c", f_string_eol_s[0]);
-
fprintf(data->output.stream, " %s%s%s {%c", data->context.set.important.before->string, controller_string_environment_s, data->context.set.important.after->string, f_string_eol_s[0]);
- for (i = 0; i < rule->environment.used; ++i) {
+ for (i = 0; i < rule.environment.used; ++i) {
- if (rule->environment.array[i].used) {
- fprintf(data->output.stream, " %s%c", rule->environment.array[i].string, f_string_eol_s[0]);
+ if (rule.environment.array[i].used) {
+ fprintf(data->output.stream, " %s%c", rule.environment.array[i].string, f_string_eol_s[0]);
}
} // for
fprintf(data->output.stream, " }%c", f_string_eol_s[0]);
-
fprintf(data->output.stream, " %s%s%s {%c", data->context.set.important.before->string, controller_string_group_s, data->context.set.important.after->string, f_string_eol_s[0]);
- if (rule->has & controller_rule_has_group) {
- fprintf(data->output.stream, " %i%c", rule->group, f_string_eol_s[0]);
+ if (rule.has & controller_rule_has_group) {
+ fprintf(data->output.stream, " %i%c", rule.group, f_string_eol_s[0]);
- for (i = 0; i < rule->groups.used; ++i) {
- fprintf(data->output.stream, " %i%c", rule->groups.array[i], f_string_eol_s[0]);
+ for (i = 0; i < rule.groups.used; ++i) {
+ fprintf(data->output.stream, " %i%c", rule.groups.array[i], f_string_eol_s[0]);
} // for
}
fprintf(data->output.stream, " }%c", f_string_eol_s[0]);
-
fprintf(data->output.stream, " %s%s%s {%c", data->context.set.important.before->string, controller_string_limit_s, data->context.set.important.after->string, f_string_eol_s[0]);
- for (i = 0; i < rule->limits.used; ++i) {
-
- fprintf(data->output.stream, " %s %s=%s %llu %llu%c", controller_rule_setting_limit_type_name(rule->limits.array[i].type).string, data->context.set.important.before->string, data->context.set.important.after->string, rule->limits.array[i].value.rlim_cur, rule->limits.array[i].value.rlim_max, f_string_eol_s[0]);
+ for (i = 0; i < rule.limits.used; ++i) {
+ fprintf(data->output.stream, " %s %s=%s %llu %llu%c", controller_rule_setting_limit_type_name(rule.limits.array[i].type).string, data->context.set.important.before->string, data->context.set.important.after->string, rule.limits.array[i].value.rlim_cur, rule.limits.array[i].value.rlim_max, f_string_eol_s[0]);
} // for
fprintf(data->output.stream, " }%c", f_string_eol_s[0]);
-
fprintf(data->output.stream, " %s%s%s {%c", data->context.set.important.before->string, controller_string_need_s, data->context.set.important.after->string, f_string_eol_s[0]);
- for (i = 0; i < rule->need.used; ++i) {
+ for (i = 0; i < rule.need.used; ++i) {
- if (rule->need.array[i].used) {
- fprintf(data->output.stream, " %s%c", rule->need.array[i].string, f_string_eol_s[0]);
+ if (rule.need.array[i].used) {
+ fprintf(data->output.stream, " %s%c", rule.need.array[i].string, f_string_eol_s[0]);
}
} // for
fprintf(data->output.stream, " %s%s%s {%c", data->context.set.important.before->string, controller_string_parameter_s, data->context.set.important.after->string, f_string_eol_s[0]);
- for (i = 0; i < rule->parameter.used; ++i) {
+ for (i = 0; i < rule.parameter.used; ++i) {
- if (rule->parameter.array[i].name.used && rule->parameter.array[i].value.used) {
- fprintf(data->output.stream, " %s %s=%s %s%c", rule->parameter.array[i].name.string, data->context.set.important.before->string, data->context.set.important.after->string, rule->parameter.array[i].value.string, f_string_eol_s[0]);
+ if (rule.parameter.array[i].name.used && rule.parameter.array[i].value.used) {
+ fprintf(data->output.stream, " %s %s=%s %s%c", rule.parameter.array[i].name.string, data->context.set.important.before->string, data->context.set.important.after->string, rule.parameter.array[i].value.string, f_string_eol_s[0]);
}
} // for
fprintf(data->output.stream, " }%c", f_string_eol_s[0]);
-
fprintf(data->output.stream, " %s%s%s {%c", data->context.set.important.before->string, controller_string_want_s, data->context.set.important.after->string, f_string_eol_s[0]);
- for (i = 0; i < rule->want.used; ++i) {
+ for (i = 0; i < rule.want.used; ++i) {
- if (rule->want.array[i].used) {
- fprintf(data->output.stream, " %s%c", rule->want.array[i].string, f_string_eol_s[0]);
+ if (rule.want.array[i].used) {
+ fprintf(data->output.stream, " %s%c", rule.want.array[i].string, f_string_eol_s[0]);
}
} // for
fprintf(data->output.stream, " }%c", f_string_eol_s[0]);
-
fprintf(data->output.stream, " %s%s%s {%c", data->context.set.important.before->string, controller_string_wish_s, data->context.set.important.after->string, f_string_eol_s[0]);
- for (i = 0; i < rule->wish.used; ++i) {
+ for (i = 0; i < rule.wish.used; ++i) {
- if (rule->wish.array[i].used) {
- fprintf(data->output.stream, " %s%c", rule->wish.array[i].string, f_string_eol_s[0]);
+ if (rule.wish.array[i].used) {
+ fprintf(data->output.stream, " %s%c", rule.wish.array[i].string, f_string_eol_s[0]);
}
} // for
fprintf(data->output.stream, " }%c", f_string_eol_s[0]);
- if (rule->items.used) {
+ if (rule.items.used) {
controller_rule_action_t *action = 0;
controller_rule_item_t *item = 0;
f_string_dynamic_t *parameter = 0;
f_array_length_t j = 0;
f_array_length_t k = 0;
- for (i = 0; i < rule->items.used; ++i) {
+ for (i = 0; i < rule.items.used; ++i) {
- item = &rule->items.array[i];
+ item = &rule.items.array[i];
fprintf(data->output.stream, " %s%s%s {%c", data->context.set.important.before->string, controller_string_item_s, data->context.set.important.after->string, f_string_eol_s[0]);
-
fprintf(data->output.stream, " %s%s%s %s%c", data->context.set.important.before->string, controller_string_type_s, data->context.set.important.after->string, controller_rule_item_type_name(item->type).string, f_string_eol_s[0]);
for (j = 0; j < item->actions.used; ++j) {
action = &item->actions.array[j];
fprintf(data->output.stream, " %s%s%s {%c", data->context.set.important.before->string, controller_string_action_s, data->context.set.important.after->string, f_string_eol_s[0]);
-
fprintf(data->output.stream, " %s%s%s %s%c", data->context.set.important.before->string, controller_string_type_s, data->context.set.important.after->string, controller_rule_action_type_name(action->type).string, f_string_eol_s[0]);
if (item->type == controller_rule_item_type_script) {
fprintf(data->output.stream, "}%c", f_string_eol_s[0]);
- setting->rules.array[index].status = F_complete;
+ main.setting->rules.array[index].status = F_complete;
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&main.thread->lock.print);
}
#endif // _di_controller_rule_simulate_
#ifndef _di_controller_rule_wait_all_
- void controller_rule_wait_all(controller_thread_t *thread) {
+ void controller_rule_wait_all(const controller_main_t main) {
- for (f_array_length_t i = 0; i < thread->asynchronouss.used && thread->enabled; ++i) {
+ f_thread_lock_read(&main.thread->lock.process);
- // 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) {
- continue;
- }
+ controller_process_t *process = 0;
- if (thread->asynchronouss.array[i].index >= thread->setting->rules.used) {
- continue;
- }
+ for (f_array_length_t i = 0; i < main.thread->processs.used && main.thread->enabled; ++i) {
- f_thread_mutex_lock(&thread->setting->rules.array[thread->asynchronouss.array[i].index].lock);
+ process = &main.thread->processs.array[i];
- 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_lock_read(&process->active);
+ f_thread_lock_read(&process->lock);
- f_thread_mutex_unlock(&thread->setting->rules.array[thread->asynchronouss.array[i].index].lock);
+ if (process->state == controller_process_state_idle || process->state == controller_process_state_done) {
- if (!thread->enabled) break;
+ if (process->state == controller_process_state_done) {
+ f_thread_unlock(&process->lock);
+ f_thread_lock_write(&process->lock);
- if (f_thread_mutex_lock_try(&thread->lock.asynchronous) == F_none) {
+ if (process->state == controller_process_state_done) {
+ f_thread_join(process->id_thread, 0);
- if (thread->asynchronouss.array[i].state != controller_asynchronous_state_joined) {
- f_thread_join(thread->asynchronouss.array[i].id, 0);
+ process->state = controller_process_state_idle;
+ }
}
- 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;
- }
+ f_thread_unlock(&process->active);
+ f_thread_unlock(&process->lock);
- controller_macro_cache_action_t_clear(thread->asynchronouss.array[i].cache);
- }
+ continue;
+ }
+
+ f_thread_condition_wait(&process->wait, &process->running);
+
+ if (process->state == controller_process_state_done) {
+ f_thread_unlock(&process->lock);
+ f_thread_lock_write(&process->lock);
- f_thread_mutex_unlock(&thread->lock.asynchronous);
+ if (process->state == controller_process_state_done) {
+ f_thread_join(process->id_thread, 0);
+
+ process->state = controller_process_state_idle;
+ }
}
+
+ f_thread_unlock(&process->lock);
+
+ // always pass the signal along when done waiting.
+ f_thread_condition_signal(&process->wait);
+ f_thread_mutex_unlock(&process->running);
+
+ f_thread_unlock(&process->active);
} // for
+
+ f_thread_unlock(&main.thread->lock.process);
}
#endif // _di_controller_rule_wait_all_
#endif // _di_controller_rule_action_method_name_
/**
+ * Find the location of the Rule by the Rule alias.
+ *
+ * @param alias
+ * The Rule alias to find.
+ * @param rules
+ * The rules to search through.
+ * @param at
+ * The index the rule was found at.
+ *
+ * @return
+ * F_none on success, but the id.used is 0.
+ * F_true on success and rule was found, index is updated.
+ * F_false on success and rule was not found.
+ */
+#ifndef _di_controller_rule_find_
+ extern f_status_t controller_rule_find(const f_string_static_t alias, const controller_rules_t rules, f_array_length_t *at) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_rule_find_
+
+/**
* Read the parameters for some rule action.
*
* The object and content ranges are merged together (in that order) as the action parameters.
* @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_data
- * The thread data.
+ * @param main
+ * The main data.
* @param cache
* A structure for containing and caching relevant data.
* @param rule
* 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 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;
+ extern f_status_t controller_rule_execute(const uint8_t type, const uint8_t options, controller_main_t main, controller_cache_t *cache, controller_rule_t *rule) f_gcc_attribute_visibility_internal;
#endif // _di_controller_rule_execute_
/**
* 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_data
- * The thread data.
+ * @param main
+ * The main data.
* @param rule
* The rule to process.
*
* @see fll_execute_program()
*/
#ifndef _di_controller_rule_execute_foreground_
- 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;
+ 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_main_t main, controller_rule_t *rule) f_gcc_attribute_visibility_internal;
#endif // _di_controller_rule_execute_foreground_
/**
* 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
- * The thread data.
+ * @param main
+ * The main 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.
* @see fll_execute_program()
*/
#ifndef _di_controller_rule_execute_pid_with_
- 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;
+ 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_main_t main, 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.
- *
- * 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.
- *
- * This does not do any locking or unlocking, be sure to lock appropriately before and after calling this.
- *
- * @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 f_string_static_t rule_id, controller_thread_data_t thread_data) f_gcc_attribute_visibility_internal;
-#endif // _di_controller_rule_find_loaded_
-
-/**
* Construct an id from two distinct strings found within a single given source.
*
* @param data
* A range within the source representing the directory part of a rule id.
* @param basename
* A range within the source representing the basename part of a rule id.
- * @param id
- * The constructed id.
+ * @param alias
+ * The constructed alias.
*
* @return
* F_none on success.
* @see f_string_dynamic_terminate_after()
*/
#ifndef _di_controller_rule_id_construct_
- extern f_status_t controller_rule_id_construct(const controller_data_t data, const f_string_static_t source, const f_string_range_t directory, const f_string_range_t basename, f_string_dynamic_t *id) f_gcc_attribute_visibility_internal;
+ extern f_status_t controller_rule_id_construct(const controller_data_t data, const f_string_static_t source, const f_string_range_t directory, const f_string_range_t basename, f_string_dynamic_t *alias) f_gcc_attribute_visibility_internal;
#endif // _di_controller_rule_id_construct_
/**
#endif // _di_controller_rule_path_
/**
- * Synchronously process and execute the given rule by the rule id.
+ * Process and execute the given rule.
*
- * Any dependent rules are loaded and executed as per "need", "want", and "wish" rule settings.
+ * Any dependent rules are processed and executed as per "need", "want", and "wish" rule settings.
* All dependent rules must be already loaded, this function will not load any rules.
*
+ * @fixme recursion is no longer happening is it?
* 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 rule
* The rule information at the time the rule process started.
- * @param at_process
- * The position within the processs array representing this rule process.
* @param action
* The action to perform based on the action type codes.
*
* 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_data
- * The thread data.
- * @param cache
- * A structure for containing and caching relevant data.
+ * @param main
+ * The main data.
+ * @param process
+ * The process data for processing this rule.
*
* @return
* F_none on success.
* F_signal on (exit) signal received.
*/
#ifndef _di_controller_rule_process_
- extern f_status_t controller_rule_process(const controller_rule_t rule, const f_array_length_t at_process, const uint8_t action, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache) f_gcc_attribute_visibility_internal;
+ extern f_status_t controller_rule_process(const controller_rule_t rule, const uint8_t action, const uint8_t options, const controller_main_t main, controller_process_t *process) f_gcc_attribute_visibility_internal;
#endif // _di_controller_rule_process_
/**
- * Asynchronously process and execute the given rule by the rule id.
+ * Synchronously or Asynchronously begin processing some rule.
*
- * Any dependent rules are loaded and executed as per "need", "want", and "wish" rule settings.
- * All dependent rules must be already loaded, this function will not load any rules.
- *
- * 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 id_rule
- * The ID of the rule, such as "boot/init".
+ * @param asynchronous
+ * If TRUE, then asynchronously execute a process.
+ * If FALSE, then synchronously execute a process.
+ * @param alias_rule
+ * The alias of the rule, such as "boot/init".
* @param action
* The action to perform based on the action type codes.
- *
- * Only subset of the action type codes are supported:
- * - controller_rule_action_type_kill
- * - controller_rule_action_type_reload
- * - controller_rule_action_type_restart
- * - controller_rule_action_type_start
- * - controller_rule_action_type_stop
* @param options
* A number using bits to represent specific boolean options.
- * 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_data
- * The thread data.
+ * @param stack
+ * A stack representing the processes already running in this rule process dependency tree.
+ * This is used to prevent circular dependencies.
+ * @param main
+ * The main data.
* @param cache
* A structure for containing and caching relevant data.
*
* @return
* F_none on success.
+ * F_busy on success and the process was found to already be running (nothing to do).
* F_signal on (exit) signal received.
*
- * Errors (with error bit) from: controller_asynchronouss_increase().
+ * F_found_not (with error bit) if unable to for a process for the given rule id.
+ * F_recurse (with error bit) on recursion error (the process is already on the process stack).
+ *
+ * Status from: controller_rule_process().
+ *
+ * Errors (with error bit) from: controller_rule_process().
* Errors (with error bit) from: f_string_dynamic_append().
* Errors (with error bit) from: f_thread_create().
+ *
+ * @see controller_rule_process()
+ * @see f_string_dynamic_append()
+ * @see f_thread_create()
*/
-#ifndef _di_controller_rule_process_asynchronous_
- extern f_status_t controller_rule_process_asynchronous(const f_string_static_t id_rule, 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_
+#ifndef _di_controller_rule_process_begin_
+ extern f_status_t controller_rule_process_begin(const bool asynchronous, const f_string_static_t alias_rule, const uint8_t action, const uint8_t options, const f_array_lengths_t stack, const controller_main_t main, controller_cache_t *cache) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_rule_process_begin_
+
+/**
+ * Helper for calling controller_rule_process().
+ *
+ * This does all the preparation work that needs to be synchronously performed within the same thread.
+ *
+ * @param asynchronous
+ * If TRUE, designates that this function is being asynchronously executed.
+ * If FALSE, designates that this function is being synchronously executed.
+ * @param process
+ * The process data.
+ *
+ * @return
+ * F_none on success.
+ * F_found on success and the process was found to already be running (nothing to do).
+ * F_signal on (exit) signal received.
+ *
+ * F_found_not (with error bit) if unable to for a process for the given rule id.
+ *
+ * Status from: controller_rule_process().
+ *
+ * Errors (with error bit) from: controller_rule_copy().
+ * Errors (with error bit) from: controller_rule_process().
+ *
+ * @see controller_rule_copy()
+ * @see controller_rule_process()
+ * @see controller_rule_process_begin()
+ */
+#ifndef _di_controller_rule_process_do_
+ extern f_status_t controller_rule_process_do(const bool asynchronous, controller_process_t *process) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_rule_process_do_
/**
* Read the rule file, extracting all valid items.
* 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.
+ * @param main
+ * The main data.
* @param cache
* A structure for containing and caching relevant data.
* @param rule
* @see fll_fss_basic_list_read().
*/
#ifndef _di_controller_rule_read_
- 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;
+ extern f_status_t controller_rule_read(const f_string_static_t rule_id, controller_main_t main, controller_cache_t *cache, controller_rule_t *rule) f_gcc_attribute_visibility_internal;
#endif // _di_controller_rule_read_
/**
*
* This automatically sets the rule's status to F_complete.
*
+ * @param rule
+ * The rule to process.
* @param action
* The action to perform based on the action type codes.
*
* 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_data
- * The thread data.
+ * @param main
+ * The main 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 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;
+ extern void controller_rule_simulate(const controller_rule_t rule, const uint8_t action, const uint8_t options, const controller_main_t main, controller_cache_t *cache) f_gcc_attribute_visibility_internal;
#endif // _di_controller_rule_simulate_
/**
- * Wait until all currently running asynchronous execution threads are complete.
+ * Wait until all currently running Rule processes are complete.
*
- * @param thread
- * The thread data.
+ * @param main
+ * The main data.
*/
#ifndef _di_controller_rule_wait_all_
- extern void controller_rule_wait_all(controller_thread_t *thread) f_gcc_attribute_visibility_internal;
+ extern void controller_rule_wait_all(const controller_main_t main) f_gcc_attribute_visibility_internal;
#endif // _di_controller_rule_wait_all_
#ifdef __cplusplus
extern "C" {
#endif
-#ifndef _di_controller_thread_asynchronous_process_
- void * controller_thread_asynchronous_process(void *arguments) {
-
- controller_asynchronous_t *asynchronous = (controller_asynchronous_t *) arguments;
- controller_thread_t *main = (controller_thread_t *) asynchronous->thread;
-
- f_thread_lock_read(&main->lock.asynchronous);
-
- if (!main->enabled) {
- f_thread_unlock(&main->lock.asynchronous);
-
- return 0;
- }
-
- f_thread_unlock(&main->lock.asynchronous);
-
- f_array_length_t at_process = 0;
-
- f_thread_lock_read(&main->thread->lock.process);
-
- if (controller_find_process(rule.id, *main->processs, &at_process) == F_false) {
- f_thread_unlock(&main->thread->lock.process);
- f_thread_lock_write(&main->thread->lock.process);
-
- const f_status_t status = controller_processs_increase(main->processs);
-
- if (F_status_is_error(status)) {
- controller_entry_error_print(main->data->error, asynchronous->cache->action, F_status_set_fine(status), "controller_processs_increase", F_true, main->thread);
-
- f_thread_unlock(&main->thread->lock.process);
- return 0;
- }
- else {
- at_process = main->processs->used++;
- }
- }
-
- // once the "active" lock is in place for some process, then it will not be deleted and should be guaranteed to not change or be relocated.
- f_thread_lock_read(&main->processs.array[id_process].active);
- f_thread_unlock(&main->thread->lock.process);
-
- // @todo looks like I do need a r/w lock on controller_asynchronous_t after all.
-
- controller_rule_t rule = controller_rule_t_initialize;
-
- // @todo copy rule, finding the rule using main->processs.array[id_process].id_rule.
- //status = controller_rule_copy(, &rule);
-
- {
- const f_status_t status = controller_rule_process(rule, at_process, controller_rule_action_type_start, rule_options, thread_data, asynchronous->cache);
-
- asynchronous->state = controller_asynchronous_state_done;
-
- if (F_status_is_error(status)) {
- f_thread_mutex_lock(&thread_data.thread->lock.print);
-
- controller_entry_error_print_cache(thread_data.data->error, asynchronous->cache->action);
-
- f_thread_mutex_unlock(&thread_data.thread->lock.print);
- }
- }
-
- f_thread_unlock(&main->processs.array[id_process].active);
-
- return 0;
- }
-#endif // _di_controller_thread_asynchronous_process_
-
-#ifndef _di_controller_thread_asynchronous_cancel_
- void controller_thread_asynchronous_cancel(controller_thread_t *thread) {
-
- thread->enabled = F_false;
-
- f_thread_mutex_lock(&thread->lock.asynchronous);
+#ifndef _di_controller_thread_cleanup_
+ void * controller_thread_cleanup(void *arguments) {
- for (f_array_length_t i = 0; i < thread->asynchronouss.used; ++i) {
+ const controller_main_t *main = (controller_main_t *) arguments;
- if (!thread->asynchronouss.array[i].state) continue;
+ const unsigned int interval = main->data->parameters[controller_parameter_test].result == f_console_result_found ? controller_thread_cache_cleanup_interval_short : controller_thread_cache_cleanup_interval_long;
- if (f_thread_mutex_lock_try(&thread->asynchronouss.array[i].lock) == F_none) {
- f_thread_cancel(thread->asynchronouss.array[i].id);
- f_thread_detach(thread->asynchronouss.array[i].id);
- f_thread_mutex_unlock(&thread->asynchronouss.array[i].lock);
- }
- else {
- if (thread->asynchronouss.array[i].child > 0) {
- f_signal_send(F_signal_termination, thread->asynchronouss.array[i].child);
- }
- else {
- f_thread_cancel(thread->asynchronouss.array[i].id);
- }
+ while (main->thread->enabled) {
- // the cancel make take time so detach the process to allow it to exit on its own.
- f_thread_detach(thread->asynchronouss.array[i].id);
- }
- } // for
+ sleep(interval);
- thread->asynchronouss.used = 0;
+ if (f_thread_lock_write_try(&main->thread->lock.process) == F_none) {
+ controller_process_t *process = 0;
- f_thread_unlock(&thread->lock.asynchronous);
- }
-#endif // _di_controller_thread_asynchronous_cancel_
+ // index 0 is reserved for "main thread".
+ f_array_length_t i = 1;
-#ifndef _di_controller_thread_cleanup_
- void * controller_thread_cleanup(void *arguments) {
+ for (; j < main->thread->processs.used; ++i) {
- controller_thread_data_t *thread_data = (controller_thread_data_t *) arguments;
+ process = &main->thread->processs.array[i];
- 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;
+ if (f_thread_lock_write_try(&process->active) != F_none) {
+ continue;
+ }
- for (; thread_data->thread->enabled; ) {
- sleep(interval);
+ if (f_thread_lock_write_try(&process->lock) != F_none) {
+ f_thread_unlock(&process->active);
- /*
- if (f_thread_lock_write_try(&thread_data->thread->lock.asynchronous) == F_none) {
- controller_thread_t *thread = &thread_data->thread;
+ continue;
+ }
- if (thread->asynchronouss.used) {
- for (i = 0; i < thread->asynchronouss.used; ++i) {
+ if (process->state == controller_process_state_active || process->state == controller_process_state_busy) {
+ f_thread_unlock(&process->active);
+ f_thread_unlock(&process->lock);
- if (!thread->enabled) break;
- if (!thread->asynchronouss.array[i].state) continue;
+ continue;
+ }
- if (f_thread_lock_write_try(&thread->asynchronouss.array[i].lock) != F_none) continue;
+ if (process->state == controller_process_state_done) {
+ f_thread_detach(process->id_thread);
+ process->state = controller_process_state_idle;
+ }
- if (f_thread_lock_write_try(&thread_data->setting->rules.array[thread->asynchronouss.array[i].index].lock) == F_none) {
+ // deallocate dynamic portions of the structure that are only ever needed while the process is running.
+ controller_cache_delete_simple(&process->cache);
+ f_type_array_lengths_resize(0, &process->stack);
- 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;
- }
+ f_thread_unlock(&process->active);
+ f_thread_unlock(&process->lock);
+ } // for
- if (thread->asynchronouss.array[i].state == controller_asynchronous_state_joined) {
- controller_macro_asynchronous_t_delete_simple(thread->asynchronouss.array[i]);
+ for (i = main->thread->processs.used - 1; main->thread->processs.used; --i, --main->thread->processs.used) {
- thread->asynchronouss.array[i].state = 0;
- }
+ process = &main->thread->processs.array[i];
- 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);
- }
+ if (f_thread_lock_write_try(&process->active) != F_none) {
+ break;
+ }
- f_thread_mutex_unlock(&thread->asynchronouss.array[i].lock);
- } // for
+ if (f_thread_lock_write_try(&process->lock) != F_none) {
+ f_thread_unlock(&process->active);
- for (i = thread->asynchronouss.used - 1; thread->asynchronouss.used; --i, --thread->asynchronouss.used) {
+ break;
+ }
- if (!thread->enabled) break;
+ if (process->state == controller_process_state_active || process->state == controller_process_state_busy) {
+ f_thread_unlock(&process->active);
+ f_thread_unlock(&process->lock);
- if (f_thread_mutex_lock_try(&thread->asynchronouss.array[i].lock) != F_none) break;
+ break;
+ }
- if (thread->asynchronouss.array[i].state == controller_asynchronous_state_joined) {
- controller_macro_asynchronous_t_delete_simple(thread->asynchronouss.array[i]);
+ if (process->state == controller_process_state_done) {
+ f_thread_detach(process->id_thread);
+ process->state = controller_process_state_idle;
+ }
- thread->asynchronouss.array[i].state = 0;
- }
- else if (thread->asynchronouss.array[i].state) {
- f_thread_unlock(&thread->asynchronouss.array[i].lock);
- break;
- }
+ // deallocate dynamic portions of the structure that are only ever needed while the process is running.
+ controller_cache_delete_simple(&process->cache);
+ f_type_array_lengths_resize(0, &process->stack);
- f_thread_unlock(&thread->asynchronouss.array[i].lock);
- } // for
- }
+ --main->thread->processs.used;
- if (thread->enabled && thread->asynchronouss.used < thread->asynchronouss.size) {
- controller_asynchronouss_resize(thread->asynchronouss.used, &thread->asynchronouss);
- }
+ f_thread_unlock(&process->active);
+ f_thread_unlock(&process->lock);
+ } // for
- f_thread_unlock(&thread->lock.asynchronous);
+ f_thread_unlock(&main->thread->lock.process);
}
- */
- } // for
+ } // while
return 0;
}
#ifndef _di_controller_thread_control_
void * controller_thread_control(void *arguments) {
- controller_thread_data_t *thread_data = (controller_thread_data_t *) arguments;
+ controller_main_t *main = (controller_main_t *) arguments;
// @todo
f_status_t status = F_none;
controller_thread_t thread = controller_thread_t_initialize;
- controller_processs_t processs = controller_processs_t_initialize;
- controller_thread_data_t thread_data = controller_macro_thread_data_t_initialize(0, data, setting, &processs, &thread);
+ controller_main_t main = controller_macro_main_t_initialize(data, setting, &thread);
- status = controller_asynchronouss_increase(&thread.asynchronouss);
+ // the main locks must be initialized, but only once, so initialize immediately upon allocation.
+ status = controller_lock_create(&thread.lock);
- if (F_status_is_error_not(status)) {
- status = f_thread_create(0, &thread.id_signal, &controller_thread_signal, (void *) &thread_data);
+ if (F_status_is_error(status)) {
+ if (data->error.verbosity != f_console_verbosity_quiet) {
+ fll_error_print(data->error, status, "controller_lock_create", F_true);
+ }
}
+ else {
+ status = controller_processs_increase(&thread.processs);
+
+ if (F_status_is_error(status)) {
+ controller_error_print(data->error, F_status_set_fine(status), "controller_processs_increase", F_true, &thread);
+ }
+ }
+
+ if (F_status_is_error_not(status)) {
+ status = f_thread_create(0, &thread.id_signal, &controller_thread_signal, (void *) &main);
- if (F_status_is_error(status)) {
if (data->error.verbosity != f_console_verbosity_quiet) {
controller_error_print(data->error, F_status_set_fine(status), "f_thread_create", F_true, &thread);
}
}
- else {
+
+ if (F_status_is_error_not(status)) {
if (data->parameters[controller_parameter_daemon].result == f_console_result_found) {
setting->ready = controller_setting_ready_done;
if (f_file_exists(setting->path_pid.string) == F_true) {
if (data->error.verbosity != f_console_verbosity_quiet) {
+
f_thread_mutex_lock(&thread.lock.print);
fprintf(data->error.to.stream, "%c", f_string_eol_s[0]);
else {
// index 0 is reserved for running the main thread cache.
- thread.asynchronouss.used = 1;
+ thread.processs.used = 1;
- status = controller_entry_read(entry_name, thread_data, &thread.asynchronouss.array[0].cache);
+ status = controller_entry_read(entry_name, main, &thread.processs.array[0].cache);
if (F_status_is_error(status)) {
setting->ready = controller_setting_ready_fail;
}
else if (status != F_signal && status != F_child) {
- status = controller_preprocess_entry(thread_data, &thread.asynchronouss.array[0].cache);
+ status = controller_preprocess_entry(main, &thread.processs.array[0].cache);
}
if (F_status_is_error_not(status) && status != F_signal && status != F_child) {
+
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(setting->path_pid.string) == F_true) {
if (data->error.verbosity != f_console_verbosity_quiet) {
+
f_thread_mutex_lock(&thread.lock.print);
fprintf(data->error.to.stream, "%c", f_string_eol_s[0]);
status = F_status_set_error(F_available_not);
}
else {
- status = controller_process_entry(thread_data, &thread.asynchronouss.array[0].cache);
+ status = controller_process_entry(main, &thread.processs.array[0].cache);
if (F_status_is_error(status)) {
setting->ready = controller_setting_ready_fail;
status = F_signal;
}
- // only make the rule and control threads available once any/all pre-processing and is completed.
+ // only make the rule and control threads available once any/all pre-processing and are completed.
if (F_status_is_error_not(status) && status != F_signal && status != F_child) {
if (data->parameters[controller_parameter_validate].result == f_console_result_none) {
- controller_rule_wait_all(&thread);
-
- status = f_thread_create(0, &thread.id_rule, &controller_thread_rule, (void *) &thread_data);
+ controller_rule_wait_all(main);
- if (F_status_is_error_not(status)) {
- status = f_thread_create(0, &thread.id_control, &controller_thread_control, (void *) &thread_data);
- }
+ status = f_thread_create(0, &thread.id_control, &controller_thread_control, (void *) &main);
if (F_status_is_error_not(status)) {
- status = f_thread_create(0, &thread.id_cleanup, &controller_thread_cleanup, (void *) &thread_data);
+ status = f_thread_create(0, &thread.id_cleanup, &controller_thread_cleanup, (void *) &main);
}
if (F_status_is_error(status)) {
}
if (thread.enabled) {
- controller_thread_asynchronous_cancel(&thread);
+ controller_thread_process_cancel(main);
}
- // @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_detach(thread.id_cleanup);
+ f_thread_detach(thread.id_control);
- controller_processs_delete_simple(&processs);
controller_thread_delete_simple(&thread);
if (F_status_is_error(status)) {
}
#endif // _di_controller_thread_main_
-#ifndef _di_controller_thread_rule_
- void * controller_thread_rule(void *arguments) {
-
- controller_thread_data_t *thread_data = (controller_thread_data_t *) arguments;
+#ifndef _di_controller_thread_process_
+ void * controller_thread_process(void *arguments) {
- // @todo
- // f_thread_mutex_lock(&thread_data->lock.rule);
- // f_thread_mutex_unlock(&thread_data->lock.rule);
+ controller_rule_process_do(F_true, (controller_process_t *) arguments);
return 0;
}
-#endif // _di_controller_thread_rule_
+#endif // _di_controller_thread_process_
+
+#ifndef _di_controller_thread_process_cancel_
+ void controller_thread_process_cancel(const controller_main_t main) {
+
+ // this must be set, regardless of lock state and only this function changes this.
+ main.thread->enabled = F_false;
+
+ f_thread_lock_write(&main.thread->lock.process);
+
+ if (!main.thread->processs.used) {
+ f_thread_unlock(&main.thread->lock.process);
+
+ return;
+ }
+
+ controller_process_t *process = 0;
+
+ bool locked = 0;
+
+ //pid_t[main.thread->processs.used] pids;
+ //memset(&pids, 0, sizeof(pid_t) * main.thread->processs.used);
+
+ // index 0 is reserved for running the main thread cache.
+ for (f_array_length_t i = 1; i < main.thread->processs.used; ++i) {
+
+ process = &main.thread->processs.array[i];
+
+ locked = f_thread_lock_write_try(&process->lock) == F_none;
+
+ if (!locked) {
+ locked = f_thread_lock_read_try(&process->lock) == F_none;
+ }
+
+ if (locked) {
+ if (process->child > 0) {
+ f_signal_send(F_signal_quit, process->child);
+ }
+
+ if (process->state == controller_process_state_active || process->state == controller_process_state_busy) {
+ f_thread_cancel(process->id_thread);
+ f_thread_detach(process->id_thread);
+ }
+ else if (process->state == controller_process_state_done) {
+ f_thread_detach(process->id_thread);
+ }
+
+ f_thread_unlock(&process->lock);
+ }
+ } // for
+
+ main.thread->processs.used = 0;
+
+ // @todo: sleep a little, check to see if child processes quit, and if not then sen F_signal_quit_termination.
+ // this will likely need to be done by:
+ // 1) create an array of child process ids from above loop.
+ // 2) search through loop at this location in the code and if the process id is found, sleep a little.
+ // 3) check again to see if the child process quit and if not, then send the F_signal_quit_termination.
+ // 4) continue to next child until entire array is processed.
+
+ f_thread_unlock(&main.thread->lock.process);
+ }
+#endif // _di_controller_thread_process_cancel_
#ifndef _di_controller_thread_signal_
void * controller_thread_signal(void *arguments) {
- controller_thread_data_t *thread_data = (controller_thread_data_t *) arguments;
+ controller_main_t *main = (controller_main_t *) arguments;
- for (int signal = 0; thread_data->thread->enabled; ) {
+ for (int signal = 0; main->thread->enabled; ) {
- sigwait(&thread_data->data->signal.set, &signal);
+ sigwait(&main->data->signal.set, &signal);
- if (thread_data->data->parameters[controller_parameter_interruptable].result == f_console_result_found) {
+ if (main->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_data->thread->signal = signal;
+ main->thread->signal = signal;
- controller_thread_asynchronous_cancel(thread_data->thread);
+ controller_thread_process_cancel(*main);
break;
}
}
#endif
/**
- * Asynchronously execute a process.
- *
- * @param arguments
- * The thread arguments.
- * Must be of type controller_asynchronous_t.
- *
- * @return
- * 0, always.
- */
-#ifndef _di_controller_thread_asynchronous_process_
- extern void * controller_thread_asynchronous_process(void *arguments) f_gcc_attribute_visibility_internal;
-#endif // _di_controller_thread_asynchronous_process_
-
-/**
- * Cancel all asynchronous threads.
- *
- * @param thread
- * The thread data.
- */
-#ifndef _di_controller_thread_asynchronous_cancel_
- void controller_thread_asynchronous_cancel(controller_thread_t *thread) f_gcc_attribute_visibility_internal;
-#endif // _di_controller_thread_asynchronous_cancel_
-
-/**
* Thread for periodically cleanup data when not busy.
*
* @param arguments
* The thread arguments.
- * Must be of type controller_thread_data_t.
+ * Must be of type controller_main_t.
*
* @return
* 0, always.
*
* @param arguments
* The thread arguments.
- * Must be of type controller_thread_data_t.
+ * Must be of type controller_main_t.
*
* @return
* 0, always.
#endif // _di_controller_thread_main_
/**
- * Thread for handling loading of rules into memory.
+ * Asynchronously execute a Rule process.
*
* @param arguments
* The thread arguments.
- * Must be of type controller_thread_data_t.
+ * Must be of type controller_process_t.
*
* @return
* 0, always.
+ *
+ * @see controller_rule_process_do()
+ */
+#ifndef _di_controller_thread_process_
+ extern void * controller_thread_process(void *arguments) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_thread_process_
+
+/**
+ * Cancel all process threads.
+ *
+ * @param main
+ * The main thread data.
*/
-#ifndef _di_controller_thread_rule_
- extern void * controller_thread_rule(void *arguments) f_gcc_attribute_visibility_internal;
-#endif // _di_controller_thread_rule_
+#ifndef _di_controller_thread_process_cancel_
+ void controller_thread_process_cancel(const controller_main_t main) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_thread_process_cancel_
/**
* Thread for handling signals/interrupts.
*
* @param arguments
* The thread arguments.
- * Must be of type controller_thread_data_t.
+ * Must be of type controller_main_t.
*
* @return
* 0, always.