* This program provides system service management, much like sysvcontroller and controllerng.
* This program can be controlled from user-space via the "control" program.
*
- * @todo research containers and build in container support into this, providing "container" appropriate verbiage for individual rules.
- * @todo research namespaces and user_namespaces, they may be important to support.
- *
* @todo Implement "exit" files that are the opposite of "entry" files whereas rules specified within are all called via the "stop" action type.
* This would then allow for switching modes.
+ *
+ * @fixme the entire program needs to check the return status on all locks (mutex, r/w locks, etc..) and if there is a problem, print a message and wait (but ideally allow for signals, if enabled).
+ *
+ * @todo This currently only exits on memory error.
+ * For a production "init" program, this should continue to run...so it needs to sleep and wait for resources to become available.
*/
#ifndef _controller_h
f_macro_array_lengths_t_delete_simple(asynchronous->stack)
controller_cache_delete_simple(&asynchronous->cache);
- controller_rule_delete_simple(&asynchronous->rule);
}
#endif // _di_controller_asynchronous_delete_simple_
}
#endif // _di_controller_entry_items_delete_simple_
-#ifndef _di_controller_error_print_locked_
- void controller_error_print_locked(const fll_error_print_t error, const f_status_t status, const f_string_t function, const bool fallback, controller_thread_t *thread) {
+#ifndef _di_controller_error_print_
+ void controller_error_print(const fll_error_print_t print, const f_status_t status, const f_string_t function, const bool fallback, controller_thread_t *thread) {
- if (error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread->mutex.print);
+ if (print.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&thread->lock.print);
- fll_error_print(error, status, function, fallback);
+ fll_error_print(print, status, function, fallback);
- f_thread_mutex_unlock(&thread->mutex.print);
+ f_thread_mutex_unlock(&thread->lock.print);
}
}
-#endif // _di_controller_error_print_locked_
+#endif // _di_controller_error_print_
#ifndef _di_controller_process_delete_simple_
void controller_process_delete_simple(controller_process_t *process) {
f_string_dynamic_resize(0, &process->id);
- f_thread_mutex_delete(&process->lock);
+
+ f_thread_lock_delete(&process->lock);
+ f_thread_lock_attribute_delete(&process->attribute);
f_thread_condition_delete(&process->wait);
}
#endif // _di_controller_process_delete_simple_
#ifndef _di_controller_rule_delete_simple_
void controller_rule_delete_simple(controller_rule_t *rule) {
- f_macro_thread_mutex_t_delete_simple(rule->lock)
- f_macro_thread_condition_t_delete_simple(rule->wait)
- f_macro_string_maps_t_delete_simple(rule->define)
- f_macro_string_maps_t_delete_simple(rule->parameter)
- f_macro_string_dynamics_t_delete_simple(rule->environment)
- f_macro_string_dynamics_t_delete_simple(rule->need)
- f_macro_string_dynamics_t_delete_simple(rule->want)
- f_macro_string_dynamics_t_delete_simple(rule->wish)
- f_macro_int32s_t_delete_simple(rule->affinity)
- f_macro_control_group_t_delete_simple(rule->control_group)
- f_macro_int32s_t_delete_simple(rule->groups)
- f_macro_limit_sets_t_delete_simple(rule->limits)
-
f_string_dynamic_resize(0, &rule->id);
f_string_dynamic_resize(0, &rule->name);
f_string_dynamic_resize(0, &rule->path);
f_string_dynamic_resize(0, &rule->script);
+ f_string_maps_resize(0, &rule->define);
+ f_string_maps_resize(0, &rule->parameter);
+
+ f_string_dynamics_resize(0, &rule->environment);
+ f_string_dynamics_resize(0, &rule->need);
+ f_string_dynamics_resize(0, &rule->want);
+ f_string_dynamics_resize(0, &rule->wish);
+
+ f_macro_int32s_t_delete_simple(rule->affinity)
+ f_macro_control_group_t_delete_simple(rule->control_group)
+ f_macro_int32s_t_delete_simple(rule->groups)
+ f_macro_limit_sets_t_delete_simple(rule->limits)
+
f_capability_delete(&rule->capability);
controller_rule_items_delete_simple(&rule->items);
#ifndef _di_controller_rule_item_delete_simple_
void controller_rule_item_delete_simple(controller_rule_item_t *item) {
- f_string_dynamic_resize(0, item->actions);
+ controller_rule_actions_delete_simple(&item->actions);
}
#endif // _di_controller_rule_item_delete_simple_
#ifndef _di_controller_thread_delete_simple_
void controller_thread_delete_simple(controller_thread_t *thread) {
- f_thread_mutex_unlock(&thread->mutex.asynchronous);
- f_thread_mutex_unlock(&thread->mutex.print);
- f_thread_mutex_unlock(&thread->mutex.process);
- f_thread_mutex_unlock(&thread->mutex.rule);
+ 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);
}
* The process lock is intended to lock any activity on the processs structure.
* The rule lock is intended to lock any activity on the rules structure.
*/
-#ifndef _di_controller_mutex_t_
+#ifndef _di_controller_lock_t_
typedef struct {
- f_thread_mutex_t asynchronous;
f_thread_mutex_t print;
- f_thread_mutex_t process;
- f_thread_mutex_t rule;
- } controller_mutex_t;
- #define controller_mutex_t_initialize { \
- f_thread_mutex_t_initialize, \
- f_thread_mutex_t_initialize, \
+ f_thread_lock_t asynchronous;
+ f_thread_lock_attribute_t asynchronous_attribute;
+
+ 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_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_
*/
#ifndef _di_controller_process_t_
typedef struct {
- f_status_t status;
f_string_dynamic_t id;
- f_thread_mutex_t lock;
+ f_status_t status;
+
+ f_thread_lock_t lock;
+ f_thread_lock_attribute_t attribute;
f_thread_condition_t wait;
} controller_process_t;
#define controller_process_t_initialize { \
- F_known_not, \
f_string_dynamic_t_initialize \
- f_thread_mutex_t_initialize, \
+ F_known_not, \
+ f_thread_lock_t_initialize, \
+ f_thread_lock_attribute_t_initialize, \
f_thread_condition_t_initialize, \
}
typedef struct {
f_thread_id_t id;
- f_thread_mutex_t lock;
- f_array_length_t index;
+ f_thread_lock_t lock;
+ f_thread_lock_attribute_t attribute;
+ f_array_length_t index;
uint8_t state;
uint8_t action;
uint8_t options;
f_array_lengths_t stack;
controller_cache_t cache;
- controller_rule_t rule;
} controller_asynchronous_t;
#define controller_asynchronous_t_initialize { \
f_thread_id_t_initialize, \
- f_thread_mutex_t_initialize, \
+ f_thread_lock_t_initialize, \
+ f_thread_lock_attribute_t_initialize, \
0, \
0, \
0, \
0, \
0, \
f_array_lengths_t_initialize, \
- controller_cache_t_initialize, \
- controller_rule_t_initialize \
+ controller_cache_t_initialize \
}
+ // @fixme remove the clear() macros..clear isn't safe when mixing in mutexes and whatnot that cannot be cleared.
#define controller_macro_asynchronous_t_clear(asynchronous) \
f_macro_thread_id_t_clear(asynchronous.id) \
asynchronous.index = 0; \
asynchronous.options = 0; \
asynchronous.child = 0; \
f_macro_array_lengths_t_clear(asynchronous.stack) \
- controller_macro_cache_t_clear(asynchronous.cache) \
- controller_macro_rule_t_clear(asynchronous.rule)
+ controller_macro_cache_t_clear(asynchronous.cache)
#endif // _di_controller_asynchronous_t_
#ifndef _di_controller_asynchronouss_t_
f_thread_id_t id_rule;
f_thread_id_t id_signal;
- controller_mutex_t mutex;
+ controller_lock_t lock;
controller_asynchronouss_t asynchronouss;
} controller_thread_t;
f_thread_id_t_initialize, \
f_thread_id_t_initialize, \
f_thread_id_t_initialize, \
- controller_mutex_t_initialize, \
+ controller_lock_t_initialize, \
controller_asynchronouss_t_initialize \
}
- #define controller_macro_thread_t_initialize(mutex, asynchronouss) { \
+ #define controller_macro_thread_t_initialize(lock, asynchronouss) { \
F_true, \
f_thread_id_t_initialize, \
f_thread_id_t_initialize, \
f_thread_id_t_initialize, \
f_thread_id_t_initialize. \
- mutex, \
+ lock, \
asynchronouss \
}
f_macro_thread_id_t_clear(thread.id_control); \
f_macro_thread_id_t_clear(thread.id_rule); \
f_macro_thread_id_t_clear(thread.id_signal); \
- controller_macro_mutex_t_clear(thread.mutex), \
controller_macro_asynchronouss_t_clear(thread.asynchronouss)
#endif // _di_controller_data_common_t_
*
* @see fll_error_print()
*/
-#ifndef _di_controller_error_print_locked_
- extern void controller_error_print_locked(const fll_error_print_t error, const f_status_t status, const f_string_t function, const bool fallback, controller_thread_t *thread) f_gcc_attribute_visibility_internal;
-#endif // _di_controller_error_print_locked_
+#ifndef _di_controller_error_print_
+ extern void controller_error_print(const fll_error_print_t print, const f_status_t status, const f_string_t function, const bool fallback, controller_thread_t *thread) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_error_print_
/**
* Fully deallocate all memory for the given process without caring about return status.
}
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_append", F_true);
+ if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&thread_data.thread->lock.print);
+
+ fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_append", F_true);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ }
+
return status;
}
status = f_string_dynamic_terminate_after(&cache->action.name_file);
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);
+ if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&thread_data.thread->lock.print);
+
+ fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ }
+
return status;
}
status = f_file_stream_open(path, 0, &file);
if (F_status_is_error(status)) {
- 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);
+ if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&thread_data.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);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ }
}
else {
status = f_file_stream_read(file, 1, &cache->buffer_file);
if (F_status_is_error(status)) {
- 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);
+ if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&thread_data.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);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ }
}
}
status = f_file_stat(path, F_true, &stat_file);
if (F_status_is_error(status)) {
- 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);
+ if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&thread_data.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);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ }
}
else {
cache->timestamp.seconds = stat_file.st_ctim.tv_sec;
}
#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) {
+
+ if (!id.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) == F_equal_to) {
+ *at = i;
+ return F_true;
+ }
+ } // for
+
+ return F_false;
+ }
+#endif // _di_controller_find_process_
+
#ifndef _di_controller_get_id_user_
f_status_t controller_get_id_user(const f_string_static_t buffer, const f_string_range_t range, controller_cache_t *cache, uid_t *id) {
f_number_unsigned_t number = 0;
// always return immediately on memory errors.
if (F_status_set_fine(status) == F_memory_not) {
- 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);
+ if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&thread_data.thread->lock.print);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ fll_error_file_print(thread_data.data->error, F_status_set_fine(status), "controller_file_pid_create", F_true, thread_data.setting->path_pid.string, "create", fll_error_file_type_file);
+
+ controller_entry_error_print_cache(thread_data.data->error, cache->action);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ }
return status;
}
- 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);
+ if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
+ f_thread_mutex_lock(&thread_data.thread->lock.print);
- controller_entry_error_print(thread_data.data->warning, cache->action);
+ fll_error_file_print(thread_data.data->warning, F_status_set_fine(status), "controller_file_pid_create", F_true, thread_data.setting->path_pid.string, "create", fll_error_file_type_file);
+
+ controller_entry_error_print_cache(thread_data.data->warning, cache->action);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ }
status = F_none;
}
f_macro_array_lengths_t_increase_by(status, cache->ats, controller_default_allocation_step)
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true);
+ controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true, thread_data.thread);
return status;
}
status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[0].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ 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);
return status;
}
status2 = controller_string_dynamic_append_terminated(controller_entry_action_type_name(actions->array[cache->ats.array[at_j]].type), &cache->action.name_action);
if (F_status_is_error(status2)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ 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);
return status2;
}
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);
+
fprintf(thread_data.data->warning.to.stream, "%c", f_string_eol_s[0]);
fprintf(thread_data.data->warning.to.stream, "%s%sMultiple '", thread_data.data->warning.context.before->string, thread_data.data->warning.prefix ? thread_data.data->warning.prefix : f_string_empty_s);
fprintf(thread_data.data->warning.to.stream, "%s%s%s%s", thread_data.data->warning.context.after->string, thread_data.data->warning.notable.before->string, controller_string_ready_s, thread_data.data->warning.notable.after->string);
fprintf(thread_data.data->warning.to.stream, "%s' entry item actions detected; only the first will be used.%s%c", thread_data.data->warning.context.before->string, thread_data.data->warning.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print(thread_data.data->warning, cache->action);
+ controller_entry_error_print_cache(thread_data.data->warning, cache->action);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
}
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);
+
fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]);
fprintf(thread_data.data->error.to.stream, "%s%sThe entry item named '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s);
fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, thread_data.setting->entry.items.array[i].name.string, thread_data.data->error.notable.after->string);
fprintf(thread_data.data->error.to.stream, "%s' cannot be executed because recursion is not allowed.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]);
- }
- controller_entry_error_print(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(thread_data.data->error, cache->action);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ }
if (F_status_is_error_not(status)) {
status = F_status_set_error(F_recurse);
f_macro_array_lengths_t_increase_by(status2, cache->ats, controller_default_allocation_step)
if (F_status_is_error(status2)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status2), "f_macro_array_lengths_t_increase_by", F_true);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ 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);
return status2;
}
status2 = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[i].name, &cache->action.name_item);
if (F_status_is_error(status2)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ 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);
return status2;
}
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);
+
fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]);
fprintf(thread_data.data->error.to.stream, "%s%sThe entry item named '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s);
fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, actions->array[cache->ats.array[at_j]].parameters.array[0].string, thread_data.data->error.notable.after->string);
fprintf(thread_data.data->error.to.stream, "%s' does not exist.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]);
- }
- controller_entry_error_print(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(thread_data.data->error, cache->action);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ }
if (F_status_is_error_not(status)) {
status = F_status_set_error(F_valid_not);
status2 = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
if (F_status_is_error(status2)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status2), "controller_string_dynamic_append_terminated", F_true);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ 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);
return status2;
}
controller_entry_actions_t *actions = 0;
+ controller_process_t *process = 0;
+
const bool simulate = thread_data.data->parameters[controller_parameter_test].result == f_console_result_found;
cache->ats.used = 0;
f_macro_array_lengths_t_increase_by(status, cache->ats, controller_default_allocation_step)
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ 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);
return status;
}
status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[0].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ 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);
return status;
}
if (simulate) {
+ 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, "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]);
+
+ f_thread_mutex_unlock(&thread_data.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.
for (;;) {
actions = &thread_data.setting->entry.items.array[cache->ats.array[at_i]].actions;
status = controller_string_dynamic_append_terminated(controller_entry_action_type_name(actions->array[cache->ats.array[at_j]].type), &cache->action.name_action);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ 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);
return status;
}
if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_rule) {
if (simulate) {
+ 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, "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(thread_data.data->output.stream, "' is %s and is in a %sfailed%s state, skipping execution.%c", actions->array[cache->ats.array[at_j]].code & controller_entry_rule_code_require ? "required" : "optional", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
else if (actions->array[cache->ats.array[at_j]].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);
+
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(thread_data.data->error.to.stream, "%s and is in a ", thread_data.data->error.context.before->string);
fprintf(thread_data.data->error.to.stream, "%s%sfailed%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, thread_data.data->error.notable.after->string);
fprintf(thread_data.data->error.to.stream, "%s state, skipping execution.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]);
- }
- controller_entry_error_print(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(thread_data.data->error, cache->action);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ }
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);
+
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(thread_data.data->warning.to.stream, "%s%sfailed%s", thread_data.data->warning.context.after->string, thread_data.data->warning.notable.before->string, thread_data.data->warning.notable.after->string);
fprintf(thread_data.data->warning.to.stream, "%s state, skipping execution.%s%c", thread_data.data->warning.context.before->string, thread_data.data->warning.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print(thread_data.data->warning, cache->action);
+ controller_entry_error_print_cache(thread_data.data->warning, cache->action);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
}
else {
if (simulate) {
+ 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, "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(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]);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
else if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
+ f_thread_mutex_lock(&thread_data.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(thread_data.data->warning.to.stream, "%s%sfailed%s", thread_data.data->warning.context.after->string, thread_data.data->warning.notable.before->string, thread_data.data->warning.notable.after->string);
fprintf(thread_data.data->warning.to.stream, "%s state, skipping.%s%c", thread_data.data->warning.context.before->string, thread_data.data->warning.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print(thread_data.data->warning, cache->action);
+ controller_entry_error_print_cache(thread_data.data->warning, cache->action);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
}
if (thread_data.setting->ready == controller_setting_ready_wait) {
if (simulate) {
+ 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, "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]);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
else {
controller_perform_ready(thread_data, cache);
thread_data.setting->ready = controller_setting_ready_yes;
}
else if (simulate) {
+ 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, "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]);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
}
else if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_item) {
// 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);
+
fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]);
fprintf(thread_data.data->error.to.stream, "%s%sInvalid entry item index ", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s);
fprintf(thread_data.data->error.to.stream, "%s%s%llu%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, actions->array[cache->ats.array[at_j]].number, thread_data.data->error.notable.after->string);
fprintf(thread_data.data->error.to.stream, "%s detected.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]);
- }
- controller_entry_error_print(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(thread_data.data->error, cache->action);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ }
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)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "f_macro_array_lengths_t_increase_by", F_true);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ 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);
return status;
}
status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ 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);
return status;
}
if (simulate) {
+ 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, "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]);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
// exit inner loop to force restarting and start processing the requested item.
status = controller_rules_increase(&thread_data.setting->rules);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_rules_increase", F_true);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ controller_entry_error_print(thread_data.data->error, cache->action, F_status_set_fine(status), "controller_rules_increase", F_true, thread_data.thread);
return status;
}
rule_id_name[actions->array[cache->ats.array[at_j]].parameters.array[0].used] = f_path_separator_s[0];
rule_id_name[rule_id_length] = 0;
- f_thread_mutex_lock(&thread_data.thread->mutex.rule);
+ f_thread_lock_read(&thread_data.thread->lock.rule);
at = controller_rule_find_loaded(rule_id, thread_data);
- if (at < thread_data.setting->rules.used) {
- f_thread_mutex_unlock(&thread_data.thread->mutex.rule);
- }
+ const f_array_length_t used = thread_data.setting->rules.used;
+
+ f_thread_unlock(&thread_data.thread->lock.rule);
if (simulate) {
+ 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, "%s entry item rule '", actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_rule ? "Processing" : "Considering");
fprintf(thread_data.data->output.stream, "%s%s%s", thread_data.data->context.set.title.before->string, rule_id.string, thread_data.data->context.set.title.after->string);
fprintf(thread_data.data->output.stream, "'.%c", f_string_eol_s[0]);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
// the rule is not yet loaded, ensure that it is loaded.
- if (at == thread_data.setting->rules.used) {
+ if (at == used) {
// 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);
+
status = controller_rule_read(rule_id, thread_data, cache, &thread_data.setting->rules.array[thread_data.setting->rules.used]);
// restore cache.
cache->action.line_item = cache_line_item;
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action);
+
+ if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&thread_data.thread->lock.print);
+
+ controller_entry_error_print_cache(thread_data.data->error, cache->action);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ }
if (!simulate) {
- f_thread_mutex_unlock(&thread_data.thread->mutex.rule);
+ f_thread_unlock(&thread_data.thread->lock.rule);
break;
}
thread_data.setting->rules.used++;
}
- f_thread_mutex_unlock(&thread_data.thread->mutex.rule);
+ f_thread_unlock(&thread_data.thread->lock.rule);
}
- if (F_status_is_error_not(status)) {
+ if (F_status_is_error_not(status) && actions->array[cache->ats.array[at_j]].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;
memcpy(cache_name_item, cache->action.name_item.string, cache->action.name_item.used);
memcpy(cache_name_file, cache->action.name_file.string, cache->action.name_file.used);
- if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_rule) {
- rule_options = 0;
+ rule_options = 0;
- if (simulate) {
- rule_options |= controller_rule_option_simulate;
- }
+ if (simulate) {
+ rule_options |= controller_rule_option_simulate;
+ }
- if (actions->array[cache->ats.array[at_j]].code & controller_entry_rule_code_require) {
- rule_options |= controller_rule_option_require;
- }
+ if (actions->array[cache->ats.array[at_j]].code & controller_entry_rule_code_require) {
+ rule_options |= controller_rule_option_require;
+ }
- if (actions->array[cache->ats.array[at_j]].code & controller_entry_rule_code_wait) {
- rule_options |= controller_rule_option_wait;
- }
+ if (actions->array[cache->ats.array[at_j]].code & controller_entry_rule_code_wait) {
+ rule_options |= controller_rule_option_wait;
+ }
- // @fixme this logic needs to change.
- // determine how to pass rule ids.
- // each thread has a main rule, but child threads need to be copied over and passed somehow.
- f_thread_mutex_lock(&thread_data.setting->rules.array[at].lock);
+ if (actions->array[cache->ats.array[at_j]].code & controller_entry_rule_code_asynchronous) {
+ rule_options |= controller_rule_option_asynchronous;
- if (actions->array[cache->ats.array[at_j]].code & controller_entry_rule_code_asynchronous) {
- rule_options |= controller_rule_option_asynchronous;
+ // @todo this function will need to do the same process prep work as is done right before controller_rule_process().
+ status = controller_rule_process_asynchronous(at, controller_rule_action_type_start, rule_options, thread_data, cache);
+ }
+ else {
- status = controller_rule_process_asynchronous(at, controller_rule_action_type_start, rule_options, thread_data, cache);
- }
- else {
- status = controller_rule_process(at, controller_rule_action_type_start, rule_options, thread_data, cache);
+ f_array_length_t at_process = 0;
+
+ f_thread_lock_read(&thread_data.thread->lock.process);
+
+ 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);
+
+ status = controller_processs_increase(thread_data.processs);
+
+ 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);
+ }
+ else {
+ at_process = thread_data.processs->used;
+ }
}
- if (status == F_child || status == F_signal) break;
+ f_thread_unlock(&thread_data.thread->lock.process);
- 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_not(status)) {
+ f_thread_lock_write(&thread_data.processs->array[at_process].lock);
+
+ controller_rule_t rule = controller_rule_t_initialize;
+
+ status = controller_rule_copy(thread_data.setting->rules.array[at], &rule);
+
+ f_thread_condition_signal(&thread_data.processs->array[at_process].wait);
+ f_thread_unlock(&thread_data.processs->array[at_process].lock);
+
+ status = controller_rule_process(rule, at_process, controller_rule_action_type_start, rule_options, thread_data, cache);
+
+ controller_rule_delete_simple(&rule);
+ }
}
// restore cache.
cache->action.line_action = cache_line_action;
cache->action.line_item = cache_line_item;
+
+ if (status == F_child || status == F_signal) break;
}
+ // @todo this may need to be relocated (currently it may result in multiple error messages due to other messages being printed above.)
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action);
+ f_thread_mutex_lock(&thread_data.thread->lock.print);
+
+ controller_entry_error_print_cache(thread_data.data->error, cache->action);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
if (!simulate || F_status_set_fine(status) == F_memory_not) {
break;
code = controller_string_stop_s;
}
+ 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, "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, "' to '");
fprintf(thread_data.data->output.stream, "%s%llu%s", thread_data.data->context.set.important.before->string, actions->array[cache->ats.array[at_j]].number, thread_data.data->context.set.important.after->string);
fprintf(thread_data.data->output.stream, "' MegaTime (milliseconds).%c", f_string_eol_s[0]);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
if (actions->array[cache->ats.array[at_j]].code == controller_entry_timeout_code_kill) {
// 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);
+
fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]);
fprintf(thread_data.data->error.to.stream, "%s%sInvalid entry item index ", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s);
fprintf(thread_data.data->error.to.stream, "%s%s%llu%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, actions->array[cache->ats.array[at_j]].number, thread_data.data->error.notable.after->string);
fprintf(thread_data.data->error.to.stream, "%s detected.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]);
- }
- controller_entry_error_print(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(thread_data.data->error, cache->action);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
+ }
return F_status_is_error(F_critical);
}
thread_data.setting->failsafe_rule_id = actions->array[cache->ats.array[at_j]].number;
if (simulate) {
+ 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, "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]);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
}
}
status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[cache->ats.array[at_i]].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ 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);
break;
}
}
if (F_status_is_error_not(status) && simulate) {
+ f_thread_mutex_lock(&thread_data.thread->lock.print);
+
fprintf(thread_data.data->output.stream, "%c", f_string_eol_s[0]);
+
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
return status;
}
#endif // _di_controller_validate_has_graph_
+controller_processs_t
+
#ifdef __cplusplus
} // extern "C"
#endif
#endif // _di_controller_file_pid_delete_
/**
+ * Find an existing process.
+ *
+ * Do not confuse this with a process in the context of a PID.
+ * This is a stucture for the current processing of some rule.
+ *
+ * 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 processs
+ * The array of processes to.
+ * @param at
+ * The location within processs the id was found.
+ *
+ * @return
+ * F_none if not given a valid id to search.
+ * F_false if there is no process found.
+ * 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;
+#endif // _di_controller_find_process_
+
+/**
* Convert the string from a string representation of an ID or a user name into the numeric representation of that ID or user name.
*
* @param buffer
*
* This prints messages on errors.
*
+ * 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 cache
#endif // _di_controller_entry_actions_read_
#ifndef _di_controller_entry_error_print_
- void controller_entry_error_print(const fll_error_print_t output, const controller_cache_action_t cache) {
-
- if (output.verbosity != f_console_verbosity_quiet) {
- fprintf(output.to.stream, "%c", f_string_eol_s[0]);
- fprintf(output.to.stream, "%s%sWhile processing ", output.context.before->string, output.prefix ? output.prefix : f_string_empty_s);
-
- if (cache.name_action.used) {
- fprintf(output.to.stream, "action '");
- fprintf(output.to.stream, "%s%s%s%s", output.context.after->string, output.notable.before->string, cache.name_action.string, output.notable.after->string);
- fprintf(output.to.stream, "%s' on line ", output.context.before->string);
- fprintf(output.to.stream, "%s%s%llu%s", output.context.after->string, output.notable.before->string, cache.line_action, output.notable.after->string);
- fprintf(output.to.stream, "%s for ", output.context.before->string);
- }
+ void controller_entry_error_print(const fll_error_print_t print, const controller_cache_action_t cache, const f_status_t status, const f_string_t function, const bool fallback, controller_thread_t *thread) {
- if (cache.name_item.used) {
- fprintf(output.to.stream, "entry item '");
- fprintf(output.to.stream, "%s%s%s%s", output.context.after->string, output.notable.before->string, cache.name_item.string, output.notable.after->string);
- fprintf(output.to.stream, "%s' on line ", output.context.before->string);
- fprintf(output.to.stream, "%s%s%llu%s", output.context.after->string, output.notable.before->string, cache.line_item, output.notable.after->string);
- fprintf(output.to.stream, "%s for ", output.context.before->string);
- }
+ if (print.verbosity != f_console_verbosity_quiet) {
+ f_thread_mutex_lock(&thread->lock.print);
- if (cache.name_file.used) {
- fprintf(output.to.stream, "file '");
- fprintf(output.to.stream, "%s%s%s%s", output.context.after->string, output.notable.before->string, cache.name_file.string, output.notable.after->string);
- fprintf(output.to.stream, "%s'.%s%c", output.context.before->string, output.context.after->string, f_string_eol_s[0]);
- }
+ fll_error_print(print, status, function, fallback);
+ controller_entry_error_print_cache(print, cache);
+
+ f_thread_mutex_unlock(&thread->lock.print);
}
}
#endif // _di_controller_entry_error_print_
+#ifndef _di_controller_entry_error_print_cache_
+ void controller_entry_error_print_cache(const fll_error_print_t print, const controller_cache_action_t cache) {
+
+ fprintf(print.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(print.to.stream, "%s%sWhile processing ", print.context.before->string, print.prefix ? print.prefix : f_string_empty_s);
+
+ if (cache.name_action.used) {
+ fprintf(print.to.stream, "action '");
+ fprintf(print.to.stream, "%s%s%s%s", print.context.after->string, print.notable.before->string, cache.name_action.string, print.notable.after->string);
+ fprintf(print.to.stream, "%s' on line ", print.context.before->string);
+ fprintf(print.to.stream, "%s%s%llu%s", print.context.after->string, print.notable.before->string, cache.line_action, print.notable.after->string);
+ fprintf(print.to.stream, "%s for ", print.context.before->string);
+ }
+
+ if (cache.name_item.used) {
+ fprintf(print.to.stream, "entry item '");
+ fprintf(print.to.stream, "%s%s%s%s", print.context.after->string, print.notable.before->string, cache.name_item.string, print.notable.after->string);
+ fprintf(print.to.stream, "%s' on line ", print.context.before->string);
+ fprintf(print.to.stream, "%s%s%llu%s", print.context.after->string, print.notable.before->string, cache.line_item, print.notable.after->string);
+ fprintf(print.to.stream, "%s for ", print.context.before->string);
+ }
+
+ if (cache.name_file.used) {
+ fprintf(print.to.stream, "file '");
+ fprintf(print.to.stream, "%s%s%s%s", print.context.after->string, print.notable.before->string, cache.name_file.string, print.notable.after->string);
+ fprintf(print.to.stream, "%s'.%s%c", print.context.before->string, print.context.after->string, f_string_eol_s[0]);
+ }
+ }
+#endif // _di_controller_entry_error_print_cache_
+
#ifndef _di_controller_entry_items_increase_by_
f_status_t controller_entry_items_increase_by(const f_array_length_t amount, controller_entry_items_t *items) {
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);
+ controller_error_print(thread_data.data->error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true, thread_data);
}
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);
+ controller_error_print(thread_data.data->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true, thread_data);
}
}
}
else {
if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_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 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]);
+
+ f_thread_unlock(&thread_data.thread->lock.print);
}
status = F_status_set_error(F_data_not);
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_lock(&thread_data.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]);
- controller_entry_error_print(thread_data.data->warning, cache->action);
+ controller_entry_error_print_cache(thread_data.data->warning, cache->action);
+
+ f_thread_unlock(&thread_data.thread->lock.print);
}
code |= 0x2;
status = controller_string_dynamic_append_terminated(cache->action.name_item, &thread_data.setting->entry.items.array[at].name);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true);
+ controller_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, thread_data);
break;
}
status = controller_entry_actions_read(*range, thread_data, cache, &thread_data.setting->entry.items.array[at].actions);
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action);
+ f_thread_lock(&thread_data.thread->lock.print);
+
+ controller_entry_error_print_cache(thread_data.data->error, cache->action);
+
+ f_thread_unlock(&thread_data.thread->lock.print);
if (F_status_set_fine(status) == F_memory_not) {
break;
if (!(code & 0x1)) {
if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_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 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]);
+
+ f_thread_unlock(&thread_data.thread->lock.print);
}
status = F_status_set_error(F_found_not);
status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[i].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- fll_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true);
+ controller_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, thread_data);
break;
}
if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
+ f_thread_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 required entry item '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s);
fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, action->parameters.array[0].string, thread_data.data->error.notable.after->string);
fprintf(thread_data.data->error.to.stream, "%s' does not exist.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(thread_data.data->error, cache->action);
+
+ f_thread_unlock(&thread_data.thread->lock.print);
}
action->number = 0;
#endif // _di_controller_entry_actions_read_
/**
- * Print additional error/warning information in addition to existing error.
+ * Print the entry related error, locking the print mutex during the print.
+ *
+ * @param print
+ * Designates how printing is to be performed.
+ * @param cache
+ * The action cache.
+ * @param status
+ * The status code to process.
+ * Make sure this has F_status_set_fine() called if the status code has any error or warning bits.
+ * @param function
+ * The name of the function where the error happened.
+ * Set to 0 to disable.
+ * @param fallback
+ * Set to F_true to print the fallback error message for unknown errors.
+ * @param thread
+ * The thread data.
+ *
+ * @see fll_error_print()
+ * @see controller_entry_error_print_cache()
+ */
+#ifndef _di_controller_entry_error_print_
+ extern void controller_entry_error_print(const fll_error_print_t print, const controller_cache_action_t cache, const f_status_t status, const f_string_t function, const bool fallback, controller_thread_t *thread) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_entry_error_print_
+
+/**
+ * Print additional error/warning information in addition to existing error that is found within the cache.
*
* This is explicitly intended to be used in addition to the error message.
*
- * @param output
- * The error or warning output structure.
+ * This neither locks the thread nor does it check to see if output is enabled or disabled.
+ *
+ * @param print
+ * Designates how printing is to be performed.
* @param cache
- * A structure for containing and caching relevant data.
+ * The action cache.
*
* @see controller_entry_actions_read()
* @see controller_entry_read()
*/
-#ifndef _di_controller_entry_error_print_
- extern void controller_entry_error_print(const fll_error_print_t output, const controller_cache_action_t cache) f_gcc_attribute_visibility_internal;
-#endif // _di_controller_entry_error_print_
+#ifndef _di_controller_entry_error_print_cache_
+ extern void controller_entry_error_print_cache(const fll_error_print_t print, const controller_cache_action_t cache) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_entry_error_print_cache_
/**
* Increase the size of the entry items array by the specified amount, but only if necessary.
#endif // _di_controller_rule_action_read_
#ifndef _di_controller_rule_copy_
- f_status_t controller_rule_copy(controller_rule_t *source, controller_rule_t *destination) {
+ f_status_t controller_rule_copy(const controller_rule_t source, controller_rule_t *destination) {
f_status_t status = F_none;
- f_thread_condition_wait(&source->wait, &destination->lock);
+ destination->timeout_kill = source.timeout_kill;
+ destination->timeout_start = source.timeout_start;
+ destination->timeout_stop = source.timeout_stop;
- // @todo
+ destination->has = source.has;
+ destination->nice = source.nice;
+ destination->user = source.user;
+ destination->group = source.group;
- f_thread_condition_signal(&source->wait);
- f_thread_mutex_unlock(&destination->lock);
+ destination->timestamp.seconds = source.seconds;
+ destination->timestamp.nanoseconds = source.nanoseconds;
+
+ destination->path_control.used = 0;
+ destination->name.used = 0;
+ destination->path.used = 0;
+ destination->script.used = 0;
+
+ destination->define.used = 0;
+ destination->parameter.used = 0;
+
+ destination->environment.used = 0;
+ destination->need.used = 0;
+ destination->want.used = 0;
+ destination->wish.used = 0;
+
+ destination->affinity.used = 0;
+ destination->capability.used = 0;
+ destination->control_group.used = 0;
+ destination->groups.used = 0;
+ destination->limits.used = 0;
+ destination->scheduler.used = 0;
+
+ destination->items.used = 0;
+
+ if (source.id.used) {
+
+ status = f_string_dynamic_append(source.id, &dynamic->id);
+ if (F_status_is_error(status)) return status;
+ }
+
+ if (source.name.used) {
+
+ status = f_string_dynamic_append(source.name, &dynamic->name);
+ if (F_status_is_error(status)) return status;
+ }
+
+ if (source.path.used) {
+
+ status = f_string_dynamic_append(source.path, &dynamic->path);
+ if (F_status_is_error(status)) return status;
+ }
+
+ if (source.script.used) {
+
+ status = f_string_dynamic_append(source.script, &dynamic->script);
+ if (F_status_is_error(status)) return status;
+ }
+
+ if (source.define.used) {
+ status = f_string_maps_append(source.define, &destination->define);
+ }
+
+ if (source.parameter.used) {
+ status = f_string_maps_append(source.parameter, &destination->parameter);
+ }
+
+ if (source.environment.used) {
+ status = f_string_dynamics_append(source.environment, &destination->environment);
+ }
+
+ if (source.need.used) {
+ status = f_string_dynamics_append(source.need, &destination->need);
+ }
+
+ if (source.want.used) {
+ status = f_string_dynamics_append(source.want, &destination->want);
+ }
+
+ if (source.wish.used) {
+ status = f_string_dynamics_append(source.wish, &destination->wish);
+ }
+
+ if (source.affinity.used) {
+ status = f_int32s_append(source.affinity, &destination->affinity);
+ }
+
+ if (source.capability.used) {
+ // @todo copy capability
+ }
+
+ if (source.control_group.used) {
+ // @todo copy control_group
+ }
+
+ if (source.groups.used) {
+ status = f_int32s_append(source.groups, &destination->groups);
+ }
+
+ if (source.limits.used) {
+ status = f_limit_sets_append(source.limits, &destination->limits);
+ }
+
+ if (source.scheduler.used) {
+ // @todo copy scheduler
+ }
+
+ if (source.items.used) {
+ // @todo copy items
+ }
return status;
}
void controller_rule_error_print_locked(const fll_error_print_t output, const controller_cache_action_t cache, const bool item, controller_thread_t *thread) {
if (output.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread->mutex.print);
+ f_thread_mutex_lock(&thread->lock.print);
controller_rule_error_print(output, cache, item);
- f_thread_mutex_unlock(&thread->mutex.print);
+ f_thread_mutex_unlock(&thread->lock.print);
}
}
#endif // _di_controller_rule_error_print_
else {
if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ f_thread_mutex_lock(&thread_data.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]);
controller_rule_error_print(thread_data.data->warning, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
rule->items.array[i].actions.array[j].status = F_ignore;
if (options & controller_rule_option_simulate) {
if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ 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.notable.string, rule->name.used ? rule->name.string : f_string_empty_s, thread_data.data->context.reset.string);
fprintf(thread_data.data->output.stream, "%s'.%c", thread_data.data->context.reset.string, f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
// sleep for less than a second to better show simulation of synchronous vs asynchronous.
if (F_status_is_error(status)) {
status = F_status_set_fine(status);
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ f_thread_mutex_lock(&thread_data.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);
fll_error_print(thread_data.data->error, status, "fll_execute_program", F_true);
}
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
status = F_status_set_error(status);
}
if (options & controller_rule_option_simulate) {
if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ 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.notable.string, rule->name.used ? rule->name.string : f_string_empty_s, thread_data.data->context.reset.string);
fprintf(thread_data.data->output.stream, "%s'.%c", thread_data.data->context.reset.string, f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
// sleep for less than a second to better show simulation of synchronous vs asynchronous.
if (F_status_is_error(status)) {
status = F_status_set_fine(status);
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ f_thread_mutex_lock(&thread_data.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);
fll_error_print(thread_data.data->error, status, "fll_execute_program", F_true);
}
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
return F_status_set_error(status);
}
#endif // _di_controller_rule_path_
#ifndef _di_controller_rule_process_
- f_status_t controller_rule_process(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache) {
+ 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".
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->mutex.print);
+ 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%sUnsupported action type '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s);
controller_rule_error_print(thread_data.data->error, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
return F_status_set_error(F_parameter);
}
if (index >= thread_data.setting->rules.used) {
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ 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->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
return F_status_set_error(F_parameter);
}
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->mutex.print);
+ 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->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
return status;
}
if (thread_data.thread->asynchronouss.array[thread_data.id].stack.array[i] == index) {
if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ 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);
controller_rule_error_print(thread_data.data->error, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
// never continue on recursion errors even in simulate mode.
}
if (F_status_is_error(status)) {
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ f_thread_mutex_lock(&thread_data.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);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
return status;
}
status = f_string_dynamic_append(thread_data.setting->rules.array[index].id, &cache->action.name_file);
if (F_status_is_error(status)) {
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ f_thread_mutex_lock(&thread_data.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);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
return status;
}
}
if (F_status_is_error(status)) {
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ f_thread_mutex_lock(&thread_data.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);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.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->mutex.print);
+ f_thread_mutex_lock(&thread_data.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);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
return status;
}
if (at == thread_data.setting->rules.used) {
if (i == 0) {
- f_thread_mutex_lock(&thread_data.thread->mutex.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, "was not found");
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->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
if (!(options & controller_rule_option_simulate)) break;
}
else {
if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ f_thread_mutex_lock(&thread_data.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);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
}
}
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->mutex.print);
+ 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->mutex.print);
+ 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);
if (F_status_is_error(status)) {
if (i == 0 || i == 1 || F_status_set_fine(status) == F_memory_not) {
- f_thread_mutex_lock(&thread_data.thread->mutex.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);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.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);
}
else {
if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ f_thread_mutex_lock(&thread_data.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);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
}
}
if (F_status_is_error(thread_data.setting->rules.array[at].status)) {
if (i == 0 || i == 1) {
- f_thread_mutex_lock(&thread_data.thread->mutex.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, "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);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
if (!(options & controller_rule_option_simulate)) break;
}
else {
if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ f_thread_mutex_lock(&thread_data.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);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
}
}
if (missing) {
if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ 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);
controller_rule_error_print(thread_data.data->error, cache->action, F_true);
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
status = F_status_set_error(F_parameter);
#ifndef _di_controller_rule_process_asynchronous_
f_status_t controller_rule_process_asynchronous(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_thread_data_t thread_data, controller_cache_t *cache) {
- f_thread_mutex_lock(&thread_data->mutex.asynchronous);
+ f_thread_mutex_lock(&thread_data->lock.asynchronous);
if (!thread_data.thread->enabled) {
- f_thread_mutex_unlock(&thread_data.thread->mutex.asynchronous);
+ f_thread_mutex_unlock(&thread_data.thread->lock.asynchronous);
return F_signal;
}
f_status_t status = controller_asynchronouss_increase(&thread_data.thread->asynchronouss);
if (F_status_is_error(status)) {
- f_thread_mutex_unlock(&thread_data.thread->mutex.asynchronous);
+ f_thread_mutex_unlock(&thread_data.thread->lock.asynchronous);
return status;
}
thread_data.thread->asynchronouss.used--;
}
- f_thread_mutex_unlock(&thread_data.thread->mutex.asynchronous);
+ f_thread_mutex_unlock(&thread_data.thread->lock.asynchronous);
if (F_status_is_error(status)) {
return status;
controller_data_t *data = thread_data.thread->data;
controller_setting_t *setting = thread_data.thread->setting;
- f_thread_mutex_lock(&thread_data.thread->mutex.print);
+ f_thread_mutex_lock(&thread_data.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->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
return;
}
setting->rules.array[index].status = F_complete;
- f_thread_mutex_unlock(&thread_data.thread->mutex.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
#endif // _di_controller_rule_simulate_
if (!thread->enabled) break;
- if (f_thread_mutex_lock_try(&thread->mutex.asynchronous) == F_none) {
+ if (f_thread_mutex_lock_try(&thread->lock.asynchronous) == F_none) {
if (thread->asynchronouss.array[i].state != controller_asynchronous_state_joined) {
f_thread_join(thread->asynchronouss.array[i].id, 0);
controller_macro_cache_action_t_clear(thread->asynchronouss.array[i].cache);
}
- f_thread_mutex_unlock(&thread->mutex.asynchronous);
+ f_thread_mutex_unlock(&thread->lock.asynchronous);
}
} // for
}
/**
* Copy a rule, allocating new space as necessary.
*
+ * This does not do any locking or unlocking for the rule data, be sure to lock appropriately before and after calling this.
+ *
+ * @todo finish writing this.
+ *
* @param source
* The source rule to copy from.
* @param destination
* 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.
*
* 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.
*
* F_signal on (exit) signal received.
*/
#ifndef _di_controller_rule_process_
- extern f_status_t controller_rule_process(const f_array_length_t index, const uint8_t action, const uint8_t options, controller_thread_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 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;
#endif // _di_controller_rule_process_
/**
thread.cache_main = thread_main->cache_main;
thread.cache_action = &asynchronous->cache;
thread.data = thread_main->data;
- thread.mutex = thread_main->mutex;
+ thread.lock = thread_main->lock;
thread.setting = thread_main->setting;
thread.stack = &asynchronous->stack;
thread->enabled = F_false;
- f_thread_mutex_lock(&thread->mutex.asynchronous);
+ f_thread_mutex_lock(&thread->lock.asynchronous);
for (f_array_length_t i = 0; i < thread->asynchronouss.used; ++i) {
thread->asynchronouss.used = 0;
- f_thread_mutex_unlock(&thread->mutex.asynchronous);
+ f_thread_mutex_unlock(&thread->lock.asynchronous);
}
#endif // _di_controller_thread_asynchronous_cancel_
for (; thread_data->thread->enabled; ) {
sleep(interval);
- if (f_thread_mutex_lock_try(&thread_data->thread->mutex.asynchronous) == F_none) {
+ if (f_thread_mutex_lock_try(&thread_data->thread->lock.asynchronous) == F_none) {
controller_thread_t *thread = &thread_data->thread;
if (thread->asynchronouss.used) {
controller_asynchronouss_resize(thread->asynchronouss.used, &thread->asynchronouss);
}
- f_thread_mutex_unlock(&thread->mutex.asynchronous);
+ f_thread_mutex_unlock(&thread->lock.asynchronous);
}
} // for
status = f_thread_create(0, &thread.id_signal, &controller_thread_signal, (void *) &data_main);
}
- if (F_status_is_error_not(status)) {
- status = f_thread_create(0, &thread.id_cleanup, &controller_thread_cleanup, (void *) &data_main);
- }
-
if (F_status_is_error(status)) {
if (data->error.verbosity != f_console_verbosity_quiet) {
- controller_error_print_locked(data->error, F_status_set_fine(status), "f_thread_create", F_true, &thread);
+ controller_error_print(data->error, F_status_set_fine(status), "f_thread_create", F_true, &thread);
}
}
else {
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.mutex.print);
+ f_thread_mutex_lock(&thread.lock.print);
fprintf(data->error.to.stream, "%c", f_string_eol_s[0]);
fprintf(data->error.to.stream, "%s%sThe pid file '", data->error.context.before->string, data->error.prefix ? data->error.prefix : f_string_empty_s);
fprintf(data->error.to.stream, "%s%s%s%s", data->error.context.after->string, data->error.notable.before->string, setting->path_pid.string, data->error.notable.after->string);
fprintf(data->error.to.stream, "%s' must not already exist.%s%c", data->error.context.before->string, data->error.context.after->string, f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread.mutex.print);
+ f_thread_mutex_unlock(&thread.lock.print);
}
setting->ready = controller_setting_ready_abort;
if (f_file_exists(setting->path_pid.string) == F_true) {
if (data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_mutex_lock(&thread.mutex.print);
+ f_thread_mutex_lock(&thread.lock.print);
fprintf(data->error.to.stream, "%c", f_string_eol_s[0]);
fprintf(data->error.to.stream, "%s%sThe pid file '", data->error.context.before->string, data->error.prefix ? data->error.prefix : f_string_empty_s);
fprintf(data->error.to.stream, "%s%s%s%s", data->error.context.after->string, data->error.notable.before->string, setting->path_pid.string, data->error.notable.after->string);
fprintf(data->error.to.stream, "%s' must not already exist.%s%c", data->error.context.before->string, data->error.context.after->string, f_string_eol_s[0]);
- f_thread_mutex_unlock(&thread.mutex.print);
+ f_thread_mutex_unlock(&thread.lock.print);
}
setting->ready = controller_setting_ready_fail;
status = f_thread_create(0, &thread.id_control, &controller_thread_control, (void *) &data_main);
}
+ if (F_status_is_error_not(status)) {
+ status = f_thread_create(0, &thread.id_cleanup, &controller_thread_cleanup, (void *) &data_main);
+ }
+
if (F_status_is_error(status)) {
if (data->error.verbosity != f_console_verbosity_quiet) {
controller_error_print_locked(data->error, F_status_set_fine(status), "f_thread_create", F_true, &thread);
controller_thread_data_t *thread_data = (controller_thread_data_t *) arguments;
// @todo
- // f_thread_mutex_lock(&thread_data->mutex.rule);
- // f_thread_mutex_unlock(&thread_data->mutex.rule);
+ // f_thread_mutex_lock(&thread_data->lock.rule);
+ // f_thread_mutex_unlock(&thread_data->lock.rule);
return 0;
}