]> Kevux Git Server - fll/commitdiff
Progress: controller program.
authorKevin Day <thekevinday@gmail.com>
Mon, 14 Dec 2020 02:36:58 +0000 (20:36 -0600)
committerKevin Day <thekevinday@gmail.com>
Mon, 14 Dec 2020 02:36:58 +0000 (20:36 -0600)
level_3/controller/c/private-common.h
level_3/controller/c/private-controller.c
level_3/controller/c/private-entry.c
level_3/controller/c/private-rule.c
level_3/controller/c/private-rule.h

index 0508ca4827b08a0cbbec1f6d6338ba1b45ca9e37..4d9059c63276d1e69e4bc92458f0362238fe1bf1 100644 (file)
@@ -239,6 +239,10 @@ extern "C" {
     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;
@@ -262,6 +266,8 @@ extern "C" {
       F_known_not, \
       0, \
       0, \
+      0, \
+      0, \
       f_time_spec_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
@@ -457,9 +463,16 @@ extern "C" {
 
   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;
 
@@ -472,6 +485,11 @@ extern "C" {
       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, \
index ee07570166c849e3b2b8dd436440f4cef347534f..b1e3f529a38e8e99d79b4abe7336264bc5a175ed 100644 (file)
@@ -539,6 +539,20 @@ extern "C" {
           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) {
@@ -625,10 +639,10 @@ extern "C" {
         }
         else if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_consider || actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_rule) {
 
-          status = controller_rules_increase_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;
@@ -715,30 +729,69 @@ extern "C" {
           }
         }
         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
index 5ef7a96682a50cffc2a216c66a3fa38bebc74a32..6b677b6506fc070d9d8f9551684fb70c11563da8 100644 (file)
@@ -396,13 +396,13 @@ extern "C" {
             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) {
@@ -428,7 +428,7 @@ extern "C" {
               }
             } // 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);
 
@@ -445,14 +445,15 @@ extern "C" {
             }
           }
           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);
@@ -804,7 +805,7 @@ extern "C" {
                 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) {
 
@@ -818,7 +819,7 @@ extern "C" {
                   } // for
 
                   if (missing & 0x1) {
-                    missing &= 0x2;
+                    missing |= 0x2;
 
                     cache->line_action = action->line;
                     cache->line_item = entry->items.array[i].line;
@@ -832,25 +833,33 @@ extern "C" {
 
                     if (data.error.verbosity != f_console_verbosity_quiet) {
                       fprintf(data.error.to.stream, "%c", f_string_eol_s[0]);
-                      fprintf(data.error.to.stream, "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;
             }
           }
         }
index 4c19ed340b63fcbcaeadceec11710abb61eebbf1..459c07ab7f3255382cbda9874fb729768e3ed11a 100644 (file)
@@ -1876,18 +1876,24 @@ extern "C" {
   }
 #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;
@@ -1895,7 +1901,7 @@ extern "C" {
 
     return F_none;
   }
-#endif // _di_controller_rule_increase_by_
+#endif // _di_controller_rules_increase_
 
 #ifdef __cplusplus
 } // extern "C"
index 42eba62af5760a60018c4287a457b06fd57e03d9..6c7545ba99aec769bb5989f25dd19e5bb5086f41 100644 (file)
@@ -462,12 +462,8 @@ 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.
  *
@@ -479,9 +475,9 @@ extern "C" {
  *
  * @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"