]> Kevux Git Server - fll/commitdiff
Progress: controller program.
authorKevin Day <thekevinday@gmail.com>
Tue, 8 Dec 2020 04:02:23 +0000 (22:02 -0600)
committerKevin Day <thekevinday@gmail.com>
Tue, 8 Dec 2020 04:02:23 +0000 (22:02 -0600)
level_3/controller/c/private-common.h
level_3/controller/c/private-controller.c
level_3/controller/c/private-controller.h
level_3/controller/c/private-entry.c
level_3/controller/c/private-rule.c
level_3/controller/c/private-rule.h
level_3/controller/data/settings/rules/task/clock.rule [moved from level_3/controller/data/settings/rules/task/clock with 100% similarity]
level_3/controller/data/settings/rules/task/keyboard.rule [moved from level_3/controller/data/settings/rules/task/keyboard with 100% similarity]

index 1e1875e9e3af10b48f68e29a6683fe5537c57e1d..7e6e906ff8ddaa04d11916284bd587fa8c7f502c 100644 (file)
@@ -224,6 +224,8 @@ extern "C" {
   typedef struct {
     f_status_t status;
 
+    f_time_spec_t timestamp;
+
     f_string_dynamic_t id;
     f_string_dynamic_t name;
     f_string_dynamic_t control_group;
@@ -243,6 +245,8 @@ extern "C" {
   #define controller_rule_t_initialize \
     { \
       F_known_not, \
+      0, \
+      f_time_spec_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
       f_string_dynamic_t_initialize, \
@@ -468,6 +472,8 @@ extern "C" {
     f_string_length_t line_action;
     f_string_length_t line_item;
 
+    f_time_spec_t timestamp;
+
     f_string_range_t range_action;
 
     f_array_lengths_t ats;
@@ -494,6 +500,7 @@ extern "C" {
     { \
       0, \
       0, \
+      f_time_spec_t_initialize, \
       f_string_range_t_initialize, \
       f_array_lengths_t_initialize, \
       f_fss_comments_t_initialize, \
index 9a3da4889cff1e806a1bb411d09ebdc7808519c0..7b9c526f0d572be31c2bba94aa1b5f6a2b3f9529 100644 (file)
@@ -79,14 +79,19 @@ extern "C" {
 #endif // _di_controller_string_dynamic_partial_append_terminated_
 
 #ifndef _di_controller_file_load_
-  f_return_status controller_file_load(const controller_data_t data, const controller_setting_t setting, const f_string_t path_prefix, const f_string_static_t path_name, const f_string_t path_suffix, const f_string_length_t path_prefix_length, const f_string_length_t path_suffix_length, f_string_dynamic_t *path_file, f_string_dynamic_t *buffer) {
+  f_return_status controller_file_load(const controller_data_t data, const controller_setting_t setting, const f_string_t path_prefix, const f_string_static_t path_name, const f_string_t path_suffix, const f_string_length_t path_prefix_length, const f_string_length_t path_suffix_length, controller_cache_t *cache) {
     f_status_t status = F_none;
     f_file_t file = f_file_t_initialize;
 
-    status = fl_string_append(path_prefix, path_prefix_length, path_file);
+    cache->name_file.used = 0;
+    cache->buffer_file.used = 0;
+
+    f_macro_time_spec_t_clear(cache->timestamp);
+
+    status = fl_string_append(path_prefix, path_prefix_length, &cache->name_file);
 
     if (F_status_is_error_not(status)) {
-      status = fl_string_append(f_path_separator, f_path_separator_length, path_file);
+      status = fl_string_append(f_path_separator, f_path_separator_length, &cache->name_file);
     }
 
     if (F_status_is_error(status)) {
@@ -94,17 +99,17 @@ extern "C" {
       return status;
     }
 
-    status = fl_string_dynamic_append(path_name, path_file);
+    status = fl_string_dynamic_append(path_name, &cache->name_file);
 
     if (F_status_is_error(status)) {
       fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_append", F_true);
       return status;
     }
 
-    status = fl_string_append(f_path_extension_separator, f_path_extension_separator_length, path_file);
+    status = fl_string_append(f_path_extension_separator, f_path_extension_separator_length, &cache->name_file);
 
     if (F_status_is_error_not(status)) {
-      status = fl_string_append(path_suffix, path_suffix_length, path_file);
+      status = fl_string_append(path_suffix, path_suffix_length, &cache->name_file);
     }
 
     if (F_status_is_error(status)) {
@@ -112,19 +117,19 @@ extern "C" {
       return status;
     }
 
-    status = fl_string_dynamic_terminate_after(path_file);
+    status = fl_string_dynamic_terminate_after(&cache->name_file);
 
     if (F_status_is_error(status)) {
       fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_terminate_after", F_true);
       return status;
     }
 
-    const f_string_length_t path_length = setting.path_setting.used ? setting.path_setting.used + f_path_separator_length + path_file->used : path_file->used;
+    const f_string_length_t path_length = setting.path_setting.used ? setting.path_setting.used + f_path_separator_length + cache->name_file.used : cache->name_file.used;
     char path[path_length + 1];
 
     if (setting.path_setting.used) {
       memcpy(path, setting.path_setting.string, setting.path_setting.used);
-      memcpy(path + setting.path_setting.used + f_path_separator_length, path_file->string, path_file->used);
+      memcpy(path + setting.path_setting.used + f_path_separator_length, cache->name_file.string, cache->name_file.used);
 
       path[setting.path_setting.used] = f_path_separator[0];
     }
@@ -137,7 +142,7 @@ extern "C" {
       fll_error_file_print(data.error, F_status_set_fine(status), "f_file_stream_open", F_true, path, "open", fll_error_file_type_file);
     }
     else {
-      status = f_file_stream_read(file, 1, buffer);
+      status = f_file_stream_read(file, 1, &cache->buffer_file);
 
       if (F_status_is_error(status)) {
         fll_error_file_print(data.error, F_status_set_fine(status), "f_file_stream_read", F_true, path, "read", fll_error_file_type_file);
@@ -146,6 +151,20 @@ extern "C" {
 
     f_file_stream_close(F_true, &file);
 
+    if (F_status_is_error_not(status)) {
+      struct stat stat_file;
+
+      status = f_file_stat(path, F_true, &stat_file);
+
+      if (F_status_is_error(status)) {
+        fll_error_file_print(data.error, F_status_set_fine(status), "f_file_stat", F_true, path, "stat", fll_error_file_type_file);
+      }
+      else {
+        cache->timestamp.seconds = stat_file.st_ctim.tv_sec;
+        cache->timestamp.nanoseconds = stat_file.st_ctim.tv_nsec;
+      }
+    }
+
     if (F_status_is_error(status)) return status;
 
     return F_none;
@@ -493,6 +512,7 @@ extern "C" {
     f_array_length_t i = 0;
     f_array_length_t j = 0;
 
+    f_array_length_t at = 0;
     f_array_length_t at_i = 0;
     f_array_length_t at_j = 1;
 
@@ -616,56 +636,81 @@ 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) {
 
-          // rule execution will re-use the existing cache, so save the current cache.
-          const f_array_length_t cache_line_action = cache->line_action;
-          const f_array_length_t cache_line_item = cache->line_item;
+          status = controller_rules_increase_by(controller_default_allocation_step, &setting->rules);
 
-          const f_string_length_t cache_name_action_used = cache->name_action.used;
-          const f_string_length_t cache_name_item_used = cache->name_item.used;
+          if (F_status_is_error(status)) {
+            fll_error_print(data.error, F_status_set_fine(status), "controller_rules_increase_by", F_true);
+            controller_entry_error_print(data.error, *cache);
 
-          char cache_name_item[cache_name_action_used];
-          char cache_name_action[cache_name_item_used];
+            return status;
+          }
+          else {
 
-          memcpy(cache_name_item, cache->name_item.string, cache->name_item.used);
-          memcpy(cache_name_action, cache->name_action.string, cache->name_action.used);
+            // rule execution will re-use the existing cache, so save the current cache.
+            const f_array_length_t cache_line_action = cache->line_action;
+            const f_array_length_t cache_line_item = cache->line_item;
 
-          const f_string_length_t rule_id_length = actions->array[cache->ats.array[at_j]].parameters.array[0].used + actions->array[cache->ats.array[at_j]].parameters.array[1].used + 1;
-          char rule_id_name[rule_id_length + 1];
-          const f_string_static_t rule_id = f_macro_string_static_t_initialize(rule_id_name, rule_id_length);
+            const f_string_length_t cache_name_action_used = cache->name_action.used;
+            const f_string_length_t cache_name_item_used = cache->name_item.used;
 
-          memcpy(rule_id_name, actions->array[cache->ats.array[at_j]].parameters.array[0].string, actions->array[cache->ats.array[at_j]].parameters.array[0].used);
-          memcpy(rule_id_name + actions->array[cache->ats.array[at_j]].parameters.array[0].used + 1, actions->array[cache->ats.array[at_j]].parameters.array[1].string, actions->array[cache->ats.array[at_j]].parameters.array[1].used);
+            char cache_name_item[cache_name_action_used];
+            char cache_name_action[cache_name_item_used];
 
-          rule_id_name[actions->array[cache->ats.array[at_j]].parameters.array[0].used] = f_path_separator[0];
-          rule_id_name[rule_id_length] = 0;
+            memcpy(cache_name_item, cache->name_item.string, cache->name_item.used);
+            memcpy(cache_name_action, cache->name_action.string, cache->name_action.used);
 
-          // @todo check if the rule is already loaded by using the "rule_id", if not then load it.
+            const f_string_length_t rule_id_length = actions->array[cache->ats.array[at_j]].parameters.array[0].used + actions->array[cache->ats.array[at_j]].parameters.array[1].used + 1;
+            char rule_id_name[rule_id_length + 1];
+            const f_string_static_t rule_id = f_macro_string_static_t_initialize(rule_id_name, rule_id_length);
 
-          //status = controller_rule_read(data, *setting, rule_id, cache, &setting->rules.array[setting->rules.used]);
+            memcpy(rule_id_name, actions->array[cache->ats.array[at_j]].parameters.array[0].string, actions->array[cache->ats.array[at_j]].parameters.array[0].used);
+            memcpy(rule_id_name + actions->array[cache->ats.array[at_j]].parameters.array[0].used + 1, actions->array[cache->ats.array[at_j]].parameters.array[1].string, actions->array[cache->ats.array[at_j]].parameters.array[1].used);
 
-          // @todo execute rule.
-          if (F_status_is_error_not(status) && actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_rule) {
-            //setting->rules.used++;
-            //status = controller_rule_process();
-          }
+            rule_id_name[actions->array[cache->ats.array[at_j]].parameters.array[0].used] = f_path_separator[0];
+            rule_id_name[rule_id_length] = 0;
 
-          // restore cache.
-          memcpy(cache->name_action.string, cache_name_action, cache_name_action_used);
-          memcpy(cache->name_item.string, cache_name_item, cache_name_item_used);
+            at = controller_rule_find_loaded(data, *setting, rule_id);
 
-          cache->name_action.string[cache_name_action_used] = 0;
-          cache->name_item.string[cache_name_item_used] = 0;
+            if (at == setting->rules.used) {
+              status = controller_rule_read(data, *setting, rule_id, cache, &setting->rules.array[setting->rules.used]);
 
-          cache->name_action.used = cache_name_action_used;
-          cache->name_item.used = cache_name_item_used;
+              if (F_status_is_error(status)) {
+                controller_entry_error_print(data.error, *cache);
 
-          cache->line_action = cache_line_action;
-          cache->line_item = cache_line_item;
+                if (!simulate) break;
+              }
+              else {
+                setting->rules.used++;
+              }
+            }
 
-          if (F_status_is_error(status)) {
-            controller_entry_error_print(data.error, *cache);
+            if (F_status_is_error_not(status) && actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_rule) {
+              if (similate) {
+                // @todo print message about how this would execute the rule.
+              }
+              else {
+                //status = controller_rule_process();
+              }
+            }
+
+            // restore cache.
+            memcpy(cache->name_action.string, cache_name_action, cache_name_action_used);
+            memcpy(cache->name_item.string, cache_name_item, cache_name_item_used);
+
+            cache->name_action.string[cache_name_action_used] = 0;
+            cache->name_item.string[cache_name_item_used] = 0;
+
+            cache->name_action.used = cache_name_action_used;
+            cache->name_item.used = cache_name_item_used;
 
-            if (!simulate) break;
+            cache->line_action = cache_line_action;
+            cache->line_item = cache_line_item;
+
+            if (F_status_is_error(status)) {
+              controller_entry_error_print(data.error, *cache);
+
+              if (!simulate) break;
+            }
           }
         }
         else if (actions->array[cache->ats.array[at_j]].type == controller_entry_action_type_timeout) {
index e7058c0489c4fd96b622a7173e58ad526ef60e43..9467033d3089aa724c17cba653c85c0c2512d7a8 100644 (file)
@@ -87,10 +87,11 @@ extern "C" {
  *   The length of the prefix path.
  * @param path_suffix_length
  *   The length of the suffix path.
- * @param path_file
- *   This is updated with a partial path to the given file.
- * @param buffer
- *   The buffer to load the file into.
+ * @param cache
+ *   The following within the cache is updated:
+ *   - name_file: The partial path of the file is inserted.
+ *   - buffer_file: The contents of the file is inserted.
+ *   - timestamp: This is updated to reflect the last changed timestamp.
  *
  * @return
  *   F_none on success.
@@ -102,7 +103,7 @@ extern "C" {
  * @see f_file_stream_read()
  */
 #ifndef _di_controller_file_load_
-  extern f_return_status controller_file_load(const controller_data_t data, const controller_setting_t setting, const f_string_t path_prefix, const f_string_static_t path_name, const f_string_t path_suffix, const f_string_length_t path_prefix_length, const f_string_length_t path_suffix_length, f_string_dynamic_t *path_file, f_string_dynamic_t *buffer) f_gcc_attribute_visibility_internal;
+  extern f_return_status controller_file_load(const controller_data_t data, const controller_setting_t setting, const f_string_t path_prefix, const f_string_static_t path_name, const f_string_t path_suffix, const f_string_length_t path_prefix_length, const f_string_length_t path_suffix_length, controller_cache_t *cache) f_gcc_attribute_visibility_internal;
 #endif // _di_controller_file_load_
 
 /**
index 79a9b51ebe4dd13f8125bd0ea84ef961fb9c6497..4d124ae5fd787df6db010168902d1bcebebf8f97 100644 (file)
@@ -545,6 +545,8 @@ extern "C" {
     cache->line_action = 0;
     cache->line_item = 0;
 
+    f_macro_time_spec_t_clear(cache->timestamp);
+
     cache->comments.used = 0;
     cache->delimits.used = 0;
 
@@ -562,7 +564,7 @@ extern "C" {
     cache->name_action.used = 0;
     cache->name_item.used = 0;
 
-    status = controller_file_load(data, setting, controller_string_entries, entry_name, controller_string_entry, controller_string_entries_length, controller_string_entry_length, &cache->name_file, &cache->buffer_file);
+    status = controller_file_load(data, setting, controller_string_entries, entry_name, controller_string_entry, controller_string_entries_length, controller_string_entry_length, cache);
 
     if (F_status_is_error_not(status)) {
       if (cache->buffer_file.used) {
index 52e16e6af1d7ca2a09bc849ee2986b8011afcddc..9b595d320d4291d7034d47421a5287e7091bada0 100644 (file)
@@ -268,6 +268,21 @@ extern "C" {
   }
 #endif // _di_controller_rule_error_print_
 
+#ifndef _di_controller_rule_find_loaded_
+  f_array_length_t controller_rule_find_loaded(const controller_data_t data, const controller_setting_t setting, const f_string_static_t rule_id) {
+    f_array_length_t i = 0;
+
+    for (; i < setting.rules.used; ++i) {
+
+      if (fl_string_dynamic_compare(setting.rules.array[i], rule_id) == F_equal_to) {
+        return i;
+      }
+    } // for
+
+    return i;
+  }
+#endif // _di_controller_rule_find_loaded_
+
 #ifndef _di_controller_rule_item_read_
   f_return_status controller_rule_item_read(const controller_data_t data, controller_cache_t *cache, controller_rule_item_t *item) {
     f_status_t status = F_none;
@@ -446,6 +461,8 @@ extern "C" {
 
     rule->status = F_known_not;
 
+    f_macro_time_spec_t_clear(rule->timestamp);
+
     rule->id.used = 0;
     rule->name.used = 0;
 
@@ -486,22 +503,26 @@ extern "C" {
       fll_error_print(data.error, F_status_set_fine(status), "fl_string_dynamic_append_nulless", F_true);
     }
     else {
-      status = controller_file_load(data, setting, controller_string_rules, rule->id, controller_string_rule, controller_string_rules_length, controller_string_rule_length, &cache->name_file, &cache->buffer_file);
+      status = controller_file_load(data, setting, controller_string_rules, rule->id, controller_string_rule, controller_string_rules_length, controller_string_rule_length, cache);
     }
 
-    if (F_status_is_error_not(status) && cache->buffer_file.used) {
-      f_string_range_t range = f_macro_string_range_t_initialize(cache->buffer_file.used);
+    if (F_status_is_error_not(status)) {
+      rule->timestamp = cache->timestamp;
 
-      status = fll_fss_basic_list_read(cache->buffer_file, &range, &cache->object_items, &cache->content_items, &cache->delimits, 0, &cache->comments);
+      if (cache->buffer_file.used) {
+        f_string_range_t range = f_macro_string_range_t_initialize(cache->buffer_file.used);
 
-      if (F_status_is_error(status)) {
-        fll_error_print(data.error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true);
-      }
-      else {
-        status = fl_fss_apply_delimit(cache->delimits, &cache->buffer_file);
+        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(data.error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true);
+          fll_error_print(data.error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true);
+        }
+        else {
+          status = fl_fss_apply_delimit(cache->delimits, &cache->buffer_file);
+
+          if (F_status_is_error(status)) {
+            fll_error_print(data.error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true);
+          }
         }
       }
     }
@@ -1174,6 +1195,27 @@ extern "C" {
   }
 #endif // _di_controller_rule_setting_read_
 
+#ifndef _di_controller_rules_increase_by_
+  f_return_status controller_rules_increase_by(const f_array_length_t amount, 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);
+      }
+
+      const f_status_t status = f_memory_resize((void **) & rules->array, sizeof(controller_rule_t), rules->size, rules->used + amount);
+
+      if (F_status_is_error_not(status)) {
+        rules->size = rules->used + amount;
+      }
+
+      return status;
+    }
+
+    return F_none;
+  }
+#endif // _di_controller_rule_increase_by_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif
index a6ad8b3deb891eef8c4bc44975ad0d8e623d3842..71b2ede1fab1db1fe023443a20547fb680936774 100644 (file)
@@ -119,6 +119,26 @@ extern "C" {
 #endif // _di_controller_rule_error_print_
 
 /**
+ * Search the already loaded rules to see if one is found.
+ *
+ * @param data
+ *   The program data.
+ * @param setting
+ *   The controller settings data.
+ * @param rule_id
+ *   The string identifying the rule.
+ *   This is constructed from the path parts to the file without the file extension and without the settings directory prefix.
+ *   "/etc/controller/rules/example/my.rule" would have a rule id of "example/my".
+ *
+ * @return
+ *   If found, a valid location within the setting.rules array.
+ *   If not found, then setting.rules.used is returned.
+ */
+#ifndef _di_controller_rule_find_loaded_
+  extern f_array_length_t controller_rule_find_loaded(const controller_data_t data, const controller_setting_t setting, const f_string_static_t rule_id) f_gcc_attribute_visibility_internal;
+#endif // _di_controller_rule_find_loaded_
+
+/**
  * Read the content within the buffer, extracting all valid items after determining their type for some rule file.
  *
  * This will perform additional FSS read functions as appropriate.
@@ -241,6 +261,28 @@ extern "C" {
   extern f_return_status controller_rule_setting_read(const controller_data_t data, controller_cache_t *cache, controller_rule_t *rule) f_gcc_attribute_visibility_internal;
 #endif // _di_controller_rule_setting_read_
 
+/**
+ * Increase the size of the rules array by the specified amount, 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.
+ *
+ * @return
+ *   F_none on success.
+ *   F_array_too_large (with error bit) if the resulting new size is bigger than the max array length.
+ *
+ *   Errors (with error bit) from: f_memory_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_
+
 #ifdef __cplusplus
 } // extern "C"
 #endif