6ca75ed3228a27e5ce0e9e0720fecbc7b475bdc1
[platform/core/system/sync-agent.git] / src / framework / engine-controller / task.c
1 /*
2  * sync-agent
3  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4  *
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <assert.h>
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"
29
30 #ifndef SYNC_AGENT_LOG
31 #undef LOG_TAG
32 #define LOG_TAG "AF_EC"
33 #endif
34
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);
37
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)
39 {
40         _INNER_FUNC_ENTER;
41
42         retvm_if(parent_task == NULL, NULL, "ec_task_t is NULL !!");
43
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);
51         } else {
52                 assert(false);
53         }
54
55         ec_data_flow_edges_t *data_flow_edges;
56
57         if (child_task_info != NULL) {
58                 data_flow_edges = child_task_info->data_flow_edges;
59         } else {
60                 goto error_part;
61         }
62
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);
68         if (find_success) {
69                 if (from_task_index == -1) {
70                         /* get from parent_task */
71                         fetched_param = parent_task->param_array[from_param_index];
72                 } else {
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);
79                         }
80                         if (ec_error != SYNC_AGENT_EC_OK) {
81                                 goto error_part;
82                         }
83
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];
87                 }
88         }
89
90         _INNER_FUNC_EXIT;
91
92         return fetched_param;
93
94  error_part:
95         return NULL;
96 }
97
98 /* TODO : handling error case */
99 GSList *ec_task_construct_progress_blocking_realized_entity_list(ec_task_info_t * task_info)
100 {
101         _EXTERN_FUNC_ENTER;
102
103         GSList *progress_blocking_realized_entity_list = NULL;
104
105         /* add progress blocking entity according to queuing rule */
106         GSList *iter = NULL;
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);
111
112                 realized_entity = ec_progress_blocking_realized_entity_new(entity);
113
114                 progress_blocking_realized_entity_list = g_slist_prepend(progress_blocking_realized_entity_list, realized_entity);
115
116                 /* create progress_queuing_entity */
117                 g_queue_push_tail(entity->queuing_rule_spec->progress_blocking_queue, realized_entity);
118         }
119
120         _EXTERN_FUNC_EXIT;
121
122         return progress_blocking_realized_entity_list;
123 }
124
125 /* TODO : handling error case */
126 GSList *ec_task_construct_current_node_in_progress_blocking_entity_list(ec_task_info_t * task_info)
127 {
128         _EXTERN_FUNC_ENTER;
129
130         GSList *current_node_in_progress_blocking_entity_list = NULL;
131
132         /* add progress blocking entity according to queuing rule */
133         GSList *iter = NULL;
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);
137
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);
139         }
140
141         _EXTERN_FUNC_EXIT;
142
143         return current_node_in_progress_blocking_entity_list;
144 }
145
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)
147 {
148         _EXTERN_FUNC_ENTER;
149
150         GSList *current_node_in_progress_blocking_entity_list = NULL;
151
152         /* add progress blocking entity according to queuing rule */
153         GSList *iter = NULL;
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;
160                 } else {
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 */
163                 }
164
165                 current_node_in_progress_blocking_entity_list = g_slist_prepend(current_node_in_progress_blocking_entity_list, child_tree_node);
166         }
167
168         _EXTERN_FUNC_EXIT;
169
170         return current_node_in_progress_blocking_entity_list;
171 }
172
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)
174 {
175         _EXTERN_FUNC_ENTER;
176
177         ec_task_t *task = NULL;
178         sync_agent_ec_int i = 0;
179         sync_agent_ec_uint child_task_cnt = 0;
180
181         if (task_spec == NULL) {
182                 _DEBUG_INFO("input task is NULL");
183                 goto error_part;
184         }
185
186         task = (ec_task_t *) calloc(1, sizeof(ec_task_t));
187         if (task == NULL) {
188                 goto error_part;
189         }
190
191         task->ref_count = 1;
192         task->task_error = SYNC_AGENT_EC_TASK_ERROR_NOT_YET_RUN;
193
194         task->task_info = ec_task_info_pool_search_task_info(task_info_pool, request_msg->task_spec_id);
195
196         task->progress_blocking_realized_entity_list = ec_task_construct_progress_blocking_realized_entity_list(task->task_info);
197
198         task->current_node_in_progress_blocking_entity_list = ec_task_construct_current_node_in_progress_blocking_entity_list(task->task_info);
199
200         task->parent_task = NULL;
201         task->child_task_index_in_parent_task = 0;      /* meaningless value */
202
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) {
205                 goto error_part;
206         }
207
208         /* set parameter values in param_array */
209         int index = 0;
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]));
214         }
215
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);
221                 }
222         }
223
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)) {
227                 /* compute case */
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 !!");
231                         goto error_part;
232                 }
233
234                 task->dynamic_case = calculate_case_func(task_spec->task_param_cnt, task->param_array);
235
236                 child_task_cnt = ec_task_spec_get_child_task_cnt_on_dynamic_case(task_spec, task->dynamic_case);
237         }
238
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) {
242                         goto error_part;
243                 }
244         }
245
246         ec_task_set_left_child_to_run(task, child_task_cnt);
247
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) {
252                         goto error_part;
253                 }
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) {
257                         goto error_part;
258                 }
259         } else {
260                 task->current_child_task_control_flow_in_degree_array = NULL;
261         }
262
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) {
266                 goto error_part;
267         }
268         task->request_msg = pRequest_Msg_ref;
269
270         task->cancel_information = ec_task_cancel_info_init(pRequest_Msg_ref);
271         if (task->cancel_information == NULL) {
272                 goto error_part;
273         }
274
275         if (-1 == gettimeofday(&(task->create_time), NULL)) {
276                 goto error_part;
277         }
278
279         _EXTERN_FUNC_EXIT;
280
281         return task;
282
283  error_part:
284         _task_free_task(task);
285         return NULL;
286 }
287
288 ec_task_t *ec_task_alloc_child_task(ec_task_t * parent_task, sync_agent_ec_int child_index)
289 {
290         _EXTERN_FUNC_ENTER;
291
292         retvm_if(parent_task == NULL, NULL, "ec_task_t is NULL !!");
293
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;
297
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);
303                         goto error_part;
304                 }
305
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);
311                         goto error_part;
312                 }
313
314                 child_tasks_info = ec_task_spec_find_case_specific_child_tasks_info(parent_task_spec, parent_task->dynamic_case);
315         }
316
317         sync_agent_ec_task_spec_s *child_task_spec;
318
319         if (child_tasks_info != NULL) {
320                 child_task_spec = child_tasks_info->child_task_array[child_index];
321         } else {
322                 goto error_part;
323         }
324
325         sync_agent_ec_int i = 0;
326         sync_agent_ec_uint grand_child_task_cnt = 0;
327
328         child_task = (ec_task_t *) calloc(1, sizeof(ec_task_t));
329         if (child_task == NULL) {
330                 goto error_part;
331         }
332
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;
337
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);
340
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) {
343                 goto error_part;
344         }
345
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);
351         }
352
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 !!");
360                         goto error_part;
361                 }
362                 child_task->dynamic_case = calculate_case_func(child_task_spec->task_param_cnt, child_task->param_array);
363
364                 grand_child_task_cnt = ec_task_spec_get_child_task_cnt_on_dynamic_case(child_task_spec, child_task->dynamic_case);
365         }
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) {
368                 goto error_part;
369         }
370
371         ec_task_set_left_child_to_run(child_task, grand_child_task_cnt);
372
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) {
377                         goto error_part;
378                 }
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) {
382                         goto error_part;
383                 }
384         } else {
385                 child_task->current_child_task_control_flow_in_degree_array = NULL;
386         }
387
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);
392
393         if (-1 == gettimeofday(&(child_task->create_time), NULL)) {
394                 goto error_part;
395         }
396
397         _EXTERN_FUNC_EXIT;
398
399         return child_task;
400
401  error_part:
402
403         if (child_task != NULL) {
404                 _task_free_task(child_task);
405         }
406         return NULL;
407 }
408
409 static void _task_free_task(ec_task_t * task)
410 {
411         _INNER_FUNC_ENTER;
412
413         _DEBUG_TRACE("called\n");
414         if (task != NULL) {
415                 /* TODO */
416
417                 ec_task_cancel_info_unref(task->cancel_information);
418                 free(task);
419         }
420
421         _INNER_FUNC_EXIT;
422 }
423
424 ec_task_t *ec_task_ref_task(ec_task_t * task)
425 {
426         _EXTERN_FUNC_ENTER;
427
428         SYNC_AGENT_UTIL_ASSERT_CONDITION(task != NULL, "error. task == NULL\n");
429
430         g_atomic_int_inc(&(task->ref_count));
431
432         _EXTERN_FUNC_EXIT;
433
434         return task;
435 }
436
437 void ec_task_unref_task(ec_task_t * task)
438 {
439         _EXTERN_FUNC_ENTER;
440
441         if (task == NULL) {
442                 return;
443         }
444
445         if (g_atomic_int_get(&(task->ref_count)) <= 0) {
446                 _DEBUG_ERROR("ref count <= 0\n");
447         }
448
449         if (g_atomic_int_dec_and_test(&(task->ref_count))) {
450                 _task_free_task(task);
451         }
452
453         _EXTERN_FUNC_EXIT;
454 }
455
456 sync_agent_ec_boolean ec_task_is_simple_task(ec_task_t * task)
457 {
458         _EXTERN_FUNC_ENTER;
459
460         if (task == NULL) {
461                 _DEBUG_INFO("task == NULL\n");
462                 return false;
463         }
464
465         sync_agent_ec_task_spec_s *task_spec = task->task_spec;
466
467         _EXTERN_FUNC_EXIT;
468
469         return ec_task_spec_is_simple(task_spec);
470 }
471
472 sync_agent_ec_boolean ec_task_is_container_task(ec_task_t * task)
473 {
474         _EXTERN_FUNC_ENTER;
475
476         if (task == NULL) {
477                 _DEBUG_INFO("task == NULL\n");
478                 return false;
479         }
480
481         sync_agent_ec_task_spec_s *task_spec = task->task_spec;
482
483         _EXTERN_FUNC_EXIT;
484
485         return (ec_task_spec_is_container(task_spec) || ec_task_spec_is_dynamic_container(task_spec));
486 }
487
488 sync_agent_ec_boolean ec_task_is_root_task(ec_task_t * task)
489 {
490         _EXTERN_FUNC_ENTER;
491
492         ec_task_t *parent_task = ec_task_get_parent_task(task);
493         if (parent_task == NULL) {
494                 _EXTERN_FUNC_EXIT;
495                 return true;
496         } else {
497                 _EXTERN_FUNC_EXIT;
498                 return false;
499         }
500 }
501
502 sync_agent_ec_int ec_task_get_param_cnt(ec_task_t * task)
503 {
504         _EXTERN_FUNC_ENTER;
505
506         if (task == NULL) {
507                 _DEBUG_ERROR("task == NULL\n");
508                 return -1;
509         }
510
511         _EXTERN_FUNC_EXIT;
512
513         return ec_task_spec_get_param_cnt(task->task_spec);
514 }
515
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)
517 {
518         _EXTERN_FUNC_ENTER;
519
520         if (task == NULL) {
521                 _DEBUG_ERROR("task == NULL");
522                 return false;
523         }
524
525         if (task->task_spec == NULL) {
526                 _DEBUG_ERROR("task->task_spec == NULL\n");
527                 return false;
528         }
529
530         _EXTERN_FUNC_EXIT;
531
532         return ec_task_spec_get_output_param_info(task->task_spec, pOutput_param_cnt, pOutput_param_index_array);
533 }
534
535 sync_agent_ec_uint ec_task_get_child_task_cnt(ec_task_t * task)
536 {
537         _EXTERN_FUNC_ENTER;
538
539         if (task == NULL) {
540                 _DEBUG_ERROR("task == NULL\n");
541                 return -1;
542         }
543
544         _EXTERN_FUNC_EXIT;
545
546         return ec_task_spec_get_child_task_cnt(task->task_spec);
547 }
548
549 ec_task_t *ec_task_get_parent_task(ec_task_t * task)
550 {
551         _EXTERN_FUNC_ENTER;
552
553         if (task == NULL) {
554                 _DEBUG_ERROR("task == NULL\n");
555                 return NULL;
556         }
557
558         _EXTERN_FUNC_EXIT;
559
560         return task->parent_task;
561 }
562
563 sync_agent_ec_int ec_task_get_child_index_in_parent_task(ec_task_t * task)
564 {
565         _EXTERN_FUNC_ENTER;
566
567         if (task == NULL) {
568                 _DEBUG_ERROR("task == NULL\n");
569                 return -1;
570         }
571
572         _EXTERN_FUNC_EXIT;
573
574         return task->child_task_index_in_parent_task;
575 }
576
577 void ec_task_set_task_error(ec_task_t * task, sync_agent_ec_task_error_e task_error)
578 {
579         _EXTERN_FUNC_ENTER;
580
581         if (task == NULL) {
582                 _DEBUG_ERROR("task == NULL\n");
583                 return;
584         }
585
586         _EXTERN_FUNC_EXIT;
587
588         task->task_error = task_error;
589 }
590
591 sync_agent_ec_boolean ec_task_check_same_task_error(ec_task_t * task, sync_agent_ec_task_error_e task_error)
592 {
593         _EXTERN_FUNC_ENTER;
594
595         if (task == NULL) {
596                 _DEBUG_ERROR("task == NULL\n");
597                 return false;
598         }
599
600         if (task->task_error == task_error) {
601                 _EXTERN_FUNC_EXIT;
602                 return true;
603         }
604         _EXTERN_FUNC_EXIT;
605         return false;
606 }
607
608 sync_agent_ec_boolean ec_task_is_not_yet_run(ec_task_t * task)
609 {
610         _EXTERN_FUNC_ENTER;
611
612         _EXTERN_FUNC_EXIT;
613
614         return ec_task_check_same_task_error(task, SYNC_AGENT_EC_TASK_ERROR_NOT_YET_RUN);
615 }
616
617 void ec_task_do_cancellation(ec_task_t * task)
618 {
619         _EXTERN_FUNC_ENTER;
620
621 #if !GLIB_CHECK_VERSION (2, 32, 0)
622         g_mutex_lock(task->cancel_information->cancel_info_mutex);
623 #else
624         g_mutex_lock(&(task->cancel_information->cancel_info_mutex));
625 #endif
626
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);
630
631 #if !GLIB_CHECK_VERSION (2, 32, 0)
632         g_mutex_unlock(task->cancel_information->cancel_info_mutex);
633 #else
634         g_mutex_unlock(&(task->cancel_information->cancel_info_mutex));
635 #endif
636
637         _EXTERN_FUNC_EXIT;
638 }
639
640 void ec_task_call_task_finish_callback(ec_task_t * task)
641 {
642         _EXTERN_FUNC_ENTER;
643
644         retm_if(task == NULL, "ec_task_t is NULL !!");
645
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");
659                         assert(false);
660                 }
661
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");
666                                 assert(false);
667                         }
668
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];
672                         }
673                 }
674
675                 if (out_param_index_array != NULL) {
676                         free(out_param_index_array);
677                 }
678
679                 /* call task_finish_callback */
680                 task_finish_callback(task_error, cnt_out_param, out_param_array, simple_task_finish_callback_usr_data);
681
682         } else {
683                 _DEBUG_INFO("cannot call finish callback\n");
684                 /* TODO : remove output parameters since we have to nothing to return but prevent memory leak */
685         }
686
687         _EXTERN_FUNC_EXIT;
688 }
689
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)
691 {
692         _EXTERN_FUNC_ENTER;
693
694         if (parent_task == NULL) {
695                 _DEBUG_ERROR("parent_task == NULL\n");
696                 return;
697         }
698
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);
703
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);
706         }
707
708         if (ec_error != SYNC_AGENT_EC_OK) {
709                 _DEBUG_ERROR("invalid to_task_index. to_task_index = %d\n", to_task_index);
710                 return;
711         }
712
713         /* remove in_degree of to_task */
714         parent_task->current_child_task_control_flow_in_degree_array[to_task_index] -= 1;
715
716         _EXTERN_FUNC_EXIT;
717 }
718
719 void ec_task_set_left_child_to_run(ec_task_t * parent_task, sync_agent_ec_uint number)
720 {
721         _EXTERN_FUNC_ENTER;
722
723         parent_task->cnt_left_child_task_to_finish = number;
724
725         _EXTERN_FUNC_EXIT;
726 }
727
728 sync_agent_ec_boolean ec_task_is_left_child_to_run_zero(ec_task_t * parent_task)
729 {
730         _EXTERN_FUNC_ENTER;
731
732         _EXTERN_FUNC_EXIT;
733
734         return (parent_task->cnt_left_child_task_to_finish == 0);
735 }
736
737 void ec_task_decrease_left_child_to_run(ec_task_t * parent_task)
738 {
739         _EXTERN_FUNC_ENTER;
740
741         (parent_task->cnt_left_child_task_to_finish)--;
742
743         _EXTERN_FUNC_EXIT;
744 }
745
746 sync_agent_ec_boolean ec_task_is_parent_EC_TASK_DONE(ec_task_t * parent_task)
747 {
748         _EXTERN_FUNC_ENTER;
749
750         if (ec_task_is_left_child_to_run_zero(parent_task)) {
751                 _EXTERN_FUNC_EXIT;
752                 return true;
753         } else {
754                 _EXTERN_FUNC_EXIT;
755                 return false;
756         }
757 }
758
759 void ec_task_collect_parent_task_output_parameter(ec_task_t * parent_task)
760 {
761         _EXTERN_FUNC_ENTER;
762
763         if (parent_task == NULL) {
764                 _DEBUG_ERROR("parent_task == NULL\n");
765                 return;
766         }
767
768         if (!ec_task_is_container_task(parent_task)) {
769                 _DEBUG_ERROR("parent_task is not container task\n");
770                 return;
771         }
772
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;
776
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;
782
783                 if (ec_param_is_output_flag_on(to_param_spec->flags)) {
784                         from_param = _task_fetch_from_param(parent_task, -1, i);
785
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));
789                         }
790                 }
791         }
792
793         _EXTERN_FUNC_EXIT;
794 }
795
796 GSList *ec_collect_firstly_runnable_child_tasks(ec_task_t * parent_task)
797 {
798         _EXTERN_FUNC_ENTER;
799
800         GSList *runnable_child_task_list = NULL;
801         if (!ec_task_is_container_task(parent_task)) {
802                 goto error_part;
803         }
804
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);
812         } else {
813                 assert(false);
814         }
815
816         sync_agent_ec_int child_task_cnt;
817         sync_agent_ec_uint *child_task_control_flow_in_degree;
818
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;
822         } else {
823                 goto error_part;
824         }
825
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) {
831                                 goto error_part;
832                         }
833
834                         parent_task->child_task_array[i] = child_task;
835                         runnable_child_task_list = g_slist_append(runnable_child_task_list, child_task);
836                 }
837         }
838
839         _EXTERN_FUNC_EXIT;
840
841         return runnable_child_task_list;
842
843  error_part:
844         if (runnable_child_task_list != NULL) {
845                 GSList *iter = 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);
849                 }
850                 g_slist_free(runnable_child_task_list);
851         }
852
853         return NULL;
854 }
855
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)
857 {
858         _EXTERN_FUNC_ENTER;
859
860         GSList *runnable_child_task_list = NULL;
861         if (!ec_task_is_container_task(parent_task)) {
862                 goto error_part;
863         }
864
865         /* validation */
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);
870
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);
873         }
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);
876                 goto error_part;
877         }
878
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);
884         } else {
885                 assert(false);
886         }
887
888         ec_graph_edge_pool_t *control_edge_pool;
889
890         if (child_task_info != NULL) {
891                 control_edge_pool = child_task_info->control_edge_pool;
892         } else {
893                 goto error_part;
894         }
895
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);
899
900         /* remove control flow from child task at child_index of parent task */
901         GList *iter = NULL;
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);
907
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");
913                                 goto error_part;
914                         }
915
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);
918                 }
919         }
920
921         _EXTERN_FUNC_EXIT;
922
923         return runnable_child_task_list;
924
925  error_part:
926         if (runnable_child_task_list != NULL) {
927                 GSList *iter = 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);
932                 }
933                 g_slist_free(runnable_child_task_list);
934         }
935
936         return NULL;
937 }
938
939 sync_agent_ec_task_error_e ec_task_run_simple_task(ec_task_t * pSimple_task)
940 {
941         _EXTERN_FUNC_ENTER;
942
943         retvm_if(pSimple_task == NULL, SYNC_AGENT_EC_TASK_ERROR_INVALID_TASK, "ec_task_t is NULL !!");
944
945         sync_agent_ec_task_error_e task_error = SYNC_AGENT_EC_TASK_ERROR_NOT_YET_RUN;
946
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;
949
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);
952
953         sync_agent_ec_int request_msg_id = request_msg->msg_head.msg_id;
954
955         if (-1 == gettimeofday(&(pSimple_task->run_time), NULL)) {
956                 _DEBUG_INFO("setting run time error\n");
957         }
958
959         if (ec_task_cancel_info_get_cancel_flag_atomic(cancel_info)) {
960                 _DEBUG_INFO("cancel flag on case\n");
961
962                 /* do not run task if cancellation flag on */
963                 task_error = SYNC_AGENT_EC_TASK_ERROR_CANCELED;
964         } else {
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);
967         }
968
969         if (-1 == gettimeofday(&(pSimple_task->finish_time), NULL)) {
970                 _DEBUG_ERROR("setting finish time error\n");
971         }
972
973         /* set task error information */
974         ec_task_set_task_error(pSimple_task, task_error);
975
976         if (task_spec->post_func != NULL) {
977                 task_spec->post_func(task_spec->usr_post_task_func_data, request_msg_id);
978         }
979
980         _EXTERN_FUNC_EXIT;
981
982         return task_error;
983 }
984
985 sync_agent_ec_boolean ec_task_add_pending_task_list_of_first_progress_blocking_realized_entity(ec_task_t * task)
986 {
987         _EXTERN_FUNC_ENTER;
988
989         sync_agent_ec_boolean is_pending_task = false;
990
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;
997
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);
1003
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;
1009
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 */
1014                 }
1015         }
1016
1017         _EXTERN_FUNC_EXIT;
1018
1019         return is_pending_task;
1020 }
1021
1022 void ec_task_update_progress_blocking_realized_entity_and_pop_if_possible(ec_task_t * task)
1023 {
1024         _EXTERN_FUNC_ENTER;
1025
1026         retm_if(task == NULL, "ec_task_t is NULL !!");
1027
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;
1033
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);
1042
1043                         /* restart pending tasks due to realized_entity */
1044                         ec_progress_blocking_realized_entity_restart_pending_task(realized_entity);
1045                 }
1046         }
1047
1048         _EXTERN_FUNC_EXIT;
1049 }
1050
1051 #include "engine-controller/task_message.h"
1052
1053 ec_progress_blocking_realized_entity_t *ec_progress_blocking_realized_entity_new(ec_progress_blocking_entity_t * entity)
1054 {
1055         _EXTERN_FUNC_ENTER;
1056
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) {
1059                 goto error_part;
1060         }
1061
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;
1065
1066         _EXTERN_FUNC_EXIT;
1067
1068         return realized_entity;
1069
1070  error_part:
1071         ec_progress_blocking_realized_entity_free(realized_entity);
1072         return NULL;
1073 }
1074
1075 void ec_progress_blocking_realized_entity_free(ec_progress_blocking_realized_entity_t * realized_entity)
1076 {
1077         _EXTERN_FUNC_ENTER;
1078
1079         if (realized_entity != NULL) {
1080                 if (realized_entity->entity != NULL) {
1081                         ec_progress_blocking_entity_unref(realized_entity->entity);
1082                 }
1083
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);
1090                         }
1091
1092                         g_slist_free(realized_entity->pending_task_list);
1093                 }
1094
1095                 free(realized_entity);
1096         }
1097
1098         _EXTERN_FUNC_EXIT;
1099 }
1100
1101 void ec_progress_blocking_realized_entity_restart_pending_task(ec_progress_blocking_realized_entity_t * realized_entity)
1102 {
1103         _EXTERN_FUNC_ENTER;
1104
1105         retm_if(realized_entity == NULL, "ec_progress_blocking_realized_entity_t is NULL !!");
1106
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);
1114
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);
1116
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);
1120
1121                 /* TODO : error handling */
1122         }
1123
1124         _EXTERN_FUNC_EXIT;
1125 }
1126
1127 void ec_progress_blocking_realized_entity_add_pending_task(ec_progress_blocking_realized_entity_t * entity, ec_task_t * pending_task)
1128 {
1129         _EXTERN_FUNC_ENTER;
1130
1131         retm_if(entity == NULL, "ec_progress_blocking_realized_entity_t is NULL !!");
1132
1133         entity->pending_task_list = g_slist_append(entity->pending_task_list, ec_task_ref_task(pending_task));
1134
1135         _EXTERN_FUNC_EXIT;
1136 }
1137
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)
1139 {
1140         _EXTERN_FUNC_ENTER;
1141
1142         if (ec_progress_blocking_realized_entity_is_zero_left_progress_blocking_element_cnt(realized_entity)) {
1143                 return false;
1144         }
1145
1146         sync_agent_ec_boolean become_zero_after_update = false;
1147
1148         switch (task->task_error) {
1149         case SYNC_AGENT_EC_TASK_ERROR_INVALID_TASK:
1150                 _DEBUG_INFO("invalid task error returned\n");
1151                 break;
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;
1156                 break;
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)--;
1160
1161                         if (ec_progress_blocking_realized_entity_is_zero_left_progress_blocking_element_cnt(realized_entity)) {
1162                                 become_zero_after_update = true;
1163                         }
1164                 }
1165                 break;
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 */
1169
1170                         sync_agent_ec_uint can_remove_flag_on_cnt = 0;
1171
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);
1176                                 }
1177                         }
1178
1179                         if (can_remove_flag_on_cnt > 0) {
1180                                 (realized_entity->left_progress_blocking_element_cnt) -= can_remove_flag_on_cnt;
1181
1182                                 if (ec_progress_blocking_realized_entity_is_zero_left_progress_blocking_element_cnt(realized_entity)) {
1183                                         become_zero_after_update = true;
1184                                 }
1185                         }
1186                 }
1187                 break;
1188         default:
1189                 _DEBUG_INFO("unknown task error returned\n");
1190                 become_zero_after_update = true;
1191                 realized_entity->left_progress_blocking_element_cnt = 0;
1192                 break;
1193         }
1194
1195         _EXTERN_FUNC_EXIT;
1196
1197         return become_zero_after_update;
1198 }
1199
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)
1201 {
1202         _EXTERN_FUNC_ENTER;
1203
1204         _EXTERN_FUNC_EXIT;
1205
1206         return realized_entity->left_progress_blocking_element_cnt == 0;
1207 }