3 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * Licensed under the Apache License, Version 2.0 (the License);
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
21 #include "utility/fw_ref.h"
22 #include "utility/fw_assert.h"
23 #include "utility/sync_util.h"
24 #include "engine-controller/internal.h"
25 #include "engine-controller/task.h"
26 #include "engine-controller/task_spec_internal.h"
27 #include "engine-controller/param_spec_internal.h"
28 #include "engine-controller/param_value_internal.h"
30 #ifndef SYNC_AGENT_LOG
32 #define LOG_TAG "AF_EC"
35 static sync_agent_ec_param_param_s *_task_fetch_from_param(ec_task_t * parent_task, sync_agent_ec_int to_child_task_index, sync_agent_ec_int to_param_index);
36 static void _task_free_task(ec_task_t * task);
38 static sync_agent_ec_param_param_s *_task_fetch_from_param(ec_task_t * parent_task, sync_agent_ec_int to_child_task_index, sync_agent_ec_int to_param_index)
42 retvm_if(parent_task == NULL, NULL, "ec_task_t is NULL !!");
44 sync_agent_ec_param_param_s *fetched_param = NULL;
45 sync_agent_ec_task_spec_s *parent_task_spec = parent_task->task_spec;
46 ec_child_tasks_info_t *child_task_info = NULL;
47 if (ec_task_spec_is_container(parent_task_spec)) {
48 child_task_info = ec_task_spec_find_child_tasks_info(parent_task_spec);
49 } else if (ec_task_spec_is_dynamic_container(parent_task_spec)) {
50 child_task_info = ec_task_spec_find_case_specific_child_tasks_info(parent_task_spec, parent_task->dynamic_case);
55 ec_data_flow_edges_t *data_flow_edges;
57 if (child_task_info != NULL) {
58 data_flow_edges = child_task_info->data_flow_edges;
63 sync_agent_ec_int from_task_index = 0;
64 sync_agent_ec_int from_param_index = 0;
65 sync_agent_ec_boolean find_success = ec_data_flow_edges_get_from_param_info(data_flow_edges,
66 to_child_task_index, to_param_index,
67 &from_task_index, &from_param_index);
69 if (from_task_index == -1) {
70 /* get from parent_task */
71 fetched_param = parent_task->param_array[from_param_index];
73 /* validation from_task_index */
74 sync_agent_ec_error_e ec_error = SYNC_AGENT_EC_OK;
75 if (ec_task_spec_is_container(parent_task_spec)) {
76 ec_error = ec_task_spec_valididate_child_task_index(parent_task_spec, from_task_index);
77 } else if (ec_task_spec_is_dynamic_container(parent_task_spec)) {
78 ec_error = ec_task_spec_valididate_child_task_index_on_dynamic_case(parent_task->dynamic_case, parent_task_spec, from_task_index);
80 if (ec_error != SYNC_AGENT_EC_OK) {
84 /* get from child task */
85 ec_task_t *child_task = parent_task->child_task_array[from_task_index];
86 fetched_param = child_task->param_array[from_param_index];
98 /* TODO : handling error case */
99 GSList *ec_task_construct_progress_blocking_realized_entity_list(ec_task_info_t * task_info)
103 GSList *progress_blocking_realized_entity_list = NULL;
105 /* add progress blocking entity according to queuing rule */
107 ec_progress_blocking_entity_t *entity = NULL;
108 ec_progress_blocking_realized_entity_t *realized_entity = NULL;
109 for (iter = task_info->progress_blocking_entity_list; iter != NULL; iter = g_slist_next(iter)) {
110 entity = (ec_progress_blocking_entity_t *) (iter->data);
112 realized_entity = ec_progress_blocking_realized_entity_new(entity);
114 progress_blocking_realized_entity_list = g_slist_prepend(progress_blocking_realized_entity_list, realized_entity);
116 /* create progress_queuing_entity */
117 g_queue_push_tail(entity->queuing_rule_spec->progress_blocking_queue, realized_entity);
122 return progress_blocking_realized_entity_list;
125 /* TODO : handling error case */
126 GSList *ec_task_construct_current_node_in_progress_blocking_entity_list(ec_task_info_t * task_info)
130 GSList *current_node_in_progress_blocking_entity_list = NULL;
132 /* add progress blocking entity according to queuing rule */
134 ec_progress_blocking_entity_t *entity = NULL;
135 for (iter = task_info->progress_blocking_entity_list; iter != NULL; iter = g_slist_next(iter)) {
136 entity = (ec_progress_blocking_entity_t *) (iter->data);
138 current_node_in_progress_blocking_entity_list = g_slist_prepend(current_node_in_progress_blocking_entity_list, entity->element_set->n_ary_tree_with_flag);
143 return current_node_in_progress_blocking_entity_list;
146 GSList *ec_task_construct_current_node_in_progress_blocking_entity_list_from_parent_task(ec_task_t * parent_task, sync_agent_ec_int child_index)
150 GSList *current_node_in_progress_blocking_entity_list = NULL;
152 /* add progress blocking entity according to queuing rule */
154 ec_n_ary_tree_node_with_flag_t *parent_tree_node = NULL;
155 ec_n_ary_tree_node_with_flag_t *child_tree_node = NULL;
156 for (iter = parent_task->current_node_in_progress_blocking_entity_list; iter != NULL; iter = g_slist_next(iter)) {
157 parent_tree_node = (ec_n_ary_tree_node_with_flag_t *) (iter->data);
158 if (parent_tree_node == NULL) {
159 child_tree_node = NULL;
161 child_tree_node = ec_n_ary_tree_node_with_flag_get_child_node(parent_tree_node, ec_task_spec_is_dynamic_container(parent_task->task_spec), parent_task->dynamic_case, child_index);
162 /* note that child_tree_node could be NULL */
165 current_node_in_progress_blocking_entity_list = g_slist_prepend(current_node_in_progress_blocking_entity_list, child_tree_node);
170 return current_node_in_progress_blocking_entity_list;
173 ec_task_t *ec_task_alloc_root_task(sync_agent_ec_task_spec_s * task_spec, ec_request_msg_t * request_msg, ec_task_info_pool_t * task_info_pool)
177 ec_task_t *task = NULL;
178 sync_agent_ec_int i = 0;
179 sync_agent_ec_uint child_task_cnt = 0;
181 if (task_spec == NULL) {
182 _DEBUG_INFO("input task is NULL");
186 task = (ec_task_t *) calloc(1, sizeof(ec_task_t));
192 task->task_error = SYNC_AGENT_EC_TASK_ERROR_NOT_YET_RUN;
194 task->task_info = ec_task_info_pool_search_task_info(task_info_pool, request_msg->task_spec_id);
196 task->progress_blocking_realized_entity_list = ec_task_construct_progress_blocking_realized_entity_list(task->task_info);
198 task->current_node_in_progress_blocking_entity_list = ec_task_construct_current_node_in_progress_blocking_entity_list(task->task_info);
200 task->parent_task = NULL;
201 task->child_task_index_in_parent_task = 0; /* meaningless value */
203 task->param_array = (sync_agent_ec_param_param_s **) calloc(task_spec->task_param_cnt, sizeof(sync_agent_ec_param_param_s *));
204 if (task->param_array == NULL) {
208 /* set parameter values in param_array */
210 for (i = 0; i < request_msg->cnt_in_param; i++) {
211 index = request_msg->in_param_index_array[i];
212 task->param_array[index] = ec_alloc_param(1, 1, /* TODO : set ref count */
213 task_spec->task_param_spec_array[index], &(request_msg->in_param_value_array[i]));
216 /* set output parameter values */
217 for (i = 0; i < task_spec->task_param_cnt; i++) {
218 if (task->param_array[i] == NULL) {
219 task->param_array[i] = ec_alloc_param(1, 1, /* TODO : set ref count */
220 task_spec->task_param_spec_array[i], NULL);
224 if (ec_task_spec_is_container(task_spec)) {
225 child_task_cnt = ec_task_spec_get_child_task_cnt(task_spec);
226 } else if (ec_task_spec_is_dynamic_container(task_spec)) {
228 sync_agent_calculate_case_cb calculate_case_func = ec_task_spec_get_calculate_case_callback_func(task_spec);
229 if (calculate_case_func == NULL) {
230 _DEBUG_ERROR("sync_agent_calculate_case_cb is NULL !!");
234 task->dynamic_case = calculate_case_func(task_spec->task_param_cnt, task->param_array);
236 child_task_cnt = ec_task_spec_get_child_task_cnt_on_dynamic_case(task_spec, task->dynamic_case);
239 if (child_task_cnt > 0) {
240 task->child_task_array = (ec_task_t **) calloc(child_task_cnt, sizeof(ec_task_t *));
241 if (task->child_task_array == NULL) {
246 ec_task_set_left_child_to_run(task, child_task_cnt);
248 if (ec_task_spec_is_container(task_spec)) {
249 /* copy child_task_control_flow_in_degree */
250 task->current_child_task_control_flow_in_degree_array = ec_task_spec_duplicate_child_task_control_flow_in_degree(task_spec);
251 if (task->current_child_task_control_flow_in_degree_array == NULL) {
254 } else if (ec_task_spec_is_dynamic_container(task_spec)) {
255 task->current_child_task_control_flow_in_degree_array = ec_task_spec_duplicate_child_task_control_flow_in_degree_on_dynamic_case(task_spec, task->dynamic_case);
256 if (task->current_child_task_control_flow_in_degree_array == NULL) {
260 task->current_child_task_control_flow_in_degree_array = NULL;
263 task->task_spec = ec_task_spec_ref(task_spec);
264 sync_agent_util_ref_object_s *pRequest_Msg_ref = sync_agent_create_referenced_object(request_msg, NULL); /* TODO : free fucntion */
265 if (pRequest_Msg_ref == NULL) {
268 task->request_msg = pRequest_Msg_ref;
270 task->cancel_information = ec_task_cancel_info_init(pRequest_Msg_ref);
271 if (task->cancel_information == NULL) {
275 if (-1 == gettimeofday(&(task->create_time), NULL)) {
284 _task_free_task(task);
288 ec_task_t *ec_task_alloc_child_task(ec_task_t * parent_task, sync_agent_ec_int child_index)
292 retvm_if(parent_task == NULL, NULL, "ec_task_t is NULL !!");
294 ec_task_t *child_task = NULL;
295 sync_agent_ec_task_spec_s *parent_task_spec = parent_task->task_spec;
296 ec_child_tasks_info_t *child_tasks_info = NULL;
298 /* validation & get child_task_info */
299 if (ec_task_spec_is_container(parent_task_spec)) {
300 sync_agent_ec_error_e ec_error = ec_task_spec_valididate_child_task_index(parent_task_spec, child_index);
301 if (ec_error != SYNC_AGENT_EC_OK) {
302 _DEBUG_ERROR("invalid child index, child_index = %d\n", child_index);
306 child_tasks_info = ec_task_spec_find_child_tasks_info(parent_task_spec);
307 } else if (ec_task_spec_is_dynamic_container(parent_task_spec)) {
308 sync_agent_ec_error_e ec_error = ec_task_spec_valididate_child_task_index_on_dynamic_case(parent_task->dynamic_case, parent_task_spec, child_index);
309 if (ec_error != SYNC_AGENT_EC_OK) {
310 _DEBUG_ERROR("invalid child index, child_index = %d\n", child_index);
314 child_tasks_info = ec_task_spec_find_case_specific_child_tasks_info(parent_task_spec, parent_task->dynamic_case);
317 sync_agent_ec_task_spec_s *child_task_spec;
319 if (child_tasks_info != NULL) {
320 child_task_spec = child_tasks_info->child_task_array[child_index];
325 sync_agent_ec_int i = 0;
326 sync_agent_ec_uint grand_child_task_cnt = 0;
328 child_task = (ec_task_t *) calloc(1, sizeof(ec_task_t));
329 if (child_task == NULL) {
333 child_task->ref_count = 1;
334 child_task->task_error = SYNC_AGENT_EC_TASK_ERROR_NOT_YET_RUN;
335 child_task->parent_task = parent_task;
336 child_task->child_task_index_in_parent_task = child_index;
338 child_task->progress_blocking_realized_entity_list = parent_task->progress_blocking_realized_entity_list;
339 child_task->current_node_in_progress_blocking_entity_list = ec_task_construct_current_node_in_progress_blocking_entity_list_from_parent_task(parent_task, child_index);
341 child_task->param_array = (sync_agent_ec_param_param_s **) calloc(child_task_spec->task_param_cnt, sizeof(sync_agent_ec_param_param_s *));
342 if (child_task->param_array == NULL) {
346 /* set parameter values */
347 for (i = 0; i < child_task_spec->task_param_cnt; i++) {
348 sync_agent_ec_param_param_s *from_param = _task_fetch_from_param(parent_task, child_index, i);
349 child_task->param_array[i] = ec_alloc_param(1, 1, /* TODO : set ref count */
350 child_task_spec->task_param_spec_array[i], from_param != NULL ? &(from_param->param_value) : NULL);
353 if (ec_task_spec_is_container(child_task_spec)) {
354 grand_child_task_cnt = ec_task_spec_get_child_task_cnt(child_task_spec);
355 } else if (ec_task_spec_is_dynamic_container(child_task_spec)) {
356 /* compute dynamic case */
357 sync_agent_calculate_case_cb calculate_case_func = ec_task_spec_get_calculate_case_callback_func(child_task_spec);
358 if (calculate_case_func == NULL) {
359 _DEBUG_ERROR("sync_agent_calculate_case_cb is NULL !!");
362 child_task->dynamic_case = calculate_case_func(child_task_spec->task_param_cnt, child_task->param_array);
364 grand_child_task_cnt = ec_task_spec_get_child_task_cnt_on_dynamic_case(child_task_spec, child_task->dynamic_case);
366 child_task->child_task_array = (ec_task_t **) calloc(grand_child_task_cnt, sizeof(ec_task_t *));
367 if (child_task->child_task_array == NULL) {
371 ec_task_set_left_child_to_run(child_task, grand_child_task_cnt);
373 if (ec_task_spec_is_container(child_task_spec)) {
374 /* copy child_task_control_flow_in_degree */
375 child_task->current_child_task_control_flow_in_degree_array = ec_task_spec_duplicate_child_task_control_flow_in_degree(child_task_spec);
376 if (child_task->current_child_task_control_flow_in_degree_array == NULL) {
379 } else if (ec_task_spec_is_dynamic_container(child_task_spec)) {
380 child_task->current_child_task_control_flow_in_degree_array = ec_task_spec_duplicate_child_task_control_flow_in_degree_on_dynamic_case(child_task_spec, child_task->dynamic_case);
381 if (child_task->current_child_task_control_flow_in_degree_array == NULL) {
385 child_task->current_child_task_control_flow_in_degree_array = NULL;
388 child_task->task_info = ec_task_info_ref(parent_task->task_info);
389 child_task->task_spec = ec_task_spec_ref(child_task_spec);
390 child_task->request_msg = sync_agent_get_referenced_object(parent_task->request_msg);
391 child_task->cancel_information = ec_task_cancel_info_ref(parent_task->cancel_information);
393 if (-1 == gettimeofday(&(child_task->create_time), NULL)) {
403 if (child_task != NULL) {
404 _task_free_task(child_task);
409 static void _task_free_task(ec_task_t * task)
413 _DEBUG_TRACE("called\n");
417 ec_task_cancel_info_unref(task->cancel_information);
424 ec_task_t *ec_task_ref_task(ec_task_t * task)
428 SYNC_AGENT_UTIL_ASSERT_CONDITION(task != NULL, "error. task == NULL\n");
430 g_atomic_int_inc(&(task->ref_count));
437 void ec_task_unref_task(ec_task_t * task)
445 if (g_atomic_int_get(&(task->ref_count)) <= 0) {
446 _DEBUG_ERROR("ref count <= 0\n");
449 if (g_atomic_int_dec_and_test(&(task->ref_count))) {
450 _task_free_task(task);
456 sync_agent_ec_boolean ec_task_is_simple_task(ec_task_t * task)
461 _DEBUG_INFO("task == NULL\n");
465 sync_agent_ec_task_spec_s *task_spec = task->task_spec;
469 return ec_task_spec_is_simple(task_spec);
472 sync_agent_ec_boolean ec_task_is_container_task(ec_task_t * task)
477 _DEBUG_INFO("task == NULL\n");
481 sync_agent_ec_task_spec_s *task_spec = task->task_spec;
485 return (ec_task_spec_is_container(task_spec) || ec_task_spec_is_dynamic_container(task_spec));
488 sync_agent_ec_boolean ec_task_is_root_task(ec_task_t * task)
492 ec_task_t *parent_task = ec_task_get_parent_task(task);
493 if (parent_task == NULL) {
502 sync_agent_ec_int ec_task_get_param_cnt(ec_task_t * task)
507 _DEBUG_ERROR("task == NULL\n");
513 return ec_task_spec_get_param_cnt(task->task_spec);
516 sync_agent_ec_boolean ec_task_get_output_param_info(ec_task_t * task, sync_agent_ec_int * pOutput_param_cnt, sync_agent_ec_int ** pOutput_param_index_array)
521 _DEBUG_ERROR("task == NULL");
525 if (task->task_spec == NULL) {
526 _DEBUG_ERROR("task->task_spec == NULL\n");
532 return ec_task_spec_get_output_param_info(task->task_spec, pOutput_param_cnt, pOutput_param_index_array);
535 sync_agent_ec_uint ec_task_get_child_task_cnt(ec_task_t * task)
540 _DEBUG_ERROR("task == NULL\n");
546 return ec_task_spec_get_child_task_cnt(task->task_spec);
549 ec_task_t *ec_task_get_parent_task(ec_task_t * task)
554 _DEBUG_ERROR("task == NULL\n");
560 return task->parent_task;
563 sync_agent_ec_int ec_task_get_child_index_in_parent_task(ec_task_t * task)
568 _DEBUG_ERROR("task == NULL\n");
574 return task->child_task_index_in_parent_task;
577 void ec_task_set_task_error(ec_task_t * task, sync_agent_ec_task_error_e task_error)
582 _DEBUG_ERROR("task == NULL\n");
588 task->task_error = task_error;
591 sync_agent_ec_boolean ec_task_check_same_task_error(ec_task_t * task, sync_agent_ec_task_error_e task_error)
596 _DEBUG_ERROR("task == NULL\n");
600 if (task->task_error == task_error) {
608 sync_agent_ec_boolean ec_task_is_not_yet_run(ec_task_t * task)
614 return ec_task_check_same_task_error(task, SYNC_AGENT_EC_TASK_ERROR_NOT_YET_RUN);
617 void ec_task_do_cancellation(ec_task_t * task)
621 #if !GLIB_CHECK_VERSION (2, 32, 0)
622 g_mutex_lock(task->cancel_information->cancel_info_mutex);
624 g_mutex_lock(&(task->cancel_information->cancel_info_mutex));
627 ec_task_cancel_info_set_cancel_flag_atomic(task->cancel_information);
628 _DEBUG_INFO("task->cancel_information->cancel_flag = %d\n", task->cancel_information->cancel_flag);
629 ec_task_cancel_info_call_cancel_callbacks_unlocked(task->cancel_information);
631 #if !GLIB_CHECK_VERSION (2, 32, 0)
632 g_mutex_unlock(task->cancel_information->cancel_info_mutex);
634 g_mutex_unlock(&(task->cancel_information->cancel_info_mutex));
640 void ec_task_call_task_finish_callback(ec_task_t * task)
644 retm_if(task == NULL, "ec_task_t is NULL !!");
646 ec_request_msg_t *request_msg = (ec_request_msg_t *) sync_agent_get_original_object(task->request_msg);
647 sync_agent_task_finish_cb task_finish_callback = request_msg->task_finish_callback;
648 sync_agent_ec_pointer simple_task_finish_callback_usr_data = request_msg->simple_task_finish_callback_usr_data;
649 if (task_finish_callback != NULL) {
650 _DEBUG_INFO("call finish callback\n");
651 sync_agent_ec_task_error_e task_error = task->task_error;
652 sync_agent_ec_int i = 0;
653 sync_agent_ec_int cnt_out_param = 0;
654 sync_agent_ec_int out_param_index = 0;
655 sync_agent_ec_int *out_param_index_array = NULL;
656 sync_agent_ec_param_param_s **out_param_array = NULL;
657 if (!ec_task_get_output_param_info(task, &cnt_out_param, &out_param_index_array)) {
658 _DEBUG_ERROR("out of memory during ec_task_get_output_param_info\n");
662 if (cnt_out_param > 0 && out_param_index_array != NULL) {
663 out_param_array = (sync_agent_ec_param_param_s **) calloc(cnt_out_param, sizeof(sync_agent_ec_param_param_s *));
664 if (out_param_array == NULL) {
665 _DEBUG_ERROR("out of memory during ec_task_get_output_param_info\n");
669 for (i = 0; i < cnt_out_param; i++) {
670 out_param_index = out_param_index_array[i];
671 out_param_array[i] = task->param_array[out_param_index];
675 if (out_param_index_array != NULL) {
676 free(out_param_index_array);
679 /* call task_finish_callback */
680 task_finish_callback(task_error, cnt_out_param, out_param_array, simple_task_finish_callback_usr_data);
683 _DEBUG_INFO("cannot call finish callback\n");
684 /* TODO : remove output parameters since we have to nothing to return but prevent memory leak */
690 void ec_task_remove_control_flow(ec_task_t * parent_task, sync_agent_ec_int from_task_index, sync_agent_ec_int to_task_index)
694 if (parent_task == NULL) {
695 _DEBUG_ERROR("parent_task == NULL\n");
699 sync_agent_ec_task_spec_s *parent_task_spec = parent_task->task_spec;
700 sync_agent_ec_error_e ec_error = SYNC_AGENT_EC_OK;
701 if (ec_task_spec_is_container(parent_task_spec)) {
702 ec_error = ec_task_spec_valididate_child_task_index(parent_task_spec, to_task_index);
704 } else if (ec_task_spec_is_dynamic_container(parent_task_spec)) {
705 ec_error = ec_task_spec_valididate_child_task_index_on_dynamic_case(parent_task->dynamic_case, parent_task_spec, to_task_index);
708 if (ec_error != SYNC_AGENT_EC_OK) {
709 _DEBUG_ERROR("invalid to_task_index. to_task_index = %d\n", to_task_index);
713 /* remove in_degree of to_task */
714 parent_task->current_child_task_control_flow_in_degree_array[to_task_index] -= 1;
719 void ec_task_set_left_child_to_run(ec_task_t * parent_task, sync_agent_ec_uint number)
723 parent_task->cnt_left_child_task_to_finish = number;
728 sync_agent_ec_boolean ec_task_is_left_child_to_run_zero(ec_task_t * parent_task)
734 return (parent_task->cnt_left_child_task_to_finish == 0);
737 void ec_task_decrease_left_child_to_run(ec_task_t * parent_task)
741 (parent_task->cnt_left_child_task_to_finish)--;
746 sync_agent_ec_boolean ec_task_is_parent_EC_TASK_DONE(ec_task_t * parent_task)
750 if (ec_task_is_left_child_to_run_zero(parent_task)) {
759 void ec_task_collect_parent_task_output_parameter(ec_task_t * parent_task)
763 if (parent_task == NULL) {
764 _DEBUG_ERROR("parent_task == NULL\n");
768 if (!ec_task_is_container_task(parent_task)) {
769 _DEBUG_ERROR("parent_task is not container task\n");
773 sync_agent_ec_param_param_s *to_param = NULL;
774 sync_agent_ec_param_spec_s *to_param_spec = NULL;
775 sync_agent_ec_param_param_s *from_param = NULL;
777 sync_agent_ec_int i = 0;
778 sync_agent_ec_int param_cnt = ec_task_get_param_cnt(parent_task);
779 for (i = 0; i < param_cnt; i++) {
780 to_param = parent_task->param_array[i];
781 to_param_spec = to_param->pParam_spec;
783 if (ec_param_is_output_flag_on(to_param_spec->flags)) {
784 from_param = _task_fetch_from_param(parent_task, -1, i);
786 if (from_param != NULL) {
787 /* set output parameter values */
788 ec_set_param_value_with_other_param_value(&(to_param->param_value), &(from_param->param_value));
796 GSList *ec_collect_firstly_runnable_child_tasks(ec_task_t * parent_task)
800 GSList *runnable_child_task_list = NULL;
801 if (!ec_task_is_container_task(parent_task)) {
805 sync_agent_ec_int i = 0;
806 sync_agent_ec_task_spec_s *parent_task_spec = parent_task->task_spec;
807 ec_child_tasks_info_t *child_task_info = NULL;
808 if (ec_task_spec_is_container(parent_task_spec)) {
809 child_task_info = ec_task_spec_find_child_tasks_info(parent_task_spec);
810 } else if (ec_task_spec_is_dynamic_container(parent_task_spec)) {
811 child_task_info = ec_task_spec_find_case_specific_child_tasks_info(parent_task_spec, parent_task->dynamic_case);
816 sync_agent_ec_int child_task_cnt;
817 sync_agent_ec_uint *child_task_control_flow_in_degree;
819 if (child_task_info != NULL) {
820 child_task_cnt = child_task_info->child_task_cnt;
821 child_task_control_flow_in_degree = child_task_info->child_task_control_flow_in_degree;
826 ec_task_t *child_task = NULL;
827 for (i = 0; i < child_task_cnt; i++) {
828 if (child_task_control_flow_in_degree[i] == 0) {
829 child_task = ec_task_alloc_child_task(parent_task, i);
830 if (child_task == NULL) {
834 parent_task->child_task_array[i] = child_task;
835 runnable_child_task_list = g_slist_append(runnable_child_task_list, child_task);
841 return runnable_child_task_list;
844 if (runnable_child_task_list != NULL) {
846 for (iter = runnable_child_task_list; iter != NULL; iter = g_slist_next(iter)) {
847 child_task = (ec_task_t *) (iter->data);
848 ec_task_unref_task(child_task);
850 g_slist_free(runnable_child_task_list);
856 GSList *ec_collect_become_runnable_child_tasks_by_remove_control_flow(ec_task_t * parent_task, sync_agent_ec_int from_child_task_index)
860 GSList *runnable_child_task_list = NULL;
861 if (!ec_task_is_container_task(parent_task)) {
866 sync_agent_ec_task_spec_s *parent_task_spec = parent_task->task_spec;
867 sync_agent_ec_error_e ec_error = SYNC_AGENT_EC_OK;
868 if (ec_task_spec_is_container(parent_task_spec)) {
869 ec_error = ec_task_spec_valididate_child_task_index(parent_task_spec, from_child_task_index);
871 } else if (ec_task_spec_is_dynamic_container(parent_task_spec)) {
872 ec_error = ec_task_spec_valididate_child_task_index_on_dynamic_case(parent_task->dynamic_case, parent_task_spec, from_child_task_index);
874 if (ec_error != SYNC_AGENT_EC_OK) {
875 _DEBUG_ERROR("invalid from child task index. from child task index = %d\n", from_child_task_index);
879 ec_child_tasks_info_t *child_task_info = NULL;
880 if (ec_task_spec_is_container(parent_task_spec)) {
881 child_task_info = ec_task_spec_find_child_tasks_info(parent_task_spec);
882 } else if (ec_task_spec_is_dynamic_container(parent_task_spec)) {
883 child_task_info = ec_task_spec_find_case_specific_child_tasks_info(parent_task_spec, parent_task->dynamic_case);
888 ec_graph_edge_pool_t *control_edge_pool;
890 if (child_task_info != NULL) {
891 control_edge_pool = child_task_info->control_edge_pool;
896 /* get to node list from child_index */
897 /* note that to nodes_list containing sync_agent_ec_int */
898 GList *to_node_list = ec_graph_edge_pool_query_to_node_list(control_edge_pool, (sync_agent_ec_constpointer) from_child_task_index);
900 /* remove control flow from child task at child_index of parent task */
902 sync_agent_ec_int to_child_task_index = 0;
903 ec_task_t *to_child_task = NULL;
904 for (iter = to_node_list; iter != NULL; iter = g_list_next(iter)) {
905 to_child_task_index = (sync_agent_ec_int) (iter->data);
906 ec_task_remove_control_flow(parent_task, from_child_task_index, to_child_task_index);
908 /* if zero in-degree of control flow detected, make child task and append runnable_child_task_list */
909 if (parent_task->current_child_task_control_flow_in_degree_array[to_child_task_index] == 0) {
910 to_child_task = ec_task_alloc_child_task(parent_task, to_child_task_index);
911 if (to_child_task == NULL) {
912 _DEBUG_ERROR("out of memory\n");
916 parent_task->child_task_array[to_child_task_index] = to_child_task;
917 runnable_child_task_list = g_slist_append(runnable_child_task_list, to_child_task);
923 return runnable_child_task_list;
926 if (runnable_child_task_list != NULL) {
928 ec_task_t *child_task;
929 for (iter = runnable_child_task_list; iter != NULL; iter = g_slist_next(iter)) {
930 child_task = (ec_task_t *) (iter->data);
931 ec_task_unref_task(child_task);
933 g_slist_free(runnable_child_task_list);
939 sync_agent_ec_task_error_e ec_task_run_simple_task(ec_task_t * pSimple_task)
943 retvm_if(pSimple_task == NULL, SYNC_AGENT_EC_TASK_ERROR_INVALID_TASK, "ec_task_t is NULL !!");
945 sync_agent_ec_task_error_e task_error = SYNC_AGENT_EC_TASK_ERROR_NOT_YET_RUN;
947 sync_agent_ec_task_spec_s *task_spec = pSimple_task->task_spec;
948 ec_task_cancel_info_t *cancel_info = pSimple_task->cancel_information;
950 sync_agent_util_ref_object_s *request_msg_ref = pSimple_task->request_msg;
951 ec_request_msg_t *request_msg = (ec_request_msg_t *) sync_agent_get_original_object(request_msg_ref);
953 sync_agent_ec_int request_msg_id = request_msg->msg_head.msg_id;
955 if (-1 == gettimeofday(&(pSimple_task->run_time), NULL)) {
956 _DEBUG_INFO("setting run time error\n");
959 if (ec_task_cancel_info_get_cancel_flag_atomic(cancel_info)) {
960 _DEBUG_INFO("cancel flag on case\n");
962 /* do not run task if cancellation flag on */
963 task_error = SYNC_AGENT_EC_TASK_ERROR_CANCELED;
965 _DEBUG_INFO("cancel flag off case\n");
966 task_error = task_spec->u.task_process(pSimple_task->task_spec->task_param_cnt, pSimple_task->param_array);
969 if (-1 == gettimeofday(&(pSimple_task->finish_time), NULL)) {
970 _DEBUG_ERROR("setting finish time error\n");
973 /* set task error information */
974 ec_task_set_task_error(pSimple_task, task_error);
976 if (task_spec->post_func != NULL) {
977 task_spec->post_func(task_spec->usr_post_task_func_data, request_msg_id);
985 sync_agent_ec_boolean ec_task_add_pending_task_list_of_first_progress_blocking_realized_entity(ec_task_t * task)
989 sync_agent_ec_boolean is_pending_task = false;
991 GSList *iter_current_node = NULL;
992 GSList *iter_realized_entity = NULL;
993 ec_n_ary_tree_node_with_flag_t *current_node = NULL;
994 ec_progress_blocking_realized_entity_t *realized_entity = NULL;
995 ec_progress_blocking_realized_entity_t *prev_realized_entity = NULL;
996 GQueue *progress_blocking_queue = NULL;
998 /* iterate all queuing rules related to task */
999 for (iter_current_node = task->current_node_in_progress_blocking_entity_list, iter_realized_entity = task->progress_blocking_realized_entity_list; iter_current_node != NULL && iter_realized_entity != NULL;
1000 iter_current_node = g_slist_next(iter_current_node), iter_realized_entity = g_slist_next(iter_realized_entity)) {
1001 current_node = (ec_n_ary_tree_node_with_flag_t *) (iter_current_node->data);
1002 realized_entity = (ec_progress_blocking_realized_entity_t *) (iter_realized_entity->data);
1004 progress_blocking_queue = realized_entity->entity->queuing_rule_spec->progress_blocking_queue;
1005 if (current_node != NULL && ec_n_ary_tree_node_with_flag_is_blocking_flag_on(current_node) && g_queue_peek_head(progress_blocking_queue) != realized_entity) {
1006 /* pending condition */
1007 GList *realized_entity_node = g_queue_find(progress_blocking_queue, realized_entity);
1008 GList *prev_realized_entity_node = realized_entity_node->prev;
1010 prev_realized_entity = (ec_progress_blocking_realized_entity_t *) (prev_realized_entity_node->data);
1011 ec_progress_blocking_realized_entity_add_pending_task(prev_realized_entity, task);
1012 is_pending_task = true;
1013 break; /* note that only append first found queue */
1019 return is_pending_task;
1022 void ec_task_update_progress_blocking_realized_entity_and_pop_if_possible(ec_task_t * task)
1026 retm_if(task == NULL, "ec_task_t is NULL !!");
1028 GSList *iter_current_node = NULL;
1029 GSList *iter_realized_entity = NULL;
1030 ec_n_ary_tree_node_with_flag_t *current_node = NULL;
1031 ec_progress_blocking_realized_entity_t *realized_entity = NULL;
1032 GQueue *progress_blocking_queue = NULL;
1034 for (iter_current_node = task->current_node_in_progress_blocking_entity_list, iter_realized_entity = task->progress_blocking_realized_entity_list; iter_current_node != NULL && iter_realized_entity != NULL;
1035 iter_current_node = g_slist_next(iter_current_node), iter_realized_entity = g_slist_next(iter_realized_entity)) {
1036 current_node = (ec_n_ary_tree_node_with_flag_t *) (iter_current_node->data);
1037 realized_entity = (ec_progress_blocking_realized_entity_t *) (iter_realized_entity->data);
1038 if (ec_progress_blocking_realized_entity_update_and_test_left_progress_blocking_element_cnt(realized_entity, current_node, task)) {
1039 /* pop realized_entity in queue */
1040 progress_blocking_queue = realized_entity->entity->queuing_rule_spec->progress_blocking_queue;
1041 g_queue_remove(progress_blocking_queue, realized_entity);
1043 /* restart pending tasks due to realized_entity */
1044 ec_progress_blocking_realized_entity_restart_pending_task(realized_entity);
1051 #include "engine-controller/task_message.h"
1053 ec_progress_blocking_realized_entity_t *ec_progress_blocking_realized_entity_new(ec_progress_blocking_entity_t * entity)
1057 ec_progress_blocking_realized_entity_t *realized_entity = (ec_progress_blocking_realized_entity_t *) calloc(1, sizeof(ec_progress_blocking_realized_entity_t));
1058 if (realized_entity == NULL) {
1062 realized_entity->entity = ec_progress_blocking_entity_ref(entity);
1063 realized_entity->left_progress_blocking_element_cnt = entity->element_set->progress_blocking_element_cnt;
1064 realized_entity->pending_task_list = NULL;
1068 return realized_entity;
1071 ec_progress_blocking_realized_entity_free(realized_entity);
1075 void ec_progress_blocking_realized_entity_free(ec_progress_blocking_realized_entity_t * realized_entity)
1079 if (realized_entity != NULL) {
1080 if (realized_entity->entity != NULL) {
1081 ec_progress_blocking_entity_unref(realized_entity->entity);
1084 if (realized_entity->pending_task_list != NULL) {
1085 GSList *iter = NULL;
1086 ec_task_t *pending_task = NULL;
1087 for (iter = realized_entity->pending_task_list; iter != NULL; iter = g_slist_next(iter)) {
1088 pending_task = (ec_task_t *) (iter->data);
1089 ec_task_unref_task(pending_task);
1092 g_slist_free(realized_entity->pending_task_list);
1095 free(realized_entity);
1101 void ec_progress_blocking_realized_entity_restart_pending_task(ec_progress_blocking_realized_entity_t * realized_entity)
1105 retm_if(realized_entity == NULL, "ec_progress_blocking_realized_entity_t is NULL !!");
1107 GSList *iter = NULL;
1108 ec_task_t *pending_task = NULL;
1109 ec_request_msg_t *request_msg = NULL;
1110 ec_task_message_t *new_task_msg = NULL;
1111 for (iter = realized_entity->pending_task_list; iter != NULL; iter = g_slist_next(iter)) {
1112 pending_task = (ec_task_t *) (iter->data);
1113 request_msg = (ec_request_msg_t *) sync_agent_get_original_object(pending_task->request_msg);
1115 _DEBUG_INFO("pending task (request msg id = %d, task spec id = %d, task spec name = %s) by queuing rule restarted\n", request_msg->msg_head.msg_id, pending_task->task_info->task_spec_id, pending_task->task_info->task_spec->task_name);
1117 /* send msg to engine controller itself */
1118 new_task_msg = ec_task_message_create(EC_TASK_START, pending_task, 0);
1119 ec_send_msg_to_engine_controller_with_compare_priority(new_task_msg, ec_compare_priority_of_task_message_append_way, NULL);
1121 /* TODO : error handling */
1127 void ec_progress_blocking_realized_entity_add_pending_task(ec_progress_blocking_realized_entity_t * entity, ec_task_t * pending_task)
1131 retm_if(entity == NULL, "ec_progress_blocking_realized_entity_t is NULL !!");
1133 entity->pending_task_list = g_slist_append(entity->pending_task_list, ec_task_ref_task(pending_task));
1138 sync_agent_ec_boolean ec_progress_blocking_realized_entity_update_and_test_left_progress_blocking_element_cnt(ec_progress_blocking_realized_entity_t * realized_entity, ec_n_ary_tree_node_with_flag_t * current_node, ec_task_t * task)
1142 if (ec_progress_blocking_realized_entity_is_zero_left_progress_blocking_element_cnt(realized_entity)) {
1146 sync_agent_ec_boolean become_zero_after_update = false;
1148 switch (task->task_error) {
1149 case SYNC_AGENT_EC_TASK_ERROR_INVALID_TASK:
1150 _DEBUG_INFO("invalid task error returned\n");
1152 case SYNC_AGENT_EC_TASK_ERROR_RUN_FAILED:
1153 case SYNC_AGENT_EC_TASK_ERROR_CANCELED:
1154 become_zero_after_update = true;
1155 realized_entity->left_progress_blocking_element_cnt = 0;
1157 case SYNC_AGENT_EC_TASK_ERROR_RUN_SUCCESS:
1158 if (current_node != NULL && ec_n_ary_tree_node_with_flag_is_blocking_flag_on(current_node)) {
1159 (realized_entity->left_progress_blocking_element_cnt)--;
1161 if (ec_progress_blocking_realized_entity_is_zero_left_progress_blocking_element_cnt(realized_entity)) {
1162 become_zero_after_update = true;
1166 case SYNC_AGENT_EC_TASK_ERROR_NOT_YET_RUN:
1167 if (current_node != NULL && ec_task_spec_is_dynamic_container(task->task_spec)) {
1168 /* we can remove other dynamic case progress_blocking_element */
1170 sync_agent_ec_uint can_remove_flag_on_cnt = 0;
1172 ec_n_ary_tree_node_with_flag_t *child_node = NULL;
1173 for (child_node = current_node->first_child_node; child_node != NULL; child_node = child_node->next_sibling_node) {
1174 if (child_node->dynamic_case != task->dynamic_case) {
1175 can_remove_flag_on_cnt += ec_n_ary_tree_node_with_flag_count_subtree_flag_on_number(child_node);
1179 if (can_remove_flag_on_cnt > 0) {
1180 (realized_entity->left_progress_blocking_element_cnt) -= can_remove_flag_on_cnt;
1182 if (ec_progress_blocking_realized_entity_is_zero_left_progress_blocking_element_cnt(realized_entity)) {
1183 become_zero_after_update = true;
1189 _DEBUG_INFO("unknown task error returned\n");
1190 become_zero_after_update = true;
1191 realized_entity->left_progress_blocking_element_cnt = 0;
1197 return become_zero_after_update;
1200 sync_agent_ec_boolean ec_progress_blocking_realized_entity_is_zero_left_progress_blocking_element_cnt(ec_progress_blocking_realized_entity_t * realized_entity)
1206 return realized_entity->left_progress_blocking_element_cnt == 0;