Use "copy" instead of "clone", it seems more accurate given that the code is not guaranteeing the same exact memory structure (only the data is guaranteed).
I believe that I need to document my "completeness principle", documenting the structures and what needs to be done.
I also need to document the exception cases.
Implementing the rule copy function, I realized that I need to have the copy function and not just utilize the "append" functions.
There are many functions where "append" does not make sense.
This means that "copy" must be part of the completeness.
Comment out the cache clearing code.
I will probably get to that part last.
}
#endif // _di_f_capability_clear_flag_
- #ifndef _di_f_capability_clone_
- f_status_t f_capability_clone(const f_capability_t source, f_capability_t *destination) {
+ #ifndef _di_f_capability_copy_
+ f_status_t f_capability_copy(const f_capability_t source, f_capability_t *destination) {
#ifndef _di_level_0_parameter_checking_
if (!destination) return F_status_set_error(F_parameter);
#endif // _di_level_0_parameter_checking_
return F_status_set_error(F_implemented_not);
}
- #endif // _di_f_capability_clone_
+ #endif // _di_f_capability_copy_
#ifndef _di_f_capability_compare_
f_status_t f_capability_compare(const f_capability_t capability1, const f_capability_t capability2, int *flags) {
}
#endif // _di_f_capability_clear_flag_
- #ifndef _di_f_capability_clone_
- f_status_t f_capability_clone(const f_capability_t source, f_capability_t *destination) {
+ #ifndef _di_f_capability_copy_
+ f_status_t f_capability_copy(const f_capability_t source, f_capability_t *destination) {
#ifndef _di_level_0_parameter_checking_
if (!destination) return F_status_set_error(F_parameter);
#endif // _di_level_0_parameter_checking_
return F_status_set_error(F_failure);
}
- #endif // _di_f_capability_clone_
+ #endif // _di_f_capability_copy_
#ifndef _di_f_capability_compare_
f_status_t f_capability_compare(const f_capability_t capability1, const f_capability_t capability2, int *flags) {
#endif // _di_f_capability_clear_flag_
/**
- * Clone (copy) the capability structure.
+ * Copy the capability structure.
*
* @param source
- * The capability to clone.
+ * The capability to copy from.
* @param destination
* The capability to copy to.
* This must be freed via f_capability_delete() when finished with.
*
* @see cap_dup()
*/
-#ifndef _di_f_capability_clone_
- extern f_status_t f_capability_clone(const f_capability_t source, f_capability_t *destination);
-#endif // _di_f_capability_clone_
+#ifndef _di_f_capability_copy_
+ extern f_status_t f_capability_copy(const f_capability_t source, f_capability_t *destination);
+#endif // _di_f_capability_copy_
/**
* Compare two capability structures.
extern "C" {
#endif
+#ifndef _di_f_control_group_copy_
+ f_status_t f_control_group_copy(const f_control_group_t source, f_control_group_t *destination) {
+ #ifndef _di_level_0_parameter_checking_
+ if (!destination) return F_status_set_error(F_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ destination->as_new = source.as_new;
+ destination->path.used = 0;
+ destination->groups.used = 0;
+
+ f_status_t status = F_none;
+
+ if (source.path.used) {
+ status = f_string_dynamic_append(source.path, &destination->path);
+ if (F_status_is_error(status)) return status;
+ }
+
+ if (source.groups.used) {
+ status = f_string_dynamics_append(source.groups, &destination->groups);
+ if (F_status_is_error(status)) return status;
+ }
+
+ return F_none;
+ }
+#endif // _di_f_control_group_copy_
+
#ifdef __cplusplus
} // extern "C"
#endif
extern "C" {
#endif
+/**
+ * Copy the source control group onto the destination control group.
+ *
+ * @param source
+ * The source to append.
+ * @param destination
+ * The destination the source is appended onto.
+ *
+ * @return
+ * F_none on success.
+ *
+ * F_parameter (with error bit) if a parameter is invalid.
+ *
+ * Errors (with error bit) from: f_string_dynamic_append().
+ * Errors (with error bit) from: f_string_dynamics_append().
+ *
+ * @see f_string_dynamic_append()
+ * @see f_string_dynamics_append()
+ */
+#ifndef _di_f_control_group_copy_
+ extern f_status_t f_control_group_copy(const f_control_group_t source, f_control_group_t *destination);
+#endif // _di_f_control_group_copy_
+
#ifdef __cplusplus
} // extern "C"
#endif
}
#endif // _di_f_limit_process_
+#ifndef _di_f_limit_sets_copy_
+ f_status_t f_limit_sets_copy(const f_limit_sets_t source, f_limit_sets_t *destination) {
+ #ifndef _di_level_0_parameter_checking_
+ if (!destination) return F_status_set_error(F_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ destination->used = 0;
+
+ if (source.used > destination->size) {
+ f_status_t status = F_none;
+
+ f_macro_memory_structure_resize(status, (*destination), f_limit_set_t, source.used)
+ if (F_status_is_error(status)) return status;
+ }
+
+ for (f_array_length_t i = 0; i < source.used; ++i) {
+ destination->array[i].type = source.array[i].type;
+ destination->array[i].value = source.array[i].value;
+ } // for
+
+ return F_none;
+ }
+#endif // _di_f_limit_sets_copy_
+
+#ifndef _di_f_limit_values_copy_
+ f_status_t f_limit_values_copy(const f_limit_values_t source, f_limit_values_t *destination) {
+ #ifndef _di_level_0_parameter_checking_
+ if (!destination) return F_status_set_error(F_parameter);
+ #endif // _di_level_0_parameter_checking_
+
+ destination->used = 0;
+
+ if (source.used > destination->size) {
+ f_status_t status = F_none;
+
+ f_macro_memory_structure_resize(status, (*destination), f_limit_value_t, source.used)
+ if (F_status_is_error(status)) return status;
+ }
+
+ for (f_array_length_t i = 0; i < source.used; ++i) {
+ destination->array[i].rlim_cur = source.array[i].rlim_cur;
+ destination->array[i].rlim_max = source.array[i].rlim_max;
+ } // for
+
+ return F_none;
+ }
+#endif // _di_f_limit_values_copy_
+
#ifdef __cplusplus
} // extern "C"
#endif
extern f_status_t f_limit_process(const pid_t id, const int type, const f_limit_value_t *value_next, f_limit_value_t *value_current);
#endif // _di_f_limit_process_
+/**
+ * Copy the source limit sets onto the destination limit sets.
+ *
+ * @param source
+ * The source to append.
+ * @param destination
+ * The destination the source is appended onto.
+ *
+ * @return
+ * F_none on success.
+ *
+ * F_parameter (with error bit) if a parameter is invalid.
+ *
+ * Errors (with error bit) from: f_memory_structure_increase_by().
+ *
+ * @see f_memory_structure_increase_by()
+ */
+#ifndef _di_f_limit_sets_copy_
+ extern f_status_t f_limit_sets_copy(const f_limit_sets_t source, f_limit_sets_t *destination);
+#endif // _di_f_limit_sets_copy_
+
+/**
+ * Copy the source limit values onto the destination limit values.
+ *
+ * @param source
+ * The source to append.
+ * @param destination
+ * The destination the source is appended onto.
+ *
+ * @return
+ * F_none on success.
+ *
+ * F_parameter (with error bit) if a parameter is invalid.
+ *
+ * Errors (with error bit) from: f_memory_structure_increase_by().
+ *
+ * @see f_memory_structure_increase_by()
+ */
+#ifndef _di_f_limit_values_copy_
+ extern f_status_t f_limit_values_copy(const f_limit_values_t source, f_limit_values_t *destination);
+#endif // _di_f_limit_values_copy_
+
#ifdef __cplusplus
} // extern "C"
#endif
}
#endif // _di_controller_validate_has_graph_
-controller_processs_t
-
#ifdef __cplusplus
} // extern "C"
#endif
fprintf(thread_data.data->warning.to.stream, "%s", thread_data.data->warning.notable.after->string);
fprintf(thread_data.data->warning.to.stream, "%s'.%s%c", thread_data.data->warning.context.before->string, thread_data.data->warning.context.after->string, f_string_eol_s[0]);
- controller_entry_error_print(thread_data.data->warning, cache->action);
+ controller_entry_error_print_cache(thread_data.data->warning, cache->action);
}
continue;
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)) {
- controller_error_print(thread_data.data->error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true, thread_data);
+ controller_error_print(thread_data.data->error, F_status_set_fine(status), "fll_fss_basic_list_read", F_true, thread_data.thread);
}
else {
status = fl_fss_apply_delimit(cache->delimits, &cache->buffer_file);
if (F_status_is_error(status)) {
- controller_error_print(thread_data.data->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true, thread_data);
+ controller_error_print(thread_data.data->error, F_status_set_fine(status), "fl_fss_apply_delimit", F_true, thread_data.thread);
}
}
}
else {
if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&thread_data.thread->lock.print);
fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]);
fprintf(thread_data.data->error.to.stream, "%s%sThe entry file is empty.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s, thread_data.data->error.context.after->string, f_string_eol_s[0]);
- f_thread_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
status = F_status_set_error(F_data_not);
if (fl_string_dynamic_compare(thread_data.setting->entry.items.array[j].name, cache->action.name_item) == F_equal_to) {
if (thread_data.data->warning.verbosity == f_console_verbosity_debug) {
- f_thread_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&thread_data.thread->lock.print);
fprintf(thread_data.data->warning.to.stream, "%c", f_string_eol_s[0]);
fprintf(thread_data.data->warning.to.stream, "%s%sIgnoring duplicate entry item '", thread_data.data->warning.context.before->string, thread_data.data->warning.prefix ? thread_data.data->warning.prefix : f_string_empty_s);
controller_entry_error_print_cache(thread_data.data->warning, cache->action);
- f_thread_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
code |= 0x2;
status = controller_string_dynamic_append_terminated(cache->action.name_item, &thread_data.setting->entry.items.array[at].name);
if (F_status_is_error(status)) {
- controller_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, thread_data);
+ controller_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, thread_data.thread);
break;
}
status = controller_entry_actions_read(*range, thread_data, cache, &thread_data.setting->entry.items.array[at].actions);
if (F_status_is_error(status)) {
- f_thread_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&thread_data.thread->lock.print);
controller_entry_error_print_cache(thread_data.data->error, cache->action);
- f_thread_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
if (F_status_set_fine(status) == F_memory_not) {
break;
if (!(code & 0x1)) {
if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&thread_data.thread->lock.print);
fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]);
fprintf(thread_data.data->error.to.stream, "%s%sThe required entry item '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s);
fprintf(thread_data.data->error.to.stream, "%s%s%s%s", thread_data.data->error.context.after->string, thread_data.data->error.notable.before->string, controller_string_main_s, thread_data.data->error.notable.after->string);
fprintf(thread_data.data->error.to.stream, "%s' was not found.%s%c", thread_data.data->error.context.before->string, thread_data.data->error.context.after->string, f_string_eol_s[0]);
- f_thread_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
status = F_status_set_error(F_found_not);
status = controller_string_dynamic_append_terminated(thread_data.setting->entry.items.array[i].name, &cache->action.name_item);
if (F_status_is_error(status)) {
- controller_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, thread_data);
+ controller_error_print(thread_data.data->error, F_status_set_fine(status), "controller_string_dynamic_append_terminated", F_true, thread_data.thread);
break;
}
if (thread_data.data->error.verbosity != f_console_verbosity_quiet) {
- f_thread_lock(&thread_data.thread->lock.print);
+ f_thread_mutex_lock(&thread_data.thread->lock.print);
fprintf(thread_data.data->error.to.stream, "%c", f_string_eol_s[0]);
fprintf(thread_data.data->error.to.stream, "%s%sThe required entry item '", thread_data.data->error.context.before->string, thread_data.data->error.prefix ? thread_data.data->error.prefix : f_string_empty_s);
controller_entry_error_print_cache(thread_data.data->error, cache->action);
- f_thread_unlock(&thread_data.thread->lock.print);
+ f_thread_mutex_unlock(&thread_data.thread->lock.print);
}
action->number = 0;
}
if (F_status_is_error(status)) {
- controller_entry_error_print(thread_data.data->error, cache->action);
+ controller_entry_error_print_cache(thread_data.data->error, cache->action);
thread_data.setting->entry.status = controller_status_simplify(F_status_set_fine(status));
}
destination->user = source.user;
destination->group = source.group;
- destination->timestamp.seconds = source.seconds;
- destination->timestamp.nanoseconds = source.nanoseconds;
+ destination->timestamp.seconds = source.timestamp.seconds;
+ destination->timestamp.nanoseconds = source.timestamp.nanoseconds;
- destination->path_control.used = 0;
+ destination->id.used = 0;
destination->name.used = 0;
destination->path.used = 0;
destination->script.used = 0;
destination->wish.used = 0;
destination->affinity.used = 0;
- destination->capability.used = 0;
- destination->control_group.used = 0;
destination->groups.used = 0;
destination->limits.used = 0;
- destination->scheduler.used = 0;
+ destination->scheduler.policy = source.scheduler.policy;
+ destination->scheduler.priority = source.scheduler.priority;
destination->items.used = 0;
if (source.id.used) {
-
- status = f_string_dynamic_append(source.id, &dynamic->id);
+ status = f_string_dynamic_append(source.id, &destination->id);
if (F_status_is_error(status)) return status;
}
if (source.name.used) {
-
- status = f_string_dynamic_append(source.name, &dynamic->name);
+ status = f_string_dynamic_append(source.name, &destination->name);
if (F_status_is_error(status)) return status;
}
if (source.path.used) {
-
- status = f_string_dynamic_append(source.path, &dynamic->path);
+ status = f_string_dynamic_append(source.path, &destination->path);
if (F_status_is_error(status)) return status;
}
if (source.script.used) {
-
- status = f_string_dynamic_append(source.script, &dynamic->script);
+ status = f_string_dynamic_append(source.script, &destination->script);
if (F_status_is_error(status)) return status;
}
if (source.define.used) {
status = f_string_maps_append(source.define, &destination->define);
+ if (F_status_is_error(status)) return status;
}
if (source.parameter.used) {
status = f_string_maps_append(source.parameter, &destination->parameter);
+ if (F_status_is_error(status)) return status;
}
if (source.environment.used) {
status = f_string_dynamics_append(source.environment, &destination->environment);
+ if (F_status_is_error(status)) return status;
}
if (source.need.used) {
status = f_string_dynamics_append(source.need, &destination->need);
+ if (F_status_is_error(status)) return status;
}
if (source.want.used) {
status = f_string_dynamics_append(source.want, &destination->want);
+ if (F_status_is_error(status)) return status;
}
if (source.wish.used) {
status = f_string_dynamics_append(source.wish, &destination->wish);
+ if (F_status_is_error(status)) return status;
}
if (source.affinity.used) {
- status = f_int32s_append(source.affinity, &destination->affinity);
+ status = f_type_int32s_append(source.affinity, &destination->affinity);
+ if (F_status_is_error(status)) return status;
}
- if (source.capability.used) {
- // @todo copy capability
- }
+ status = f_capability_copy(source.capability, &destination->capability);
+ if (F_status_is_error(status)) return status;
- if (source.control_group.used) {
- // @todo copy control_group
- }
+ status = f_control_group_copy(source.control_group, &destination->control_group);
+ if (F_status_is_error(status)) return status;
if (source.groups.used) {
- status = f_int32s_append(source.groups, &destination->groups);
+ status = f_type_int32s_append(source.groups, &destination->groups);
+ if (F_status_is_error(status)) return status;
}
if (source.limits.used) {
- status = f_limit_sets_append(source.limits, &destination->limits);
- }
-
- if (source.scheduler.used) {
- // @todo copy scheduler
+ status = f_limit_sets_copy(source.limits, &destination->limits);
+ if (F_status_is_error(status)) return status;
}
if (source.items.used) {
- // @todo copy items
+ controller_rule_item_t *item_source = 0;
+ controller_rule_item_t *item_destination = 0;
+
+ controller_rule_action_t *action_source = 0;
+ controller_rule_action_t *action_destination = 0;
+
+ if (source.items.used > destination->items.size) {
+ status = controller_rule_items_increase_by(source.items.used - destination->items.size, &destination->items);
+ if (F_status_is_error(status)) return status;
+ }
+
+ f_array_length_t i = 0;
+ f_array_length_t j = 0;
+
+ for (; i < source.items.used; ++i) {
+
+ item_source = &source.items.array[i];
+ item_destination = &destination->items.array[i];
+
+ if (item_source->actions.used > item_destination->actions.size) {
+ status = controller_rule_actions_increase_by(item_source->actions.used - item_destination->actions.size, &item_destination->actions);
+ if (F_status_is_error(status)) return status;
+ }
+
+ item_destination->type = item_source->type;
+ item_destination->line = item_source->line;
+
+ for (j = 0; j < item_source->actions.used; ++j) {
+
+ action_source = &item_source->actions.array[j];
+ action_destination = &item_destination->actions.array[j];
+
+ action_destination->type = action_source->type;
+ action_destination->line = action_source->line;
+ action_destination->status = action_source->status;
+
+ action_destination->parameters.used = 0;
+
+ status = f_string_dynamics_append(action_source->parameters, &action_destination->parameters);
+ if (F_status_is_error(status)) return status;
+ } // for
+
+ item_destination->actions.used = item_source->actions.used;
+ } // for
+
+ destination->items.used = source.items.used;
}
return status;
status = fll_control_group_prepare(rule->control_group);
if (F_status_is_error(status)) {
- controller_error_print_locked(thread_data.data->error, F_status_set_fine(status), "fll_control_group_prepare", F_true, thread_data.thread);
+ controller_error_print(thread_data.data->error, F_status_set_fine(status), "fll_control_group_prepare", F_true, thread_data.thread);
rule->status = F_status_set_error(F_failure);
return status;
status = fl_environment_load_names(rule->environment, &environment);
if (F_status_is_error(status)) {
- controller_error_print_locked(thread_data.data->error, F_status_set_fine(status), "fl_environment_load_names", F_true, thread_data.thread);
+ controller_error_print(thread_data.data->error, F_status_set_fine(status), "fl_environment_load_names", F_true, thread_data.thread);
rule->status = F_status_set_error(F_failure);
return status;
// @fixme the cache should probably store a rule type and then that can used instead of calling controller_rule_copy() here.
controller_rule_t rule = controller_rule_t_initialize;
- status = controller_rule_copy(&thread_data.setting->rules.array[index], &rule);
+ status = controller_rule_copy(thread_data.setting->rules.array[index], &rule);
if (F_status_is_error_not(status)) {
status = controller_rule_execute(action, options, thread_data, &cache, &rule);
* @return
* F_none on success.
*
- * Errors (with error bit) from: XXXX().
+ * Errors (with error bit) from: f_capability_copy().
+ * Errors (with error bit) from: f_control_group_copy().
+ * Errors (with error bit) from: f_limit_sets_copy().
+ * Errors (with error bit) from: f_string_dynamic_append().
+ * Errors (with error bit) from: f_string_dynamics_append().
+ * Errors (with error bit) from: f_string_maps_append().
+ * Errors (with error bit) from: f_type_int32s_append().
+ *
+ * @see f_capability_copy()
+ * @see f_control_group_copy()
+ * @see f_limit_sets_append()
+ * @see f_string_dynamic_append()
+ * @see f_string_dynamics_append()
+ * @see f_string_maps_append()
+ * @see f_type_int32s_append()
*/
#ifndef _di_controller_rule_copy_
- extern f_status_t controller_rule_copy(controller_rule_t *source, controller_rule_t *destination) f_gcc_attribute_visibility_internal;
+ extern f_status_t controller_rule_copy(const controller_rule_t source, controller_rule_t *destination) f_gcc_attribute_visibility_internal;
#endif // _di_controller_rule_copy_
/**
thread->asynchronouss.used = 0;
- f_thread_mutex_unlock(&thread->lock.asynchronous);
+ f_thread_unlock(&thread->lock.asynchronous);
}
#endif // _di_controller_thread_asynchronous_cancel_
for (; thread_data->thread->enabled; ) {
sleep(interval);
- if (f_thread_mutex_lock_try(&thread_data->thread->lock.asynchronous) == F_none) {
+ /*
+ if (f_thread_lock_write_try(&thread_data->thread->lock.asynchronous) == F_none) {
controller_thread_t *thread = &thread_data->thread;
if (thread->asynchronouss.used) {
if (!thread->enabled) break;
if (!thread->asynchronouss.array[i].state) continue;
- if (f_thread_mutex_lock_try(&thread->asynchronouss.array[i].lock) != F_none) continue;
+ if (f_thread_lock_write_try(&thread->asynchronouss.array[i].lock) != F_none) continue;
- if (f_thread_mutex_lock_try(&thread_data->setting->rules.array[thread->asynchronouss.array[i].index].lock) == F_none) {
+ if (f_thread_lock_write_try(&thread_data->setting->rules.array[thread->asynchronouss.array[i].index].lock) == F_none) {
if (thread->asynchronouss.array[i].state == controller_asynchronous_state_done) {
f_thread_join(thread->asynchronouss.array[i].id, 0);
thread->asynchronouss.array[i].state = 0;
}
else if (thread->asynchronouss.array[i].state) {
- f_thread_mutex_unlock(&thread->asynchronouss.array[i].lock);
+ f_thread_unlock(&thread->asynchronouss.array[i].lock);
break;
}
- f_thread_mutex_unlock(&thread->asynchronouss.array[i].lock);
+ f_thread_unlock(&thread->asynchronouss.array[i].lock);
} // for
}
controller_asynchronouss_resize(thread->asynchronouss.used, &thread->asynchronouss);
}
- f_thread_mutex_unlock(&thread->lock.asynchronous);
+ f_thread_unlock(&thread->lock.asynchronous);
}
+ */
} // for
return 0;
if (F_status_is_error(status)) {
if (data->error.verbosity != f_console_verbosity_quiet) {
- controller_error_print_locked(data->error, F_status_set_fine(status), "f_thread_create", F_true, &thread);
+ controller_error_print(data->error, F_status_set_fine(status), "f_thread_create", F_true, &thread);
}
}
}