f_status_t status;
f_number_signed_t process; // @todo: for background/threaded support (ideally should hold the process id, but remove if this ends up not being the strategy) (this can also be used by the parent/main process to check to see if the child no longer a child of this process).
+ f_number_unsigned_t timeout_kill;
+ f_number_unsigned_t timeout_start;
+ f_number_unsigned_t timeout_stop;
+
f_time_spec_t timestamp;
f_string_dynamic_t id;
F_known_not, \
0, \
0, \
+ 0, \
+ 0, \
f_time_spec_t_initialize, \
f_string_dynamic_t_initialize, \
f_string_dynamic_t_initialize, \
typedef struct {
bool interruptable;
- bool lock; // @todo: this is intend for mutex write locking of this setting for thread safety, remove this if another approach is used.
+ bool lock; // @todo: this is intended for mutex write locking of this setting for thread safety, remove this if another approach is used.
uint8_t ready;
+ f_number_unsigned_t timeout_kill;
+ f_number_unsigned_t timeout_start;
+ f_number_unsigned_t timeout_stop;
+
+ bool failsafe_enabled;
+ f_array_length_t failsafe_rule_id;
+
f_string_dynamic_t path_pid;
f_string_dynamic_t path_setting;
F_false, \
F_false, \
0, \
+ 3, \
+ 3, \
+ 3, \
+ F_false, \
+ 0, \
f_string_dynamic_t_initialize, \
f_string_dynamic_t_initialize, \
controller_entry_t_initialize, \
return status;
}
+ if (F_status_is_error(actions->array[cache->ats.array[at_j]].status)) {
+ if (simulate) {
+ fprintf(data.output.stream, "%c", f_string_eol_s[0]);
+ fprintf(data.output.stream, "The entry item action '");
+ fprintf(data.output.stream, "%s%s%s", data.context.set.title.before->string, cache->name_action.string, data.context.set.title.after->string);
+ fprintf(data.output.stream, "' is in a %sfailed%s state, skipping execution.%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]);
+ }
+ else {
+ // @todo check to see if this rule is "required" and if so immediately fail, otherwise report a failure as a warning (normal verbosity, not debug verbosity).
+ }
+
+ continue;
+ }
+
if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_ready) {
if (setting->ready == controller_setting_ready_wait) {
}
else if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_consider || actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_rule) {
- status = controller_rules_increase_by(controller_default_allocation_step, &setting->rules);
+ status = controller_rules_increase(&setting->rules);
if (F_status_is_error(status)) {
- fll_error_print(data.error, F_status_set_fine(status), "controller_rules_increase_by", F_true);
+ fll_error_print(data.error, F_status_set_fine(status), "controller_rules_increase", F_true);
controller_entry_error_print(data.error, *cache);
return status;
}
}
else if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_timeout) {
+
if (simulate) {
+ f_string_t code = "";
+
+ if (actions->array[cache->ats.array[at_j]].code == controller_entry_timeout_code_kill) {
+ code = controller_string_kill;
+ }
+ else if (actions->array[cache->ats.array[at_j]].code == controller_entry_timeout_code_start) {
+ code = controller_string_start;
+ }
+ else if (actions->array[cache->ats.array[at_j]].code == controller_entry_timeout_code_stop) {
+ code = controller_string_stop;
+ }
+
fprintf(data.output.stream, "%c", f_string_eol_s[0]);
fprintf(data.output.stream, "Processing entry item action '");
fprintf(data.output.stream, "%s%s%s", data.context.set.title.before->string, controller_string_timeout, data.context.set.title.after->string);
fprintf(data.output.stream, "' setting '");
- fprintf(data.output.stream, "%s%s%s", data.context.set.important.before->string, "@todo", data.context.set.important.after->string);
+ fprintf(data.output.stream, "%s%s%s", data.context.set.important.before->string, code, data.context.set.important.after->string);
fprintf(data.output.stream, "' to '");
- fprintf(data.output.stream, "%s%s%s", data.context.set.important.before->string, "@todo", data.context.set.important.after->string);
- fprintf(data.output.stream, "'.%c", f_string_eol_s[0]);
+ fprintf(data.output.stream, "%s%llu%s", data.context.set.important.before->string, actions->array[cache->ats.array[at_j]].number, data.context.set.important.after->string);
+ fprintf(data.output.stream, "' MegaTime (milliseconds).%c", f_string_eol_s[0]);
}
- // @todo set the appropriate timeout value (set the entry actions timeouts which are later used as the initial defaults as the rule timeouts).
+ if (actions->array[cache->ats.array[at_j]].code == controller_entry_timeout_code_kill) {
+ setting->timeout_kill = actions->array[cache->ats.array[at_j]].number;
+ }
+ else if (actions->array[cache->ats.array[at_j]].code == controller_entry_timeout_code_start) {
+ setting->timeout_start = actions->array[cache->ats.array[at_j]].number;
+ }
+ else if (actions->array[cache->ats.array[at_j]].code == controller_entry_timeout_code_stop) {
+ setting->timeout_stop = actions->array[cache->ats.array[at_j]].number;
+ }
}
else if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_failsafe) {
- if (simulate) {
- fprintf(data.output.stream, "%c", f_string_eol_s[0]);
- fprintf(data.output.stream, "Processing entry item action '");
- fprintf(data.output.stream, "%s%s%s", data.context.set.title.before->string, controller_string_failsafe, data.context.set.title.after->string);
- fprintf(data.output.stream, "' setting value to '");
- fprintf(data.output.stream, "%s%s%s", data.context.set.important.before->string, "@todo", data.context.set.important.after->string);
- fprintf(data.output.stream, "'.%c", f_string_eol_s[0]);
+
+ if (actions->array[cache->ats.array[at_j]].number == 0 || actions->array[cache->ats.array[at_j]].number >= setting->entry.items.used) {
+
+ // This should not happen if the pre-process is working as designed, but in case it doesn't, return a critical error to prevent infinite recursion and similar errors.
+ if (data.error.verbosity != f_console_verbosity_quiet) {
+ fprintf(data.error.to.stream, "%c", f_string_eol_s[0]);
+ fprintf(data.error.to.stream, "%s%sInvalid entry item index ", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s);
+ fprintf(data.error.to.stream, "%s%s%llu%s", data.error.context.after->string, data.error.notable.before->string, actions->array[cache->ats.array[at_j]].number, data.error.notable.after->string);
+ fprintf(data.error.to.stream, "%s detected.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]);
+ }
+
+ controller_entry_error_print(data.error, *cache);
+
+ return F_status_is_error(F_critical);
}
+ else {
+ setting->failsafe_enabled = F_true;
+ setting->failsafe_rule_id = actions->array[cache->ats.array[at_j]].number;
- // @todo set the failsafe rule to this rule id (find the rule and then assign by the rule id and then assign by the array index).
+ if (simulate) {
+ fprintf(data.output.stream, "%c", f_string_eol_s[0]);
+ fprintf(data.output.stream, "Processing entry item action '");
+ fprintf(data.output.stream, "%s%s%s", data.context.set.title.before->string, controller_string_failsafe, data.context.set.title.after->string);
+ fprintf(data.output.stream, "' setting value to '");
+ fprintf(data.output.stream, "%s%s%s", data.context.set.important.before->string, setting->entry.items.array[setting->failsafe_rule_id].name.string, data.context.set.important.after->string);
+ fprintf(data.output.stream, "'.%c", f_string_eol_s[0]);
+ }
+ }
}
} // for
for (j = 2; j < action->parameters.used; ++j) {
if (fl_string_dynamic_compare_string(controller_string_asynchronous, action->parameters.array[j], controller_string_asynchronous_length) == F_equal_to) {
- // do nothing.
+ action->code = controller_entry_rule_code_asynchronous;
}
else if (fl_string_dynamic_compare_string(controller_string_require, action->parameters.array[j], controller_string_require_length) == F_equal_to) {
- // do nothing.
+ action->code = controller_entry_rule_code_require;
}
else if (fl_string_dynamic_compare_string(controller_string_wait, action->parameters.array[j], controller_string_wait_length) == F_equal_to) {
- // do nothing.
+ action->code = controller_entry_rule_code_wait;
}
else {
if (action->status == F_none) {
}
} // for
}
- else if (action->type == controller_entry_action_type_item) {
+ else if (action->type == controller_entry_action_type_failsafe || action->type == controller_entry_action_type_item) {
if (fl_string_dynamic_compare_string(controller_string_main, action->parameters.array[0], controller_string_main_length) == F_equal_to) {
action->status = F_status_set_error(F_supported_not);
}
}
else if (action->type == controller_entry_action_type_timeout) {
+
if (fl_string_dynamic_compare_string(controller_string_kill, action->parameters.array[0], controller_string_kill_length) == F_equal_to) {
- // do nothing
+ action->code = controller_entry_timeout_code_kill;
}
else if (fl_string_dynamic_compare_string(controller_string_start, action->parameters.array[0], controller_string_start_length) == F_equal_to) {
- // do nothing
+ action->code = controller_entry_timeout_code_start;
}
else if (fl_string_dynamic_compare_string(controller_string_stop, action->parameters.array[0], controller_string_stop_length) == F_equal_to) {
- // do nothing
+ action->code = controller_entry_timeout_code_stop;
}
else {
action->status = F_status_set_error(F_supported_not);
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;
+ missing |= 0x1;
for (k = 0; k < entry->items.used; ++k) {
} // for
if (missing & 0x1) {
- missing &= 0x2;
+ missing |= 0x2;
cache->line_action = action->line;
cache->line_item = entry->items.array[i].line;
if (data.error.verbosity != f_console_verbosity_quiet) {
fprintf(data.error.to.stream, "%c", f_string_eol_s[0]);
- fprintf(data.error.to.stream, "The requested entry item '");
+ fprintf(data.error.to.stream, "%s%sThe required entry item '", data.error.context.before->string, data.error.prefix ? data.error.prefix : f_string_empty_s);
fprintf(data.error.to.stream, "%s%s%s%s", data.error.context.after->string, data.error.notable.before->string, action->parameters.array[0].string, data.error.notable.after->string);
fprintf(data.error.to.stream, "%s' does not exist.%s%c", data.error.context.before->string, data.error.context.after->string, f_string_eol_s[0]);
controller_entry_error_print(data.error, *cache);
}
- entry->status = controller_status_simplify(F_found_not);
+ action->number = 0;
+ action->status = controller_status_simplify(F_found_not);
+
+ // @fixme review how entry->status is being handled with respect to action->status (here the action failed, should the entire entry fail? at the moment if mode is simulation this prevents simulation from continuing).
+ //entry->status = controller_status_simplify(F_found_not);
cache->name_action.used = 0;
cache->name_item.used = 0;
}
+ else {
+ action->number = k;
+ }
}
} // for
} // for
// the error is already fully printed and the entry status is already assigned, so immediately exit.
if (missing & 0x2) {
- return entry->status;
+ // @fixme review how entry->status is being handled with respect to action->status (here the action failed, should the entire entry fail? at the moment if mode is simulation this prevents simulation from continuing).
+ //return entry->status;
}
}
}
}
#endif // _di_controller_rule_simulate_
-#ifndef _di_controller_rules_increase_by_
- f_return_status controller_rules_increase_by(const f_array_length_t amount, controller_rules_t *rules) {
+#ifndef _di_controller_rules_increase_
+ f_return_status controller_rules_increase(controller_rules_t *rules) {
- if (rules->used + amount > rules->size) {
- if (rules->used + amount > f_array_length_t_size) {
- return F_status_set_error(F_array_too_large);
+ if (rules->used + 1 > rules->size) {
+ f_array_length_t size = rules->used + controller_default_allocation_step;
+
+ if (size > f_string_length_t_size) {
+ if (rules->used + 1 > f_array_length_t_size) {
+ return F_status_set_error(F_array_too_large);
+ }
+
+ size = f_array_length_t_size;
}
- const f_status_t status = f_memory_resize((void **) & rules->array, sizeof(controller_rule_t), rules->size, rules->used + amount);
+ const f_status_t status = f_memory_resize((void **) & rules->array, sizeof(controller_rule_t), rules->size, size);
if (F_status_is_error_not(status)) {
- rules->size = rules->used + amount;
+ rules->size = size;
}
return status;
return F_none;
}
-#endif // _di_controller_rule_increase_by_
+#endif // _di_controller_rules_increase_
#ifdef __cplusplus
} // extern "C"
#endif // _di_controller_rule_simulate_
/**
- * Increase the size of the rules array by the specified amount, but only if necessary.
+ * Increase the size of the rules array, but only if necessary.
*
- * This only increases size if the current used plus amount is greater than the currently allocated size.
- *
- * @param amount
- * A positive number representing how much to increase the size by.
* @param rules
* The rules to resize.
*
*
* @see f_memory_resize()
*/
-#ifndef _di_controller_rules_increase_by_
- extern f_return_status controller_rules_increase_by(const f_array_length_t amount, controller_rules_t *rules) f_gcc_attribute_visibility_internal;
-#endif // _di_controller_rule_increase_by_
+#ifndef _di_controller_rules_increase_
+ extern f_return_status controller_rules_increase(controller_rules_t *rules) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_rule_increase_
#ifdef __cplusplus
} // extern "C"