From 86586109a71f0b61d1faa800935883f48da82651 Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 7 Dec 2020 22:02:23 -0600 Subject: [PATCH] Progress: controller program. --- level_3/controller/c/private-common.h | 7 ++ level_3/controller/c/private-controller.c | 135 ++++++++++++++------- level_3/controller/c/private-controller.h | 11 +- level_3/controller/c/private-entry.c | 4 +- level_3/controller/c/private-rule.c | 62 ++++++++-- level_3/controller/c/private-rule.h | 42 +++++++ .../data/settings/rules/task/{clock => clock.rule} | 0 .../rules/task/{keyboard => keyboard.rule} | 0 8 files changed, 200 insertions(+), 61 deletions(-) rename level_3/controller/data/settings/rules/task/{clock => clock.rule} (100%) rename level_3/controller/data/settings/rules/task/{keyboard => keyboard.rule} (100%) diff --git a/level_3/controller/c/private-common.h b/level_3/controller/c/private-common.h index 1e1875e..7e6e906 100644 --- a/level_3/controller/c/private-common.h +++ b/level_3/controller/c/private-common.h @@ -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, \ diff --git a/level_3/controller/c/private-controller.c b/level_3/controller/c/private-controller.c index 9a3da48..7b9c526 100644 --- a/level_3/controller/c/private-controller.c +++ b/level_3/controller/c/private-controller.c @@ -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) { diff --git a/level_3/controller/c/private-controller.h b/level_3/controller/c/private-controller.h index e7058c0..9467033 100644 --- a/level_3/controller/c/private-controller.h +++ b/level_3/controller/c/private-controller.h @@ -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_ /** diff --git a/level_3/controller/c/private-entry.c b/level_3/controller/c/private-entry.c index 79a9b51..4d124ae 100644 --- a/level_3/controller/c/private-entry.c +++ b/level_3/controller/c/private-entry.c @@ -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) { diff --git a/level_3/controller/c/private-rule.c b/level_3/controller/c/private-rule.c index 52e16e6..9b595d3 100644 --- a/level_3/controller/c/private-rule.c +++ b/level_3/controller/c/private-rule.c @@ -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 diff --git a/level_3/controller/c/private-rule.h b/level_3/controller/c/private-rule.h index a6ad8b3..71b2ede 100644 --- a/level_3/controller/c/private-rule.h +++ b/level_3/controller/c/private-rule.h @@ -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 diff --git a/level_3/controller/data/settings/rules/task/clock b/level_3/controller/data/settings/rules/task/clock.rule similarity index 100% rename from level_3/controller/data/settings/rules/task/clock rename to level_3/controller/data/settings/rules/task/clock.rule diff --git a/level_3/controller/data/settings/rules/task/keyboard b/level_3/controller/data/settings/rules/task/keyboard.rule similarity index 100% rename from level_3/controller/data/settings/rules/task/keyboard rename to level_3/controller/data/settings/rules/task/keyboard.rule -- 1.8.3.1