#define controller_string_deadline "deadline"
#define controller_string_default "default"
#define controller_string_define "define"
+ #define controller_string_delay "delay"
#define controller_string_disable "disable"
#define controller_string_entry "entry"
#define controller_string_entries "entries"
#define controller_string_exits "exits"
#define controller_string_fail "fail"
#define controller_string_failsafe "failsafe"
+ #define controller_string_failure "failure"
#define controller_string_fifo "fifo"
#define controller_string_freeze "freeze"
#define controller_string_fsize "fsize"
#define controller_string_limit "limit"
#define controller_string_locks "locks"
#define controller_string_main "main"
+ #define controller_string_max "max"
#define controller_string_memlock "memlock"
#define controller_string_method "method"
#define controller_string_mode "mode"
#define controller_string_reload "reload"
#define controller_string_require "require"
#define controller_string_required "required"
+ #define controller_string_rerun "rerun"
+ #define controller_string_reset "reset"
#define controller_string_restart "restart"
#define controller_string_resume "resume"
#define controller_string_round_robin "round_robin"
#define controller_string_start "start"
#define controller_string_stop "stop"
#define controller_string_succeed "succeed"
+ #define controller_string_success "success"
#define controller_string_synchronous "synchronous"
#define controller_string_thaw "thaw"
#define controller_string_timeout "timeout"
#define controller_string_deadline_length 8
#define controller_string_default_length 7
#define controller_string_define_length 6
+ #define controller_string_delay_length 5
#define controller_string_disable_length 7
#define controller_string_entry_length 5
#define controller_string_entries_length 7
#define controller_string_exit_length 4
#define controller_string_exits_length 5
#define controller_string_fail_length 4
+ #define controller_string_failure_length 7
#define controller_string_failsafe_length 8
#define controller_string_fifo_length 4
#define controller_string_freeze_length 6
#define controller_string_limit_length 5
#define controller_string_locks_length 5
#define controller_string_main_length 4
+ #define controller_string_max_length 3
#define controller_string_memlock_length 7
#define controller_string_method_length 6
#define controller_string_mode_length 4
#define controller_string_reload_length 6
#define controller_string_require_length 7
#define controller_string_required_length 8
+ #define controller_string_rerun_length 5
+ #define controller_string_reset_length 5
#define controller_string_restart_length 7
#define controller_string_resume_length 6
#define controller_string_round_robin_length 11
#define controller_string_start_length 5
#define controller_string_stop_length 4
#define controller_string_succeed_length 7
+ #define controller_string_success_length 7
#define controller_string_synchronous_length 11
#define controller_string_thaw_length 4
#define controller_string_timeout_length 7
extern const f_string_t controller_string_deadline_s;
extern const f_string_t controller_string_default_s;
extern const f_string_t controller_string_define_s;
+ extern const f_string_t controller_string_delay_s;
extern const f_string_t controller_string_disable_s;
extern const f_string_t controller_string_entry_s;
extern const f_string_t controller_string_entries_s;
extern const f_string_t controller_string_exits_s;
extern const f_string_t controller_string_fail_s;
extern const f_string_t controller_string_failsafe_s;
+ extern const f_string_t controller_string_failure_s;
extern const f_string_t controller_string_fifo_s;
extern const f_string_t controller_string_freeze_s;
extern const f_string_t controller_string_fsize_s;
extern const f_string_t controller_string_limit_s;
extern const f_string_t controller_string_locks_s;
extern const f_string_t controller_string_main_s;
+ extern const f_string_t controller_string_max_s;
extern const f_string_t controller_string_memlock_s;
extern const f_string_t controller_string_method_s;
extern const f_string_t controller_string_mode_s;
extern const f_string_t controller_string_reload_s;
extern const f_string_t controller_string_require_s;
extern const f_string_t controller_string_required_s;
+ extern const f_string_t controller_string_rerun_s;
+ extern const f_string_t controller_string_reset_s;
extern const f_string_t controller_string_restart_s;
extern const f_string_t controller_string_resume_s;
extern const f_string_t controller_string_round_robin_s;
extern const f_string_t controller_string_start_s;
extern const f_string_t controller_string_stop_s;
extern const f_string_t controller_string_succeed_s;
+ extern const f_string_t controller_string_success_s;
extern const f_string_t controller_string_synchronous_s;
extern const f_string_t controller_string_thaw_s;
extern const f_string_t controller_string_timeout_s;
#endif // _di_controller_mutex_t_
/**
+ * The Rule "rerun" item for controlling re-execution.
+ *
+ * count: A count of the number of executions.
+ * delay: The time to wait before attempting to re-run.
+ * max: The maximum number of times to re-run (with 0 representing re-run infinitely) for executions.
+ */
+#ifndef _di_controller_rule_rerun_item_t_
+ typedef struct {
+ bool reset;
+
+ f_number_unsigned_t count;
+ f_number_unsigned_t delay;
+ f_number_unsigned_t max;
+ } controller_rule_rerun_item_t;
+
+ #define controller_rule_rerun_item_initialize { \
+ F_false, \
+ 0, \
+ 5000, \
+ 0, \
+ }
+#endif // _di_controller_rule_rerun_item_t_
+
+/**
+ * The Rule "rerun" values for controlling re-execution.
+ *
+ * controller_rule_rerun_is_*:
+ * - failure: The success re-run is enabled.
+ * - failure_reset: Reset success counter when failure is returned.
+ * - success: The success re-run is enabled.
+ * - success_reset: Reset failure counter when success is returned.
+ *
+ * is: A bitwise set of options to designate whether rerun is enabled or not and other options.
+ * count_failure: A count of the number of failed executions.
+ * count_success: A count of the number of successful executions.
+ * delay_failure: The time to wait before attempting to "rerun" for failed executions.
+ * delay_success: The time to wait before attempting to "rerun" for successful executions.
+ * max_failure: The maximum number of times to "rerun" (with 0 representing "rerun" infinitely) for failed executions.
+ * max_success: The maximum number of times to "rerun" (with 0 representing "rerun" infinitely) for successful executions.
+ */
+#ifndef _di_controller_rule_rerun_t_
+ #define controller_rule_rerun_is_failure 0x1
+ #define controller_rule_rerun_is_failure_reset 0x2
+ #define controller_rule_rerun_is_success 0x4
+ #define controller_rule_rerun_is_success_reset 0x8
+
+ typedef struct {
+ uint8_t is;
+
+ controller_rule_rerun_item_t failure;
+ controller_rule_rerun_item_t success;
+ } controller_rule_rerun_t;
+
+ #define controller_rule_rerun_initialize { \
+ 0, \
+ controller_rule_rerun_item_initialize, \
+ controller_rule_rerun_item_initialize, \
+ }
+#endif // _di_controller_rule_rerun_t_
+
+/**
* A Rule Action.
*
* controller_rule_action_method_*:
* - kill: The Kill execution instructions.
* - pause: The Pause execution instructions.
* - pid_file: The PID file setting.
+ * - rerun: The Re-run execution after success or failure.
* - reload: The Reload execution instructions.
* - restart: The Restart execution instructions.
* - resume: The Resume execution instructions.
controller_rule_action_type_pause,
controller_rule_action_type_pid_file,
controller_rule_action_type_reload,
+ controller_rule_action_type_rerun,
controller_rule_action_type_restart,
controller_rule_action_type_resume,
controller_rule_action_type_start,
controller_rule_action_type__enum_size,
};
+ enum {
+ controller_rule_action_type_execute_freeze = 0,
+ controller_rule_action_type_execute_kill,
+ controller_rule_action_type_execute_pause,
+ controller_rule_action_type_execute_reload,
+ controller_rule_action_type_execute_restart,
+ controller_rule_action_type_execute_resume,
+ controller_rule_action_type_execute_start,
+ controller_rule_action_type_execute_stop,
+ controller_rule_action_type_execute_thaw,
+
+ // designate the largest value in the enum, the '__' is intended.
+ controller_rule_action_type_execute__enum_size,
+ };
+
typedef struct {
uint8_t type;
f_array_length_t line;
* - utility: A Utility to execute.
*
* type: The type of the Rule Item.
+ * with: A bitwise number representing execute "with" options.
* line: The line number where the Rule Item begins.
+ * reruns: An array designating rerun settings for each execution type available.
* actions: The actions associated with the Rule Item.
*/
#ifndef _di_controller_rule_item_t_
typedef struct {
uint8_t type;
+ uint8_t with;
f_array_length_t line;
+ f_string_dynamic_t pid_file;
+ controller_rule_rerun_t reruns[controller_rule_action_type_execute__enum_size];
controller_rule_actions_t actions;
} controller_rule_item_t;
{ \
0, \
0, \
+ 0, \
+ f_string_dynamic_t_initialize, \
+ { \
+ controller_rule_rerun_t_initialize, \
+ controller_rule_rerun_t_initialize, \
+ controller_rule_rerun_t_initialize, \
+ controller_rule_rerun_t_initialize, \
+ controller_rule_rerun_t_initialize, \
+ controller_rule_rerun_t_initialize, \
+ controller_rule_rerun_t_initialize, \
+ controller_rule_rerun_t_initialize, \
+ controller_rule_rerun_t_initialize, \
+ }, \
controller_rule_actions_t_initialize, \
}
#endif // _di_controller_rule_item_t_
F_known_not, \
F_known_not, \
F_known_not, \
+ F_known_not, \
}, \
0, \
0, \
buffer.used = controller_string_pid_file_length;
break;
+ case controller_rule_action_type_rerun:
+ buffer.string = controller_string_rerun_s;
+ buffer.used = controller_string_rerun_length;
+ break;
+
case controller_rule_action_type_reload:
buffer.string = controller_string_reload_s;
buffer.used = controller_string_reload_length;
if (F_status_is_error(status)) {
controller_error_print(global.main->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true, global.thread);
}
+ else if (type == controller_rule_action_type_pid_file) {
+ item->pid_file.used = 0;
+
+ status = fl_string_dynamic_rip(cache->buffer_item, cache->content_action.array[0], &item->pid_file);
+
+ if (F_status_is_error(status)) {
+ controller_error_print(global.main->error, F_status_set_fine(status), "fl_string_dynamic_rip", F_true, global.thread);
+ }
+ else {
+ status = f_string_dynamic_terminate_after(&item->pid_file);
+
+ if (F_status_is_error(status)) {
+ controller_error_print(global.main->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true, global.thread);
+ }
+ }
+ }
+ else if (type == controller_rule_action_type_rerun) {
+ uint8_t type = 0;
+
+ if (cache->content_action.used) {
+ if (fl_string_dynamic_partial_compare_string(controller_string_freeze_s, cache->buffer_item, controller_string_freeze_length, cache->content_action.array[0]) == F_equal_to) {
+ type = controller_rule_action_type_execute_freeze;
+ }
+ if (fl_string_dynamic_partial_compare_string(controller_string_kill_s, cache->buffer_item, controller_string_kill_length, cache->content_action.array[0]) == F_equal_to) {
+ type = controller_rule_action_type_execute_kill;
+ }
+ else if (fl_string_dynamic_partial_compare_string(controller_string_pause_s, cache->buffer_item, controller_string_pause_length, cache->content_action.array[0]) == F_equal_to) {
+ type = controller_rule_action_type_execute_pause;
+ }
+ else if (fl_string_dynamic_partial_compare_string(controller_string_reload_s, cache->buffer_item, controller_string_reload_length, cache->content_action.array[0]) == F_equal_to) {
+ type = controller_rule_action_type_execute_reload;
+ }
+ else if (fl_string_dynamic_partial_compare_string(controller_string_restart_s, cache->buffer_item, controller_string_restart_length, cache->content_action.array[0]) == F_equal_to) {
+ type = controller_rule_action_type_execute_restart;
+ }
+ else if (fl_string_dynamic_partial_compare_string(controller_string_resume_s, cache->buffer_item, controller_string_resume_length, cache->content_action.array[0]) == F_equal_to) {
+ type = controller_rule_action_type_execute_resume;
+ }
+ else if (fl_string_dynamic_partial_compare_string(controller_string_start_s, cache->buffer_item, controller_string_start_length, cache->content_action.array[0]) == F_equal_to) {
+ type = controller_rule_action_type_execute_start;
+ }
+ else if (fl_string_dynamic_partial_compare_string(controller_string_stop_s, cache->buffer_item, controller_string_stop_length, cache->content_action.array[0]) == F_equal_to) {
+ type = controller_rule_action_type_execute_stop;
+ }
+ else if (fl_string_dynamic_partial_compare_string(controller_string_thaw_s, cache->buffer_item, controller_string_thaw_length, cache->content_action.array[0]) == F_equal_to) {
+ type = controller_rule_action_type_execute_thaw;
+ }
+ }
+
+ if (!type) {
+ if (global.main->error.verbosity != f_console_verbosity_quiet) {
+ controller_print_lock(global.main->error.to, global.thread);
+
+ fl_print_format("%c%[%SRule item action '%]", global.main->error.to.stream, f_string_eol_s[0], global.main->error.context, global.main->error.prefix, global.main->error.context);
+ fl_print_format("%[%s%]", global.main->error.to.stream, global.main->error.notable, controller_string_rerun_s, global.main->error.notable);
+ fl_print_format("%[' has '%]", global.main->error.to.stream, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%/Q%]", global.main->error.to.stream, global.main->error.notable, cache->buffer_item, cache->content_action.array[0], global.main->error.notable);
+ fl_print_format("%[' as the first value, only the following are allowed: '%]", global.main->error.to.stream, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%s%]%[', '%]", global.main->error.to.stream, global.main->error.notable, controller_string_freeze_s, global.main->error.notable, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%s%]%[', '%]", global.main->error.to.stream, global.main->error.notable, controller_string_kill_s, global.main->error.notable, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%s%]%[', '%]", global.main->error.to.stream, global.main->error.notable, controller_string_pause_s, global.main->error.notable, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%s%]%[', '%]", global.main->error.to.stream, global.main->error.notable, controller_string_reload_s, global.main->error.notable, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%s%]%[', '%]", global.main->error.to.stream, global.main->error.notable, controller_string_restart_s, global.main->error.notable, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%s%]%[', '%]", global.main->error.to.stream, global.main->error.notable, controller_string_resume_s, global.main->error.notable, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%s%]%[', '%]", global.main->error.to.stream, global.main->error.notable, controller_string_start_s, global.main->error.notable, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%s%]%[', or '%]", global.main->error.to.stream, global.main->error.notable, controller_string_stop_s, global.main->error.notable, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%s%]", global.main->error.to.stream, global.main->error.notable, controller_string_thaw_s, global.main->error.notable, global.main->error.context);
+ fl_print_format("%['.%]%c", global.main->error.to.stream, global.main->error.context, global.main->error.context, f_string_eol_s[0]);
+
+ controller_rule_error_print_cache(global.main->error, cache->action, F_true);
+
+ controller_print_unlock_flush(global.main->error.to, global.thread);
+ }
+
+ return F_status_set_error(F_valid_not);
+ }
+
+ controller_rule_rerun_item_t *rerun_item = 0;
+
+ if (cache->content_action.used > 1) {
+ if (fl_string_dynamic_partial_compare_string(controller_string_failure_s, cache->buffer_item, controller_string_failure_length, cache->content_action.array[1]) == F_equal_to) {
+ rerun_item = &item->reruns[type].failure;
+ item->reruns[type].is |= controller_rule_rerun_is_failure;
+ }
+ else if (fl_string_dynamic_partial_compare_string(controller_string_success_s, cache->buffer_item, controller_string_success_length, cache->content_action.array[1]) == F_equal_to) {
+ rerun_item = &item->reruns[type].success;
+ item->reruns[type].is |= controller_rule_rerun_is_success;
+ }
+ }
+ else {
+ if (global.main->error.verbosity != f_console_verbosity_quiet) {
+ controller_print_lock(global.main->error.to, global.thread);
+
+ fl_print_format("%c%[%SRule item action '%]", global.main->error.to.stream, f_string_eol_s[0], global.main->error.context, global.main->error.prefix, global.main->error.context);
+ fl_print_format("%[%s%]", global.main->error.to.stream, global.main->error.notable, controller_string_rerun_s, global.main->error.notable);
+ fl_print_format("%[' has '%]", global.main->error.to.stream, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%/Q%]", global.main->error.to.stream, global.main->error.notable, cache->buffer_item, cache->content_action.array[1], global.main->error.notable);
+ fl_print_format("%[' as the second value, only the following are allowed: '%]", global.main->error.to.stream, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%s%]%[' or '%]", global.main->error.to.stream, global.main->error.notable, controller_string_stop_s, global.main->error.notable, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%s%]", global.main->error.to.stream, global.main->error.notable, controller_string_thaw_s, global.main->error.notable, global.main->error.context);
+ fl_print_format("%['.%]%c", global.main->error.to.stream, global.main->error.context, global.main->error.context, f_string_eol_s[0]);
+
+ controller_rule_error_print_cache(global.main->error, cache->action, F_true);
+
+ controller_print_unlock_flush(global.main->error.to, global.thread);
+ }
+
+ return F_status_set_error(F_valid_not);
+ }
+
+ for (f_array_length_t i = 2; i < cache->content_action.used; ++i) {
+
+ if (fl_string_dynamic_partial_compare_string(controller_string_delay_s, cache->buffer_item, controller_string_delay_length, cache->content_action.array[i]) == F_equal_to) {
+ status = controller_rule_action_read_rerun_number(global, controller_string_delay_s, cache, &i, &rerun_item->delay);
+ }
+ else if (fl_string_dynamic_partial_compare_string(controller_string_max_s, cache->buffer_item, controller_string_max_length, cache->content_action.array[i]) == F_equal_to) {
+ status = controller_rule_action_read_rerun_number(global, controller_string_max_s, cache, &i, &rerun_item->max);
+ }
+ else if (fl_string_dynamic_partial_compare_string(controller_string_reset_s, cache->buffer_item, controller_string_reset_length, cache->content_action.array[i]) == F_equal_to) {
+ item->reruns[type].is |= rerun_item == &item->reruns[type].failure ? controller_rule_rerun_is_failure_reset : controller_rule_rerun_is_success_reset;
+ }
+ else {
+ if (global.main->error.verbosity != f_console_verbosity_quiet) {
+ controller_print_lock(global.main->error.to, global.thread);
+
+ fl_print_format("%c%[%SRule item action '%]", global.main->error.to.stream, f_string_eol_s[0], global.main->error.context, global.main->error.prefix, global.main->error.context);
+ fl_print_format("%[%s%]", global.main->error.to.stream, global.main->error.notable, controller_string_rerun_s, global.main->error.notable);
+ fl_print_format("%[' has an unknown value '%]", global.main->error.to.stream, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%/Q%]", global.main->error.to.stream, global.main->error.notable, cache->buffer_item, cache->content_action.array[i], global.main->error.notable);
+ fl_print_format("%['.%]%c", global.main->error.to.stream, global.main->error.context, global.main->error.context, f_string_eol_s[0]);
+
+ controller_rule_error_print_cache(global.main->error, cache->action, F_true);
+
+ controller_print_unlock_flush(global.main->error.to, global.thread);
+ }
+
+ return F_status_set_error(F_valid_not);
+ }
+ } // for
+ }
+ else if (type == controller_rule_action_type_with) {
+ item->with = 0;
+
+ for (f_array_length_t i = 0; i < cache->content_action.used; ++i) {
+
+ if (fl_string_dynamic_partial_compare_string(controller_string_full_path_s, cache->buffer_item, controller_string_full_path_length, cache->content_action.array[i]) == F_equal_to) {
+ item->with |= controller_with_full_path;
+ }
+ else {
+ if (global.main->error.verbosity != f_console_verbosity_quiet) {
+ controller_print_lock(global.main->error.to, global.thread);
+
+ fl_print_format("%c%[%SUnknown value '%]", global.main->error.to.stream, f_string_eol_s[0], global.main->error.context, global.main->error.prefix, global.main->error.context);
+ fl_print_format("%[%/Q%]", global.main->error.to.stream, global.main->error.notable, cache->buffer_item, cache->content_action.array[i], global.main->error.notable);
+ fl_print_format("%[' for rule item action '%]%[%s%]", global.main->error.to.stream, global.main->error.context, global.main->error.context, global.main->error.notable, controller_string_with_s, global.main->error.notable);
+ fl_print_format("%['.%]%c", global.main->error.to.stream, global.main->error.context, global.main->error.context, f_string_eol_s[0]);
+
+ controller_rule_error_print_cache(global.main->error, cache->action, F_true);
+
+ controller_print_unlock_flush(global.main->error.to, global.thread);
+ }
+
+ status = F_status_set_error(F_valid_not);
+ break;
+ }
+ } // for
+ }
else if (item->type == controller_rule_item_type_script || item->type == controller_rule_item_type_utility) {
status = f_string_dynamics_increase(controller_common_allocation_small, &actions->array[actions->used].parameters);
if (F_status_is_error(status)) break;
} // for
- if (F_status_is_error_not(status)) {
+ if (F_status_is_error(status)) {
+ controller_error_print(global.main->error, F_status_set_fine(status), "f_string_dynamic_partial_mash_nulless", F_true, global.thread);
+ }
+ else {
status = f_string_dynamic_terminate_after(&actions->array[actions->used].parameters.array[0]);
if (F_status_is_error(status)) {
controller_error_print(global.main->error, F_status_set_fine(status), "f_string_dynamic_terminate_after", F_true, global.thread);
}
else {
- actions->array[actions->used++].parameters.used = 1;
+ actions->array[actions->used].parameters.used = 1;
}
}
}
-
- return status;
}
else {
status = f_fss_count_lines(cache->buffer_item, range->start, &actions->array[actions->used].line);
}
#endif // _di_controller_rule_action_read_
+#ifndef _di_controller_rule_action_read_rerun_number_
+ f_status_t controller_rule_action_read_rerun_number(const controller_global_t global, const f_string_t name, controller_cache_t *cache, f_array_length_t *index, f_number_unsigned_t *number) {
+
+ f_status_t status = F_none;
+ f_number_unsigned_t parsed = 0;
+
+ if (*index + 1 == cache->content_action.used) {
+ status = F_status_set_error(F_valid_not);
+ }
+ else {
+ status = fl_conversion_string_to_number_signed(cache->buffer_item.string, cache->content_action.array[++(*index)], &parsed);
+
+ if (F_status_set_fine(status) == F_number_positive) {
+ status = fl_conversion_string_to_number_signed(cache->buffer_item.string, controller_range_after_number_sign(cache->buffer_item, cache->content_action.array[*index]), &parsed);
+ }
+
+ if (status == F_data_not) {
+ status = F_status_set_error(F_valid_not);
+ }
+ }
+
+ if (F_status_is_error(status)) {
+ if (global.main->error.verbosity != f_console_verbosity_quiet) {
+ status = F_status_set_fine(status);
+
+ if (status != F_valid_not && status != F_number && status != F_number_decimal && status != F_number_overflow && status != F_number_underflow && status != F_number_negative) {
+ controller_error_print(global.main->error, F_status_set_fine(status), "f_string_dynamics_increase", F_true, global.thread);
+ }
+ else {
+ controller_print_lock(global.main->error.to, global.thread);
+
+ fl_print_format("%c%[%SRule item action '%]", global.main->error.to.stream, f_string_eol_s[0], global.main->error.context, global.main->error.prefix, global.main->error.context);
+ fl_print_format("%[%s%]", global.main->error.to.stream, global.main->error.notable, controller_string_rerun_s, global.main->error.notable);
+ fl_print_format("%[' requires a positive whole number or 0 for the '%]", global.main->error.to.stream, global.main->error.context, global.main->error.context);
+ fl_print_format("%[%S%]", global.main->error.to.stream, global.main->error.notable, name, global.main->error.notable);
+ fl_print_format("%[' value", global.main->error.to.stream, global.main->error.context, global.main->error.context);
+
+ if (*index + 1 == cache->content_action.used) {
+ fl_print_format(", but none were given.%]%c", global.main->error.to.stream, global.main->error.context, f_string_eol_s[0]);
+ }
+ else {
+ fl_print_format(", but '%]%[%/Q%]", global.main->error.to.stream, global.main->error.context, global.main->error.notable, cache->buffer_item, cache->content_action.array[*index], global.main->error.notable);
+
+ if (status == F_number || status == F_number_decimal) {
+ fl_print_format("%[' was given.%]%c", global.main->error.to.stream, global.main->error.context, global.main->error.context, f_string_eol_s[0]);
+ }
+ else if (status == F_number_overflow) {
+ fl_print_format("%[' is too large.%]%c", global.main->error.to.stream, global.main->error.context, global.main->error.context, f_string_eol_s[0]);
+ }
+ else {
+ fl_print_format("%[' is negative.%]%c", global.main->error.to.stream, global.main->error.context, global.main->error.context, f_string_eol_s[0]);
+ }
+ }
+
+ controller_rule_error_print_cache(global.main->error, cache->action, F_true);
+
+ controller_print_unlock_flush(global.main->error.to, global.thread);
+ }
+ }
+
+ return status;
+ }
+
+ *number = parsed;
+ return F_none;
+ }
+#endif // _di_controller_rule_action_read_rerun_number_
+
#ifndef _di_controller_rule_copy_
f_status_t controller_rule_copy(const controller_rule_t source, controller_rule_t *destination) {
}
item_destination->type = item_source->type;
+ item_destination->with = item_source->with;
item_destination->line = item_source->line;
+ item_destination->pid_file.used = 0;
+
+ status = f_string_dynamic_append(item_source->pid_file, &item_destination->pid_file);
+ if (F_status_is_error(status)) return status;
+
+ status = f_string_dynamic_terminate_after(&item_destination->pid_file);
+ if (F_status_is_error(status)) return status;
+
+ for (j = 0; j < controller_rule_action_type_execute__enum_size; ++j) {
+ item_destination->reruns[j].is = item_source->reruns[j].is;
+ item_destination->reruns[j].failure.count = item_source->reruns[j].failure.count;
+ item_destination->reruns[j].failure.delay = item_source->reruns[j].failure.delay;
+ item_destination->reruns[j].failure.max = item_source->reruns[j].failure.max;
+ item_destination->reruns[j].success.count = item_source->reruns[j].success.count;
+ item_destination->reruns[j].success.delay = item_source->reruns[j].success.delay;
+ item_destination->reruns[j].success.max = item_source->reruns[j].success.max;
+ } // for
for (j = 0; j < item_source->actions.used; ++j) {
f_array_length_t j = 0;
f_array_length_t k = 0;
- f_string_dynamic_t *pid_file = 0;
-
- uint8_t with = 0;
-
// child processes should receive all signals and handle the signals as they see fit.
f_signal_how_t signals = f_signal_how_t_initialize;
f_signal_set_empty(&signals.block);
if (process->rule.items.array[i].type == controller_rule_item_type_setting) continue;
- with = 0;
-
- for (j = 0; j < process->rule.items.array[i].actions.used; ++j) {
-
- if (process->rule.items.array[i].actions.array[j].type == controller_rule_action_type_with) {
- for (k = 0; k < process->rule.items.array[i].actions.array[j].parameters.used; ++k) {
-
- if (fl_string_dynamic_compare_string(controller_string_full_path_s, process->rule.items.array[i].actions.array[j].parameters.array[k], controller_string_full_path_length) == F_equal_to) {
- with |= controller_with_full_path;
- }
- } // for
- }
- } // for
-
for (j = 0; j < process->rule.items.array[i].actions.used; ++j) {
if (!controller_thread_is_enabled_process(process, global.thread)) {
execute_set.parameter.data = 0;
execute_set.parameter.option = fl_execute_parameter_option_threadsafe | fl_execute_parameter_option_return;
- if (with & controller_with_full_path) {
+ if (process->rule.items.array[i].with & controller_with_full_path) {
execute_set.parameter.option |= fl_execute_parameter_option_path;
}
+ // @todo: wrap these executions (foreground and background) in an additional loop to re-execution on the given re-run conditions.
if (process->rule.items.array[i].type == controller_rule_item_type_command) {
status = controller_rule_execute_foreground(process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], 0, process->rule.items.array[i].actions.array[j].parameters, options, global, &execute_set, process);
}
}
else if (process->rule.items.array[i].type == controller_rule_item_type_service) {
- pid_file = 0;
-
- for (k = 0; k < process->rule.items.array[i].actions.used; ++k) {
-
- if (process->rule.items.array[i].actions.array[k].type != controller_rule_action_type_pid_file) {
- continue;
- }
-
- if (!process->rule.items.array[i].actions.array[k].parameters.used) {
- continue;
- }
-
- pid_file = &process->rule.items.array[i].actions.array[k].parameters.array[0];
- } // for
-
- if (pid_file) {
- status = controller_rule_execute_pid_with(*pid_file, process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], 0, process->rule.items.array[i].actions.array[j].parameters, options, with, global, &execute_set, process);
+ if (process->rule.items.array[i].pid_file.used) {
+ status = controller_rule_execute_pid_with(process->rule.items.array[i].pid_file, process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], 0, process->rule.items.array[i].actions.array[j].parameters, options, process->rule.items.array[i].with, global, &execute_set, process);
if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break;
}
}
else if (process->rule.items.array[i].type == controller_rule_item_type_utility) {
- pid_file = 0;
-
- for (k = 0; k < process->rule.items.array[i].actions.used; ++k) {
-
- if (process->rule.items.array[i].actions.array[k].type != controller_rule_action_type_pid_file) {
- continue;
- }
-
- if (!process->rule.items.array[i].actions.array[k].parameters.used) {
- continue;
- }
-
- pid_file = &process->rule.items.array[i].actions.array[k].parameters.array[0];
- } // for
-
- if (pid_file) {
+ if (process->rule.items.array[i].pid_file.used) {
execute_set.parameter.data = &process->rule.items.array[i].actions.array[j].parameters.array[0];
- status = controller_rule_execute_pid_with(*pid_file, process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], process->rule.script.used ? process->rule.script.string : controller_default_program_script, arguments_none, options, with, global, &execute_set, process);
+ status = controller_rule_execute_pid_with(process->rule.items.array[i].pid_file, process->rule.items.array[i].type, process->rule.items.array[i].actions.array[j], process->rule.script.used ? process->rule.script.string : controller_default_program_script, arguments_none, options, process->rule.items.array[i].with, global, &execute_set, process);
if (status == F_child || status == F_signal || F_status_set_fine(status) == F_lock) break;
break;
}
- if (fl_string_dynamic_compare_string(controller_string_group_s, cache->action.name_action, controller_string_group_length) == F_equal_to) {
+ if (fl_string_dynamic_compare_string(controller_string_freeze_s, cache->action.name_action, controller_string_freeze_length) == F_equal_to) {
+ type = controller_rule_action_type_freeze;
+ }
+ else if (fl_string_dynamic_compare_string(controller_string_group_s, cache->action.name_action, controller_string_group_length) == F_equal_to) {
type = controller_rule_action_type_group;
}
else if (fl_string_dynamic_compare_string(controller_string_kill_s, cache->action.name_action, controller_string_kill_length) == F_equal_to) {
else if (fl_string_dynamic_compare_string(controller_string_pid_file_s, cache->action.name_action, controller_string_pid_file_length) == F_equal_to) {
type = controller_rule_action_type_pid_file;
}
+ else if (fl_string_dynamic_compare_string(controller_string_reload_s, cache->action.name_action, controller_string_reload_length) == F_equal_to) {
+ type = controller_rule_action_type_reload;
+ }
+ else if (fl_string_dynamic_compare_string(controller_string_rerun_s, cache->action.name_action, controller_string_rerun_length) == F_equal_to) {
+ type = controller_rule_action_type_rerun;
+ }
else if (fl_string_dynamic_compare_string(controller_string_restart_s, cache->action.name_action, controller_string_restart_length) == F_equal_to) {
type = controller_rule_action_type_restart;
}
else if (fl_string_dynamic_compare_string(controller_string_resume_s, cache->action.name_action, controller_string_resume_length) == F_equal_to) {
type = controller_rule_action_type_resume;
}
- else if (fl_string_dynamic_compare_string(controller_string_reload_s, cache->action.name_action, controller_string_reload_length) == F_equal_to) {
- type = controller_rule_action_type_reload;
- }
else if (fl_string_dynamic_compare_string(controller_string_start_s, cache->action.name_action, controller_string_start_length) == F_equal_to) {
type = controller_rule_action_type_start;
}
else if (fl_string_dynamic_compare_string(controller_string_stop_s, cache->action.name_action, controller_string_stop_length) == F_equal_to) {
type = controller_rule_action_type_stop;
}
+ else if (fl_string_dynamic_compare_string(controller_string_thaw_s, cache->action.name_action, controller_string_thaw_length) == F_equal_to) {
+ type = controller_rule_action_type_thaw;
+ }
else if (fl_string_dynamic_compare_string(controller_string_user_s, cache->action.name_action, controller_string_user_length) == F_equal_to) {
type = controller_rule_action_type_user;
}
if (rule.items.used) {
controller_rule_action_t *action = 0;
controller_rule_item_t *item = 0;
+ controller_rule_rerun_item_t *rerun_item = 0;
f_string_dynamic_t *parameter = 0;
f_array_length_t j = 0;
fl_print_format(" %[%s%] {%c", main->output.stream, main->context.set.important, controller_string_item_s, main->context.set.important, f_string_eol_s[0]);
fl_print_format(" %[%s%] %Q%c", main->output.stream, main->context.set.important, controller_string_type_s, main->context.set.important, controller_rule_item_type_name(item->type), f_string_eol_s[0]);
+ fl_print_format(" %[%s%] {%c", main->output.stream, main->context.set.important, controller_string_rerun_s, main->context.set.important, f_string_eol_s[0]);
+ for (j = 0; j < controller_rule_action_type_execute__enum_size; ++j) {
+
+ for (k = 0; k < 2; ++k) {
+ if (!k && (item->reruns[j].is & controller_rule_rerun_is_failure)) {
+ rerun_item = &item->reruns[j].failure;
+ }
+ else if (k && (item->reruns[j].is & controller_rule_rerun_is_success)) {
+ rerun_item = &item->reruns[j].success;
+ }
+ else {
+ rerun_item = 0;
+ continue;
+ }
+
+ fl_print_format(" %[", main->output.stream, main->context.set.important);
+ switch (j) {
+ case controller_rule_action_type_execute_freeze:
+ f_print_terminated(controller_string_freeze_s, main->output.stream);
+ break;
+
+ case controller_rule_action_type_execute_kill:
+ f_print_terminated(controller_string_kill_s, main->output.stream);
+ break;
+
+ case controller_rule_action_type_execute_pause:
+ f_print_terminated(controller_string_pause_s, main->output.stream);
+ break;
+
+ case controller_rule_action_type_execute_reload:
+ f_print_terminated(controller_string_reload_s, main->output.stream);
+ break;
+
+ case controller_rule_action_type_execute_restart:
+ f_print_terminated(controller_string_restart_s, main->output.stream);
+ break;
+
+ case controller_rule_action_type_execute_resume:
+ f_print_terminated(controller_string_resume_s, main->output.stream);
+ break;
+
+ case controller_rule_action_type_execute_start:
+ f_print_terminated(controller_string_start_s, main->output.stream);
+ break;
+
+ case controller_rule_action_type_execute_stop:
+ f_print_terminated(controller_string_stop_s, main->output.stream);
+ break;
+
+ case controller_rule_action_type_execute_thaw:
+ f_print_terminated(controller_string_thaw_s, main->output.stream);
+ break;
+
+ default:
+ break;
+ }
+
+ fl_print_format("%] %s", main->output.stream, main->context.set.important, k ? controller_string_success_s : controller_string_failure_s);
+ fl_print_format(" %s %ul %s %ul", main->output.stream, controller_string_delay_s, rerun_item->delay, controller_string_max_s, rerun_item->max);
+
+ if (!k && (item->reruns[j].is & controller_rule_rerun_is_failure_reset) || k && (item->reruns[j].is & controller_rule_rerun_is_success_reset)) {
+ fl_print_format(" %s", main->output.stream, controller_string_reset_s);
+ }
+
+ f_print_terminated(f_string_eol_s, main->output.stream);
+ } // for
+ } // for
+ fl_print_format(" }%c", main->output.stream, f_string_eol_s[0]);
+
+ fl_print_format(" %[%s%]", main->output.stream, main->context.set.important, controller_string_pid_file_s, main->context.set.important);
+ if (item->pid_file.used) {
+ fl_print_format(" %Q", main->output.stream, item->pid_file);
+ }
+ f_print_terminated(f_string_eol_s, main->output.stream);
+
+ fl_print_format(" %[%s%]", main->output.stream, main->context.set.important, controller_string_with_s, main->context.set.important);
+ if (item->with & controller_with_full_path) {
+ fl_print_format(" %s", main->output.stream, controller_string_full_path_s);
+ }
+ f_print_terminated(f_string_eol_s, main->output.stream);
+
for (j = 0; j < item->actions.used; ++j) {
action = &item->actions.array[j];