Fix compatibility for x64 arch.
[platform/core/system/sync-agent.git] / src / framework / engine-controller / task_spec.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 <stdlib.h>
19 #include <string.h>
20 #include "utility/sync_util.h"
21 #include "engine-controller/task_spec.h"
22 #include "engine-controller/task_spec_internal.h"
23 #include "engine-controller/param_spec_internal.h"
24 #include <stdint.h>
25 #ifndef EXPORT_API
26 #define EXPORT_API __attribute__ ((visibility("default")))
27 #endif
28
29 #ifndef SYNC_AGENT_LOG
30 #undef LOG_TAG
31 #define LOG_TAG "AF_EC"
32 #endif
33
34 static sync_agent_ec_task_spec_s *_task_spec_new_default_task_spec(sync_agent_ec_char * task_name, sync_agent_ec_pointer post_task_func_usr_data, sync_agent_post_task_cb post_task_callback, sync_agent_ec_uint param_cnt,
35                                                                    sync_agent_ec_param_spec_s ** param_spec_array);
36 static void _task_spec_free_task_spec(sync_agent_ec_task_spec_s * task_spec);
37
38 static ec_child_tasks_info_t *_task_spec_new_child_tasks_info(sync_agent_ec_uint parent_param_cnt, sync_agent_ec_uint child_task_cnt, sync_agent_ec_task_spec_s ** child_task_array);
39
40 static void __task_spec_free_child_tasks_info(ec_child_tasks_info_t * child_task_info);
41
42 static ec_dynamic_container_task_specific_t *_task_spec_new_dynamic_container_task_specific(sync_agent_ec_uint parent_param_cnt, sync_agent_calculate_case_cb calculate_case_func, sync_agent_ec_uint case_cnt, sync_agent_ec_int * case_array,
43                                                                                             sync_agent_ec_uint * child_task_cnt_array, sync_agent_ec_task_spec_s *** child_task_array_per_case_array);
44
45 static void __task_spec_free_dynamic_container_task_specific(ec_dynamic_container_task_specific_t * pDynamic_container_task_specific);
46
47 static sync_agent_ec_param_spec_s *__task_spec_find_param_spec(sync_agent_ec_task_spec_s * task_spec, sync_agent_ec_int param_index);
48
49 static sync_agent_ec_error_e __task_spec_validate_container_task_spec(sync_agent_ec_task_spec_s * container_task_spec);
50
51 static sync_agent_ec_error_e _task_spec_validate_dynamic_container_task_spec(sync_agent_ec_task_spec_s * dynamic_container_task_spec);
52
53 static sync_agent_ec_error_e __task_spec_validate_param_index(sync_agent_ec_task_spec_s * task_spec, sync_agent_ec_int param_index);
54
55 static sync_agent_ec_error_e _task_spec_validate_set_control_flow_input_parameters(sync_agent_ec_task_spec_s * container_task_spec, sync_agent_ec_int from_task_index, sync_agent_ec_int to_task_index);
56
57 static sync_agent_ec_error_e _task_spec_validate_set_control_flow_input_parameters_on_dynamic_case(sync_agent_ec_int dynamic_case, sync_agent_ec_task_spec_s * dynamic_container_task_spec, sync_agent_ec_int from_task_index, sync_agent_ec_int to_task_index);
58
59 static sync_agent_ec_error_e _task_spec_validate_set_data_flow_input_parameters(sync_agent_ec_task_spec_s * container_task_spec, sync_agent_ec_int from_task_index, sync_agent_ec_int from_param_index, sync_agent_ec_int to_task_index,
60                                                                                 sync_agent_ec_int to_param_index);
61
62 static sync_agent_ec_error_e _task_spec_validate_set_data_flow_input_parameters_on_dynamic_case(sync_agent_ec_int dynamic_case, sync_agent_ec_task_spec_s * container_task_spec, sync_agent_ec_int from_task_index, sync_agent_ec_int from_param_index,
63                                                                                                 sync_agent_ec_int to_task_index, sync_agent_ec_int to_param_index);
64
65 ec_data_flow_edges_t *ec_data_flow_edges_new(sync_agent_ec_int parent_task_param_cnt, sync_agent_ec_uint child_task_cnt, sync_agent_ec_task_spec_s ** child_task_array)
66 {
67         _EXTERN_FUNC_ENTER;
68
69         sync_agent_ec_int i = 0;
70         sync_agent_ec_int total_param_cnt = 0;
71
72         ec_data_flow_edges_t *data_flow_edges = (ec_data_flow_edges_t *) calloc(1, sizeof(ec_data_flow_edges_t));
73         if (data_flow_edges == NULL) {
74                 goto error_part;
75         }
76
77         data_flow_edges->child_task_param_start_index_array = (sync_agent_ec_int *) calloc(child_task_cnt, sizeof(sync_agent_ec_int));
78         if (data_flow_edges->child_task_param_start_index_array == NULL) {
79                 goto error_part;
80         }
81
82         /* compute total param cnt and child_task_param_start_index_array */
83         total_param_cnt = parent_task_param_cnt;
84         for (i = 0; i < child_task_cnt; i++) {
85                 data_flow_edges->child_task_param_start_index_array[i] = total_param_cnt;
86                 total_param_cnt += child_task_array[i]->task_param_cnt;
87         }
88
89         data_flow_edges->child_task_cnt = child_task_cnt;
90         data_flow_edges->total_param_cnt = total_param_cnt;
91
92         sync_agent_ec_int *from_param_array = (sync_agent_ec_int *) malloc(total_param_cnt * sizeof(sync_agent_ec_int));
93         if (from_param_array == NULL) {
94                 goto error_part;
95         }
96
97         data_flow_edges->from_param_array = from_param_array;
98         for (i = 0; i < total_param_cnt; i++) {
99                 from_param_array[i] = -1;       /* when -1, no from_param exist */
100         }
101
102         _EXTERN_FUNC_EXIT;
103
104         return data_flow_edges;
105
106  error_part:
107         ec_data_flow_edges_free(data_flow_edges);
108         return NULL;
109 }
110
111 void ec_data_flow_edges_free(ec_data_flow_edges_t * data_flow_edges)
112 {
113         _EXTERN_FUNC_ENTER;
114
115         if (data_flow_edges != NULL) {
116                 if (data_flow_edges->child_task_param_start_index_array != NULL) {
117                         free(data_flow_edges->child_task_param_start_index_array);
118                 }
119
120                 if (data_flow_edges->from_param_array != NULL) {
121                         free(data_flow_edges->from_param_array);
122                 }
123
124                 free(data_flow_edges);
125         }
126
127         _EXTERN_FUNC_EXIT;
128 }
129
130 sync_agent_ec_int ec_data_flow_edges_compute_internal_index(ec_data_flow_edges_t * data_flow_edges, sync_agent_ec_int task_index, sync_agent_ec_int param_index)
131 {
132         _EXTERN_FUNC_ENTER;
133
134         sync_agent_ec_int *child_task_param_start_index_array = data_flow_edges->child_task_param_start_index_array;
135
136         if (task_index == -1) {
137                 _EXTERN_FUNC_EXIT;
138                 return param_index;
139         } else {
140                 _EXTERN_FUNC_EXIT;
141                 return param_index + child_task_param_start_index_array[task_index];
142         }
143 }
144
145 sync_agent_ec_boolean ec_data_flow_edges_compute_task_index_and_param_index(ec_data_flow_edges_t * data_flow_edges, sync_agent_ec_int internal_index, sync_agent_ec_int * pTask_index, sync_agent_ec_int * pParam_index)
146 {
147         _EXTERN_FUNC_ENTER;
148
149         retvm_if(data_flow_edges == NULL, false, "ec_data_flow_edges_t is NULL !!");
150
151         sync_agent_ec_boolean valid_internal_index = false;
152         sync_agent_ec_int task_index = -1;
153         sync_agent_ec_int param_index = -1;
154         sync_agent_ec_int i = 0;
155
156         if (internal_index >= 0 && internal_index < data_flow_edges->total_param_cnt) {
157                 valid_internal_index = true;
158
159                 for (i = 0; i < data_flow_edges->child_task_cnt; i++) {
160                         if (internal_index < data_flow_edges->child_task_param_start_index_array[i]) {
161                                 task_index = i - 1;
162
163                                 if (i == 0) {
164                                         param_index = internal_index;
165                                 } else {
166                                         param_index = internal_index - data_flow_edges->child_task_param_start_index_array[i - 1];
167                                 }
168                                 break;
169                         }
170                 }
171
172                 if (i == data_flow_edges->child_task_cnt) {
173                         task_index = i - 1;
174                         param_index = internal_index - data_flow_edges->child_task_param_start_index_array[i - 1];
175                 }
176
177                 *pTask_index = task_index;
178                 *pParam_index = param_index;
179         }
180
181         _EXTERN_FUNC_EXIT;
182
183         return valid_internal_index;
184 }
185
186 sync_agent_ec_boolean ec_data_flow_edges_add_edge(ec_data_flow_edges_t * data_flow_edges, sync_agent_ec_int from_task_index, sync_agent_ec_int from_param_index, sync_agent_ec_int to_task_index, sync_agent_ec_int to_param_index)
187 {
188         _EXTERN_FUNC_ENTER;
189
190         sync_agent_ec_boolean success = false;
191
192         sync_agent_ec_int from_param_internal_index = ec_data_flow_edges_compute_internal_index(data_flow_edges, from_task_index, from_param_index);
193         sync_agent_ec_int to_param_internal_index = ec_data_flow_edges_compute_internal_index(data_flow_edges, to_task_index, to_param_index);
194
195         /* record edge */
196         if (data_flow_edges->from_param_array[to_param_internal_index] == -1) { /* -1 means no from param exist */
197                 success = true;
198                 data_flow_edges->from_param_array[to_param_internal_index] = from_param_internal_index;
199         }
200
201         _EXTERN_FUNC_EXIT;
202
203         return success;
204 }
205
206 /* TODO : make this function accessible by other operation file */
207 sync_agent_ec_boolean ec_data_flow_edges_get_from_param_info(ec_data_flow_edges_t * data_flow_edges, sync_agent_ec_int to_task_index, sync_agent_ec_int to_param_index, sync_agent_ec_int * from_task_index, sync_agent_ec_int * from_param_index)
208 {
209         _EXTERN_FUNC_ENTER;
210
211         sync_agent_ec_boolean from_part_exist = false;
212
213         sync_agent_ec_int to_internal_index = ec_data_flow_edges_compute_internal_index(data_flow_edges, to_task_index, to_param_index);
214         sync_agent_ec_int from_internal_index = data_flow_edges->from_param_array[to_internal_index];
215         if (from_internal_index != -1) {
216                 ec_data_flow_edges_compute_task_index_and_param_index(data_flow_edges, from_internal_index, from_task_index, from_param_index);
217                 from_part_exist = true;
218         }
219
220         _EXTERN_FUNC_EXIT;
221
222         return from_part_exist;
223 }
224
225 sync_agent_ec_task_spec_s *ec_get_child_task_spec_from_child_task_info(ec_child_tasks_info_t * child_tasks_info, sync_agent_ec_uint child_task_index)
226 {
227         _EXTERN_FUNC_ENTER;
228
229         retvm_if(child_tasks_info == NULL, NULL, "ec_child_tasks_info_t is NULL !!");
230
231         if ( ((unsigned int)0 <= child_task_index) && (child_task_index < child_tasks_info->child_task_cnt)) {
232                 _EXTERN_FUNC_EXIT;
233                 return child_tasks_info->child_task_array[child_task_index];
234         } else {
235                 return NULL;
236         }
237 }
238
239 sync_agent_ec_uint *ec_task_spec_duplicate_child_task_control_flow_in_degree(sync_agent_ec_task_spec_s * task_spec)
240 {
241         _EXTERN_FUNC_ENTER;
242
243         sync_agent_ec_uint *duplcated_child_task_control_flow_in_degree = NULL;
244
245         if (!ec_task_spec_is_container(task_spec)) {
246                 goto error_part;
247         }
248
249         ec_child_tasks_info_t *child_task_info = ec_task_spec_find_child_tasks_info(task_spec);
250
251         retvm_if(child_task_info == NULL, NULL, "ec_child_tasks_info_t is NULL !!");
252
253         sync_agent_ec_uint child_task_cnt = child_task_info->child_task_cnt;
254         sync_agent_ec_uint *child_task_control_flow_in_degree = child_task_info->child_task_control_flow_in_degree;
255
256         duplcated_child_task_control_flow_in_degree = (sync_agent_ec_uint *) malloc(child_task_cnt * sizeof(sync_agent_ec_uint));
257         if (duplcated_child_task_control_flow_in_degree == NULL) {
258                 goto error_part;
259         }
260
261         memcpy(duplcated_child_task_control_flow_in_degree, child_task_control_flow_in_degree, child_task_cnt * sizeof(sync_agent_ec_uint));
262
263         _EXTERN_FUNC_EXIT;
264
265         return duplcated_child_task_control_flow_in_degree;
266
267  error_part:
268
269         return NULL;
270 }
271
272 sync_agent_ec_uint *ec_task_spec_duplicate_child_task_control_flow_in_degree_on_dynamic_case(sync_agent_ec_task_spec_s * dynamic_task_spec, sync_agent_ec_int dynamic_case)
273 {
274         _EXTERN_FUNC_ENTER;
275
276         sync_agent_ec_uint *duplcated_child_task_control_flow_in_degree = NULL;
277
278         if (!ec_task_spec_is_dynamic_container(dynamic_task_spec)) {
279                 goto error_part;
280         }
281
282         sync_agent_ec_uint child_task_cnt;
283         sync_agent_ec_uint *child_task_control_flow_in_degree;
284
285         ec_child_tasks_info_t *child_task_info = ec_task_spec_find_case_specific_child_tasks_info(dynamic_task_spec, dynamic_case);
286         if (child_task_info != NULL) {
287                 child_task_cnt = child_task_info->child_task_cnt;
288                 child_task_control_flow_in_degree = child_task_info->child_task_control_flow_in_degree;
289         } else {
290                 goto error_part;
291         }
292
293         duplcated_child_task_control_flow_in_degree = (sync_agent_ec_uint *) malloc(child_task_cnt * sizeof(sync_agent_ec_uint));
294         if (duplcated_child_task_control_flow_in_degree == NULL) {
295                 goto error_part;
296         }
297
298         memcpy(duplcated_child_task_control_flow_in_degree, child_task_control_flow_in_degree, child_task_cnt * sizeof(sync_agent_ec_uint));
299
300         _EXTERN_FUNC_EXIT;
301
302         return duplcated_child_task_control_flow_in_degree;
303
304  error_part:
305
306         return NULL;
307 }
308
309 static sync_agent_ec_task_spec_s *_task_spec_new_default_task_spec(sync_agent_ec_char * task_name, sync_agent_ec_pointer post_task_func_usr_data, sync_agent_post_task_cb post_task_callback, sync_agent_ec_uint param_cnt,
310                                                                    sync_agent_ec_param_spec_s ** param_spec_array)
311 {
312         _INNER_FUNC_ENTER;
313
314         retvm_if(task_name == NULL, NULL, "sync_agent_ec_char is NULL !!");
315
316         int i = 0;
317         sync_agent_ec_task_spec_s *task = NULL;
318
319         /* TODO : input parameter validation */
320
321         task = (sync_agent_ec_task_spec_s *) calloc(1, sizeof(sync_agent_ec_task_spec_s));
322         if (task == NULL) {
323                 goto return_part;
324         }
325
326         task->task_name = strdup(task_name);
327         if (task->task_name == NULL) {
328                 goto error_part;
329         }
330
331         task->task_param_spec_array = (sync_agent_ec_param_spec_s **) calloc(param_cnt, sizeof(sync_agent_ec_param_spec_s *));
332         if (task->task_param_spec_array == NULL) {
333                 goto error_part;
334         }
335
336         task->task_param_cnt = param_cnt;
337         for (i = 0; i < param_cnt; i++) {
338                 task->task_param_spec_array[i] = ec_ref_param_spec(param_spec_array[i]);
339         }
340
341         task->usr_post_task_func_data = post_task_func_usr_data;
342         task->post_func = post_task_callback;
343         task->ref_count = 1;
344
345  return_part:
346         _INNER_FUNC_EXIT;
347         return task;
348
349  error_part:
350         _task_spec_free_task_spec(task);
351         return NULL;
352 }
353
354 static void _task_spec_free_task_spec(sync_agent_ec_task_spec_s * task_spec)
355 {
356         _INNER_FUNC_ENTER;
357
358         if (task_spec != NULL) {
359                 if (task_spec->task_name != NULL) {
360                         free(task_spec->task_name);
361                 }
362
363                 if (task_spec->task_param_cnt > 0) {
364                         int i = 0;
365                         for (i = 0; i < task_spec->task_param_cnt; i++) {
366                                 sync_agent_unref_param_spec(task_spec->task_param_spec_array[i]);
367                         }
368                 }
369
370                 /* TODO : child_parallel_task_list when container task */
371                 /* TODO : usr_task_data */
372
373                 free(task_spec);
374         }
375
376         _INNER_FUNC_EXIT;
377 }
378
379 static ec_child_tasks_info_t *_task_spec_new_child_tasks_info(sync_agent_ec_uint parent_param_cnt, sync_agent_ec_uint child_task_cnt, sync_agent_ec_task_spec_s ** child_task_array)
380 {
381         _INNER_FUNC_ENTER;
382
383         sync_agent_ec_uint i = 0;
384         ec_child_tasks_info_t *child_task_info = (ec_child_tasks_info_t *) calloc(1, sizeof(ec_child_tasks_info_t));
385         if (child_task_info == NULL) {
386                 _DEBUG_ERROR("CALLOC failed !!!");
387                 return NULL;
388         }
389
390         child_task_info->child_task_cnt = child_task_cnt;
391         child_task_info->child_task_array = (sync_agent_ec_task_spec_s **) calloc(child_task_cnt, sizeof(sync_agent_ec_task_spec_s *));
392         if (child_task_info->child_task_array == NULL) {
393                 goto error_part;
394         }
395
396         for (i = 0; i < child_task_cnt; i++) {
397                 child_task_info->child_task_array[i] = ec_task_spec_ref(child_task_array[i]);
398         }
399
400         child_task_info->child_task_control_flow_in_degree = (sync_agent_ec_uint *) calloc(child_task_cnt, sizeof(sync_agent_ec_uint));
401         if (child_task_info->child_task_control_flow_in_degree == NULL) {
402                 goto error_part;
403         }
404
405         child_task_info->control_edge_pool = ec_graph_edge_pool_new();
406         if (child_task_info->control_edge_pool == NULL) {
407                 goto error_part;
408         }
409
410         child_task_info->data_flow_edges = ec_data_flow_edges_new(parent_param_cnt, child_task_cnt, child_task_array);
411         if (child_task_info->data_flow_edges == NULL) {
412                 goto error_part;
413         }
414
415         _INNER_FUNC_EXIT;
416
417         return child_task_info;
418
419  error_part:
420         __task_spec_free_child_tasks_info(child_task_info);
421         return NULL;
422 }
423
424 static void __task_spec_free_child_tasks_info(ec_child_tasks_info_t * child_task_info)
425 {
426         _INNER_FUNC_ENTER;
427
428         if (child_task_info != NULL) {
429                 sync_agent_ec_uint cnt = child_task_info->child_task_cnt;
430                 sync_agent_ec_uint i = 0;
431
432                 if (child_task_info->data_flow_edges != NULL) {
433                         ec_data_flow_edges_free(child_task_info->data_flow_edges);
434                 }
435
436                 if (child_task_info->control_edge_pool != NULL) {
437                         ec_graph_edge_pool_free(child_task_info->control_edge_pool);
438                 }
439
440                 if (child_task_info->child_task_control_flow_in_degree != NULL) {
441                         free(child_task_info->child_task_control_flow_in_degree);
442                 }
443
444                 if (child_task_info->child_task_array != NULL) {
445                         for (i = 0; i < cnt; i++) {
446                                 ec_task_spec_unref(child_task_info->child_task_array[i]);
447                         }
448                         free(child_task_info->child_task_array);
449                 }
450
451                 free(child_task_info);
452         }
453
454         _INNER_FUNC_EXIT;
455 }
456
457 static ec_dynamic_container_task_specific_t *_task_spec_new_dynamic_container_task_specific(sync_agent_ec_uint parent_param_cnt, sync_agent_calculate_case_cb calculate_case_func, sync_agent_ec_uint case_cnt, sync_agent_ec_int * case_array,
458                                                                                             sync_agent_ec_uint * child_task_cnt_array, sync_agent_ec_task_spec_s *** child_task_array_per_case_array)
459 {
460         _INNER_FUNC_ENTER;
461
462         retvm_if(case_array == NULL, NULL, "sync_agent_ec_int is NULL !!");
463         retvm_if(child_task_cnt_array == NULL, NULL, "sync_agent_ec_uint is NULL !!");
464
465         sync_agent_ec_uint i = 0;
466         ec_dynamic_container_task_specific_t *pDynamic_container_task_specific = (ec_dynamic_container_task_specific_t *) calloc(1, sizeof(ec_dynamic_container_task_specific_t));
467         if (pDynamic_container_task_specific == NULL) {
468                 _DEBUG_ERROR("CALLOC failed !!!");
469                 return NULL;
470         }
471
472         pDynamic_container_task_specific->calculate_case_func = calculate_case_func;
473         pDynamic_container_task_specific->case_cnt = case_cnt;
474         pDynamic_container_task_specific->case_array = (sync_agent_ec_int *) malloc(case_cnt * sizeof(sync_agent_ec_int));
475         if (pDynamic_container_task_specific->case_array == NULL) {
476                 goto error_part;
477         }
478         memcpy(pDynamic_container_task_specific->case_array, case_array, case_cnt * sizeof(sync_agent_ec_int));
479
480         pDynamic_container_task_specific->case_specific_child_task_info_array = (ec_child_tasks_info_t **) calloc(case_cnt, sizeof(ec_child_tasks_info_t *));
481         if (pDynamic_container_task_specific->case_specific_child_task_info_array == NULL) {
482                 goto error_part;
483         }
484
485         for (i = 0; i < case_cnt; i++) {
486                 pDynamic_container_task_specific->case_specific_child_task_info_array[i] = _task_spec_new_child_tasks_info(parent_param_cnt, child_task_cnt_array[i], child_task_array_per_case_array[i]);
487                 if (pDynamic_container_task_specific->case_specific_child_task_info_array[i] == NULL) {
488                         goto error_part;
489                 }
490         }
491
492         _INNER_FUNC_EXIT;
493
494         return pDynamic_container_task_specific;
495
496  error_part:
497         __task_spec_free_dynamic_container_task_specific(pDynamic_container_task_specific);
498         return NULL;
499 }
500
501 static void __task_spec_free_dynamic_container_task_specific(ec_dynamic_container_task_specific_t * pDynamic_container_task_specific)
502 {
503         _INNER_FUNC_ENTER;
504
505         if (pDynamic_container_task_specific != NULL) {
506                 if (pDynamic_container_task_specific->case_array != NULL)
507                         free(pDynamic_container_task_specific->case_array);
508                 int i = 0;
509                 if (pDynamic_container_task_specific->case_specific_child_task_info_array != NULL && pDynamic_container_task_specific->case_cnt > 0) {
510                         for (i = 0; i < pDynamic_container_task_specific->case_cnt; i++) {
511                                 __task_spec_free_child_tasks_info(pDynamic_container_task_specific->case_specific_child_task_info_array[i]);
512                         }
513                         free(pDynamic_container_task_specific->case_specific_child_task_info_array);
514                 }
515                 free(pDynamic_container_task_specific);
516         }
517
518         _INNER_FUNC_EXIT;
519 }
520
521 ec_child_tasks_info_t *ec_task_spec_find_child_tasks_info(sync_agent_ec_task_spec_s * parent_container_task_spec)
522 {
523         _EXTERN_FUNC_ENTER;
524
525         retvm_if(parent_container_task_spec == NULL, NULL, "sync_agent_ec_task_spec_s is NULL !!");
526
527         _EXTERN_FUNC_EXIT;
528
529         return parent_container_task_spec->u.container_task_specific;
530 }
531
532 ec_child_tasks_info_t *ec_task_spec_find_case_specific_child_tasks_info(sync_agent_ec_task_spec_s * parent_dynamic_task_spec, sync_agent_ec_int dynamic_case)
533 {
534         _EXTERN_FUNC_ENTER;
535
536         retvm_if(parent_dynamic_task_spec == NULL, NULL, "sync_agent_ec_task_spec_s is NULL !!");
537
538         ec_child_tasks_info_t *child_task_info = NULL;
539
540         ec_dynamic_container_task_specific_t *dynmaic_container_task_specific = parent_dynamic_task_spec->u.dynmaic_container_task_specific;
541         sync_agent_ec_uint case_cnt = dynmaic_container_task_specific->case_cnt;
542         sync_agent_ec_int *case_array = dynmaic_container_task_specific->case_array;
543         ec_child_tasks_info_t **case_specific_child_task_info_array = dynmaic_container_task_specific->case_specific_child_task_info_array;
544
545         sync_agent_ec_uint i = 0;
546         for (i = 0; i < case_cnt; i++) {
547                 if (case_array[i] == dynamic_case) {
548                         child_task_info = case_specific_child_task_info_array[i];
549                         break;
550                 }
551         }
552
553         _EXTERN_FUNC_EXIT;
554
555         return child_task_info;
556 }
557
558 static sync_agent_ec_param_spec_s *__task_spec_find_param_spec(sync_agent_ec_task_spec_s * task_spec, sync_agent_ec_int param_index)
559 {
560         _INNER_FUNC_ENTER;
561
562         retvm_if(task_spec == NULL, NULL, "sync_agent_ec_task_spec_s is NULL !!");
563
564         sync_agent_ec_param_spec_s *pParam_spec = NULL;
565         sync_agent_ec_int param_cnt = ec_task_spec_get_param_cnt(task_spec);
566         sync_agent_ec_param_spec_s **param_spec_array = task_spec->task_param_spec_array;
567
568         if (param_index >= 0 && param_index < param_cnt) {
569                 pParam_spec = param_spec_array[param_index];
570         }
571
572         _INNER_FUNC_EXIT;
573
574         return pParam_spec;
575 }
576
577 static sync_agent_ec_error_e __task_spec_validate_container_task_spec(sync_agent_ec_task_spec_s * container_task_spec)
578 {
579         _INNER_FUNC_ENTER;
580
581         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
582         if (container_task_spec == NULL) {
583                 err = SYNC_AGENT_EC_INVALID_TASK;
584                 goto error_part;
585         }
586
587         if (container_task_spec->task_type != EC_TASK_CONTAINER) {
588                 if (container_task_spec->task_type == EC_TASK_SIMPLE || container_task_spec->task_type == EC_TASK_DYNAMIC_CONTAINER) {
589                         err = SYNC_AGENT_EC_MUST_USE_CONTAINER_TASK;
590                 } else {
591                         err = SYNC_AGENT_EC_INVALID_TASK;
592                 }
593                 goto error_part;
594         }
595
596         _INNER_FUNC_EXIT;
597
598  error_part:
599         return err;
600 }
601
602 static sync_agent_ec_error_e _task_spec_validate_dynamic_container_task_spec(sync_agent_ec_task_spec_s * dynamic_container_task_spec)
603 {
604         _INNER_FUNC_ENTER;
605
606         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
607         if (dynamic_container_task_spec == NULL) {
608                 err = SYNC_AGENT_EC_INVALID_TASK;
609                 goto error_part;
610         }
611
612         if (dynamic_container_task_spec->task_type != EC_TASK_DYNAMIC_CONTAINER) {
613                 if (dynamic_container_task_spec->task_type == EC_TASK_SIMPLE || dynamic_container_task_spec->task_type == EC_TASK_CONTAINER) {
614                         err = SYNC_AGENT_EC_MUST_USE_DYNAMIC_CONTAINER_TASK;
615                 } else {
616                         err = SYNC_AGENT_EC_INVALID_TASK;
617                 }
618                 goto error_part;
619         }
620
621         _INNER_FUNC_EXIT;
622
623  error_part:
624         return err;
625 }
626
627 /*
628 sync_agent_ec_error_e task_spec_attach_queuing_rule_spec(sync_agent_ec_task_spec_s* spec, sync_agent_ec_queuing_rule_spec_s* queuing_rule_spec)
629 {
630         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
631         GSList* listnode = g_slist_find(spec->queuing_rule_spec_list, queuing_rule_spec);
632         if (listnode != NULL) {
633                 err = SYNC_AGENT_EC_DUPLICATE_QUEUING_RULE_SPEC;
634                 goto error_part;
635         }
636
637         spec->queuing_rule_spec_list = g_slist_prepend(spec->queuing_rule_spec_list, ec_ref_queuing_rule_spec(queuing_rule_spec));
638
639         error_part:
640         return err;
641 }
642 */
643
644 sync_agent_ec_error_e ec_task_spec_valididate_child_task_index(sync_agent_ec_task_spec_s * container_task_spec, sync_agent_ec_int child_task_index)
645 {
646         _EXTERN_FUNC_ENTER;
647
648         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
649
650         sync_agent_ec_task_spec_s *child_task_spec = ec_task_spec_get_child_task_spec(container_task_spec, child_task_index);
651         if (child_task_spec == NULL) {
652                 err = SYNC_AGENT_EC_INVALID_CHILD_TASK_INDEX;
653         }
654
655         _EXTERN_FUNC_EXIT;
656
657         return err;
658 }
659
660 sync_agent_ec_error_e ec_task_spec_valididate_child_task_index_on_dynamic_case(sync_agent_ec_int dynamic_case, sync_agent_ec_task_spec_s * dynamic_container_task_spec, sync_agent_ec_int child_task_index)
661 {
662         _EXTERN_FUNC_ENTER;
663
664         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
665
666         sync_agent_ec_task_spec_s *child_task_spec = ec_task_spec_get_child_task_spec_on_dynamic_case(dynamic_case,
667                                                                                                       dynamic_container_task_spec,
668                                                                                                       child_task_index);
669         if (child_task_spec == NULL) {
670                 err = SYNC_AGENT_EC_INVALID_CHILD_TASK_INDEX;
671         }
672
673         _EXTERN_FUNC_EXIT;
674
675         return err;
676 }
677
678 static sync_agent_ec_error_e __task_spec_validate_param_index(sync_agent_ec_task_spec_s * task_spec, sync_agent_ec_int param_index)
679 {
680         _INNER_FUNC_ENTER;
681
682         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
683
684         sync_agent_ec_param_spec_s *pParam_spec = __task_spec_find_param_spec(task_spec, param_index);
685         if (pParam_spec == NULL) {
686                 err = SYNC_AGENT_EC_INVALID_PARAM_INDEX;
687         }
688
689         _INNER_FUNC_EXIT;
690
691         return err;
692 }
693
694 static sync_agent_ec_error_e _task_spec_validate_set_control_flow_input_parameters(sync_agent_ec_task_spec_s * container_task_spec, sync_agent_ec_int from_task_index, sync_agent_ec_int to_task_index)
695 {
696         _INNER_FUNC_ENTER;
697
698         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
699
700         err = __task_spec_validate_container_task_spec(container_task_spec);
701         if (err != SYNC_AGENT_EC_OK) {
702                 goto error_part;
703         }
704
705         err = ec_task_spec_valididate_child_task_index(container_task_spec, from_task_index);
706         if (err != SYNC_AGENT_EC_OK) {
707                 goto error_part;
708         }
709
710         err = ec_task_spec_valididate_child_task_index(container_task_spec, to_task_index);
711
712         _INNER_FUNC_EXIT;
713
714  error_part:
715         return err;
716 }
717
718 static sync_agent_ec_error_e _task_spec_validate_set_control_flow_input_parameters_on_dynamic_case(sync_agent_ec_int dynamic_case, sync_agent_ec_task_spec_s * dynamic_container_task_spec, sync_agent_ec_int from_task_index, sync_agent_ec_int to_task_index)
719 {
720         _INNER_FUNC_ENTER;
721
722         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
723
724         err = _task_spec_validate_dynamic_container_task_spec(dynamic_container_task_spec);
725         if (err != SYNC_AGENT_EC_OK) {
726                 goto error_part;
727         }
728
729         err = ec_task_spec_valididate_child_task_index_on_dynamic_case(dynamic_case, dynamic_container_task_spec, from_task_index);
730         if (err != SYNC_AGENT_EC_OK) {
731                 goto error_part;
732         }
733
734         err = ec_task_spec_valididate_child_task_index_on_dynamic_case(dynamic_case, dynamic_container_task_spec, to_task_index);
735
736         _INNER_FUNC_EXIT;
737
738  error_part:
739         return err;
740 }
741
742 static sync_agent_ec_error_e _task_spec_validate_set_data_flow_input_parameters(sync_agent_ec_task_spec_s * container_task_spec, sync_agent_ec_int from_task_index, sync_agent_ec_int from_param_index, sync_agent_ec_int to_task_index,
743                                                                                 sync_agent_ec_int to_param_index)
744 {
745         _INNER_FUNC_ENTER;
746
747         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
748
749         err = __task_spec_validate_container_task_spec(container_task_spec);
750         if (err != SYNC_AGENT_EC_OK) {
751                 goto error_part;
752         }
753
754         sync_agent_ec_task_spec_s *pFrom_task_spec = NULL;
755         sync_agent_ec_task_spec_s *pTo_task_spec = NULL;
756         if (from_task_index != -1) {
757                 err = ec_task_spec_valididate_child_task_index(container_task_spec, from_task_index);
758                 if (err != SYNC_AGENT_EC_OK) {
759                         goto error_part;
760                 }
761
762                 pFrom_task_spec = ec_task_spec_get_child_task_spec(container_task_spec, from_task_index);
763         } else {
764                 pFrom_task_spec = container_task_spec;
765         }
766         err = __task_spec_validate_param_index(pFrom_task_spec, from_param_index);
767         if (err != SYNC_AGENT_EC_OK) {
768                 goto error_part;
769         }
770
771         if (to_task_index != -1) {
772                 err = ec_task_spec_valididate_child_task_index(container_task_spec, to_task_index);
773                 if (err != SYNC_AGENT_EC_OK) {
774                         goto error_part;
775                 }
776
777                 pTo_task_spec = ec_task_spec_get_child_task_spec(container_task_spec, to_task_index);
778         } else {
779                 pTo_task_spec = container_task_spec;
780         }
781         err = __task_spec_validate_param_index(pTo_task_spec, to_param_index);
782
783         _INNER_FUNC_EXIT;
784
785  error_part:
786         return err;
787 }
788
789 static sync_agent_ec_error_e _task_spec_validate_set_data_flow_input_parameters_on_dynamic_case(sync_agent_ec_int dynamic_case, sync_agent_ec_task_spec_s * dynamic_container_task_spec, sync_agent_ec_int from_task_index, sync_agent_ec_int from_param_index,
790                                                                                                 sync_agent_ec_int to_task_index, sync_agent_ec_int to_param_index)
791 {
792         _INNER_FUNC_ENTER;
793
794         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
795
796         err = _task_spec_validate_dynamic_container_task_spec(dynamic_container_task_spec);
797         if (err != SYNC_AGENT_EC_OK) {
798                 goto error_part;
799         }
800
801         sync_agent_ec_task_spec_s *pFrom_task_spec = NULL;
802         sync_agent_ec_task_spec_s *pTo_task_spec = NULL;
803         if (from_task_index != -1) {
804                 err = ec_task_spec_valididate_child_task_index_on_dynamic_case(dynamic_case, dynamic_container_task_spec, from_task_index);
805                 if (err != SYNC_AGENT_EC_OK) {
806                         goto error_part;
807                 }
808
809                 pFrom_task_spec = ec_task_spec_get_child_task_spec_on_dynamic_case(dynamic_case, dynamic_container_task_spec, from_task_index);
810         } else {
811                 pFrom_task_spec = dynamic_container_task_spec;
812         }
813         err = __task_spec_validate_param_index(pFrom_task_spec, from_param_index);
814         if (err != SYNC_AGENT_EC_OK) {
815                 goto error_part;
816         }
817
818         if (to_task_index != -1) {
819                 err = ec_task_spec_valididate_child_task_index_on_dynamic_case(dynamic_case, dynamic_container_task_spec, to_task_index);
820                 if (err != SYNC_AGENT_EC_OK) {
821                         goto error_part;
822                 }
823
824                 pTo_task_spec = ec_task_spec_get_child_task_spec_on_dynamic_case(dynamic_case, dynamic_container_task_spec, to_task_index);
825         } else {
826                 pTo_task_spec = dynamic_container_task_spec;
827         }
828         err = __task_spec_validate_param_index(pTo_task_spec, to_param_index);
829
830         _INNER_FUNC_EXIT;
831
832  error_part:
833         return err;
834 }
835
836 EXPORT_API sync_agent_ec_task_spec_s *sync_agent_alloc_simple_task_spec(sync_agent_ec_char * task_name, sync_agent_task_process_cb task_process, sync_agent_ec_pointer post_task_func_usr_data, sync_agent_post_task_cb post_task_callback,
837                                                                         sync_agent_ec_uint param_cnt, sync_agent_ec_param_spec_s ** param_spec_array)
838 {
839         _EXTERN_FUNC_ENTER;
840
841         sync_agent_ec_task_spec_s *task = NULL;
842
843         task = _task_spec_new_default_task_spec(task_name, post_task_func_usr_data, post_task_callback, param_cnt, param_spec_array);
844
845         if (task == NULL) {
846                 return NULL;
847         }
848         task->task_type = EC_TASK_SIMPLE;
849         task->u.task_process = task_process;
850
851         _EXTERN_FUNC_EXIT;
852
853         return task;
854 }
855
856 sync_agent_ec_task_spec_s *ec_task_spec_ref(sync_agent_ec_task_spec_s * task_spec)
857 {
858         _EXTERN_FUNC_ENTER;
859
860         if (task_spec == NULL) {
861                 return NULL;
862         }
863
864         g_atomic_int_inc(&(task_spec->ref_count));
865
866         _EXTERN_FUNC_EXIT;
867
868         return task_spec;
869 }
870
871 void ec_task_spec_unref(sync_agent_ec_task_spec_s * task_spec)
872 {
873         _EXTERN_FUNC_ENTER;
874
875         if (task_spec == NULL) {
876                 return;
877         }
878
879         if (g_atomic_int_dec_and_test(&(task_spec->ref_count))) {
880                 _task_spec_free_task_spec(task_spec);
881         }
882
883         _EXTERN_FUNC_EXIT;
884 }
885
886 sync_agent_ec_boolean ec_task_spec_is_same(sync_agent_ec_task_spec_s * task_spec1, sync_agent_ec_task_spec_s * task_spec2)
887 {
888         _EXTERN_FUNC_ENTER;
889
890         if (task_spec1 == task_spec2) {
891                 _EXTERN_FUNC_EXIT;
892                 return true;
893         }
894         _EXTERN_FUNC_EXIT;
895         return false;
896 }
897
898 sync_agent_ec_boolean ec_task_spec_is_simple(sync_agent_ec_task_spec_s * task_spec)
899 {
900         _EXTERN_FUNC_ENTER;
901
902         if (task_spec == NULL) {
903                 _DEBUG_INFO("task_spec == NULL\n");
904                 return false;
905         }
906
907         if (task_spec->task_type == EC_TASK_SIMPLE) {
908                 _EXTERN_FUNC_EXIT;
909                 return true;
910         } else {
911                 _EXTERN_FUNC_EXIT;
912                 return false;
913         }
914 }
915
916 sync_agent_ec_boolean ec_task_spec_is_container(sync_agent_ec_task_spec_s * task_spec)
917 {
918         _EXTERN_FUNC_ENTER;
919
920         if (task_spec == NULL) {
921                 _DEBUG_INFO("task_spec == NULL\n");
922                 return false;
923         }
924
925         if (task_spec->task_type == EC_TASK_CONTAINER) {
926                 _EXTERN_FUNC_EXIT;
927                 return true;
928         } else {
929                 _EXTERN_FUNC_EXIT;
930                 return false;
931         }
932 }
933
934 sync_agent_ec_boolean ec_task_spec_is_dynamic_container(sync_agent_ec_task_spec_s * task_spec)
935 {
936         _EXTERN_FUNC_ENTER;
937
938         if (task_spec == NULL) {
939                 _DEBUG_INFO("task_spec == NULL\n");
940                 return false;
941         }
942
943         if (task_spec->task_type == EC_TASK_DYNAMIC_CONTAINER) {
944                 _EXTERN_FUNC_EXIT;
945                 return true;
946         } else {
947                 _EXTERN_FUNC_EXIT;
948                 return false;
949         }
950 }
951
952 sync_agent_ec_uint ec_task_spec_get_child_task_cnt(sync_agent_ec_task_spec_s * task_spec)
953 {
954         _EXTERN_FUNC_ENTER;
955
956         if (ec_task_spec_is_container(task_spec)) {
957                 _EXTERN_FUNC_EXIT;
958                 return task_spec->u.container_task_specific->child_task_cnt;
959         } else {
960                 _EXTERN_FUNC_EXIT;
961                 return 0;
962         }
963 }
964
965 sync_agent_ec_task_spec_s *ec_task_spec_get_child_task_spec(sync_agent_ec_task_spec_s * parent_task_spec, sync_agent_ec_int child_task_index)
966 {
967         _EXTERN_FUNC_ENTER;
968
969         sync_agent_ec_task_spec_s *child_task_spec = NULL;
970
971         ec_child_tasks_info_t *child_task_info = ec_task_spec_find_child_tasks_info(parent_task_spec);
972
973         retvm_if(child_task_info == NULL, NULL, "ec_child_tasks_info_t is NULL !!");
974
975         child_task_spec = ec_get_child_task_spec_from_child_task_info(child_task_info, child_task_index);
976
977         _EXTERN_FUNC_EXIT;
978
979         return child_task_spec;
980 }
981
982 sync_agent_ec_uint ec_task_spec_get_child_task_cnt_on_dynamic_case(sync_agent_ec_task_spec_s * dynamic_task_spec, sync_agent_ec_int dynamic_case)
983 {
984         _EXTERN_FUNC_ENTER;
985
986         if (ec_task_spec_is_dynamic_container(dynamic_task_spec)) {
987                 ec_child_tasks_info_t *child_task_info = ec_task_spec_find_case_specific_child_tasks_info(dynamic_task_spec, dynamic_case);
988                 if (child_task_info != NULL) {
989                         _EXTERN_FUNC_EXIT;
990                         return child_task_info->child_task_cnt;
991                 } else {
992                         _EXTERN_FUNC_EXIT;
993                         return 0;
994                 }
995         } else {
996                 _EXTERN_FUNC_EXIT;
997                 return 0;
998         }
999 }
1000
1001 sync_agent_ec_task_spec_s *ec_task_spec_get_child_task_spec_on_dynamic_case(sync_agent_ec_int dynamic_case, sync_agent_ec_task_spec_s * parent_dynamic_task_spec, sync_agent_ec_int child_task_index)
1002 {
1003         _EXTERN_FUNC_ENTER;
1004
1005         sync_agent_ec_task_spec_s *child_task_spec = NULL;
1006
1007         sync_agent_ec_error_e ec_error = _task_spec_validate_dynamic_container_task_spec(parent_dynamic_task_spec);
1008         if (ec_error != SYNC_AGENT_EC_OK) {
1009                 goto error_part;
1010         }
1011
1012         ec_child_tasks_info_t *child_task_info = ec_task_spec_find_case_specific_child_tasks_info(parent_dynamic_task_spec, dynamic_case);
1013         child_task_spec = ec_get_child_task_spec_from_child_task_info(child_task_info, child_task_index);
1014
1015         _EXTERN_FUNC_EXIT;
1016
1017         return child_task_spec;
1018
1019  error_part:
1020         return NULL;
1021 }
1022
1023 sync_agent_ec_int ec_task_spec_get_param_cnt(sync_agent_ec_task_spec_s * task_spec)
1024 {
1025         _EXTERN_FUNC_ENTER;
1026
1027         _EXTERN_FUNC_EXIT;
1028
1029         return task_spec->task_param_cnt;
1030 }
1031
1032 sync_agent_calculate_case_cb ec_task_spec_get_calculate_case_callback_func(sync_agent_ec_task_spec_s * dynamic_container_task_spec)
1033 {
1034         _EXTERN_FUNC_ENTER;
1035
1036         retvm_if(dynamic_container_task_spec == NULL, NULL, "sync_agent_ec_task_spec_s is NULL !!");
1037
1038         _EXTERN_FUNC_EXIT;
1039
1040         return dynamic_container_task_spec->u.dynmaic_container_task_specific->calculate_case_func;
1041 }
1042
1043 sync_agent_ec_boolean ec_task_spec_get_output_param_info(sync_agent_ec_task_spec_s * task_spec, sync_agent_ec_int * output_param_cnt, sync_agent_ec_int ** output_param_index_array)
1044 {
1045         _EXTERN_FUNC_ENTER;
1046
1047         if (task_spec == NULL || output_param_cnt == NULL || output_param_index_array == NULL) {
1048                 goto error_part;
1049         }
1050
1051         sync_agent_ec_int i = 0;
1052         sync_agent_ec_int param_cnt = ec_task_spec_get_param_cnt(task_spec);
1053         sync_agent_ec_param_spec_s **task_param_spec_array = task_spec->task_param_spec_array;
1054
1055         sync_agent_ec_int output_param_count = 0;
1056         sync_agent_ec_int *output_param_index_arr = NULL;
1057         output_param_index_arr = (sync_agent_ec_int *) calloc(param_cnt, sizeof(sync_agent_ec_int));
1058         if (output_param_index_arr == NULL) {
1059                 goto error_part;
1060         }
1061
1062         sync_agent_ec_param_spec_s *pParam_spec = NULL;
1063         for (i = 0; i < param_cnt; i++) {
1064                 pParam_spec = task_param_spec_array[i];
1065                 if (ec_param_is_output_flag_on(pParam_spec->flags)) {
1066                         output_param_index_arr[output_param_count] = i;
1067                         output_param_count++;
1068                 }
1069         }
1070
1071         *output_param_cnt = output_param_count;
1072         *output_param_index_array = output_param_index_arr;
1073
1074         _EXTERN_FUNC_EXIT;
1075
1076         return true;
1077
1078  error_part:
1079         return false;
1080 }
1081
1082 sync_agent_ec_task_spec_s *ec_alloc_container_task_spec_outline(sync_agent_ec_char * task_name, sync_agent_ec_pointer usr_post_task_func_data, sync_agent_post_task_cb post_func, sync_agent_ec_uint param_cnt, sync_agent_ec_param_spec_s ** param_spec_array,
1083                                                                 sync_agent_ec_uint child_task_cnt, sync_agent_ec_task_spec_s ** child_task_array)
1084 {
1085         _EXTERN_FUNC_ENTER;
1086
1087         sync_agent_ec_task_spec_s *task_spec = NULL;
1088
1089         task_spec = _task_spec_new_default_task_spec(task_name, usr_post_task_func_data, post_func, param_cnt, param_spec_array);
1090
1091         if (task_spec == NULL) {
1092                 return NULL;
1093         }
1094         task_spec->task_type = EC_TASK_CONTAINER;
1095         task_spec->u.container_task_specific = _task_spec_new_child_tasks_info(param_cnt, child_task_cnt, child_task_array);
1096
1097         if (task_spec->u.container_task_specific == NULL) {
1098                 goto error_part;
1099         }
1100
1101         _EXTERN_FUNC_EXIT;
1102
1103         return task_spec;
1104
1105  error_part:
1106         _task_spec_free_task_spec(task_spec);
1107         return NULL;
1108 }
1109
1110 sync_agent_ec_error_e ec_set_data_flow(sync_agent_ec_task_spec_s * container_task_spec, sync_agent_ec_int from_task_index, sync_agent_ec_int from_param_index, sync_agent_ec_int to_task_index, sync_agent_ec_int to_param_index)
1111 {
1112         _EXTERN_FUNC_ENTER;
1113
1114         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
1115
1116         /* validation */
1117         err = _task_spec_validate_set_data_flow_input_parameters(container_task_spec, from_task_index, from_param_index, to_task_index, to_param_index);
1118         if (err != SYNC_AGENT_EC_OK) {
1119                 goto error_part;
1120         }
1121
1122         if (from_task_index != -1 && to_task_index != -1) {
1123                 /* add control flow */
1124                 err = ec_set_control_flow(container_task_spec, from_task_index, to_task_index);
1125                 if (err != SYNC_AGENT_EC_OK) {
1126                         goto error_part;
1127                 }
1128         }
1129
1130         /* add data flow */
1131         ec_child_tasks_info_t *child_task_info = ec_task_spec_find_child_tasks_info(container_task_spec);
1132         ec_data_flow_edges_t *data_flow_edges = child_task_info->data_flow_edges;
1133         if (!ec_data_flow_edges_add_edge(data_flow_edges, from_task_index, from_param_index, to_task_index, to_param_index)) {
1134                 err = SYNC_AGENT_EC_DUPLICATE_DATA_FLOW_EDGE;
1135         }
1136
1137         _EXTERN_FUNC_EXIT;
1138
1139  error_part:
1140         return err;
1141 }
1142
1143 sync_agent_ec_error_e ec_set_data_flow_on_dynamic_case(sync_agent_ec_int dynamic_case, sync_agent_ec_task_spec_s * dynamic_container_task_spec, sync_agent_ec_int from_task_index, sync_agent_ec_int from_param_index, sync_agent_ec_int to_task_index,
1144                                                        sync_agent_ec_int to_param_index)
1145 {
1146         _EXTERN_FUNC_ENTER;
1147
1148         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
1149
1150         /* validation */
1151         err = _task_spec_validate_set_data_flow_input_parameters_on_dynamic_case(dynamic_case, dynamic_container_task_spec, from_task_index, from_param_index, to_task_index, to_param_index);
1152         if (err != SYNC_AGENT_EC_OK) {
1153                 goto error_part;
1154         }
1155
1156         if (from_task_index != -1 && to_task_index != -1) {
1157                 /* add control flow */
1158                 err = ec_task_spec_set_control_flow_on_dynamic_case(dynamic_case, dynamic_container_task_spec, from_task_index, to_task_index);
1159                 if (err != SYNC_AGENT_EC_OK) {
1160                         goto error_part;
1161                 }
1162         }
1163
1164         /* add data flow */
1165         ec_data_flow_edges_t *data_flow_edges;
1166         ec_child_tasks_info_t *child_task_info = ec_task_spec_find_case_specific_child_tasks_info(dynamic_container_task_spec, dynamic_case);
1167         if (child_task_info != NULL) {
1168                 data_flow_edges = child_task_info->data_flow_edges;
1169         } else {
1170                 err = SYNC_AGENT_EC_INVALID_TASK;
1171                 goto error_part;
1172         }
1173         if (!ec_data_flow_edges_add_edge(data_flow_edges, from_task_index, from_param_index, to_task_index, to_param_index)) {
1174                 err = SYNC_AGENT_EC_DUPLICATE_DATA_FLOW_EDGE;
1175         }
1176
1177         _EXTERN_FUNC_EXIT;
1178
1179  error_part:
1180         return err;
1181 }
1182
1183 sync_agent_ec_error_e ec_set_control_flow(sync_agent_ec_task_spec_s * container_task_spec, sync_agent_ec_int from_task_index, sync_agent_ec_int to_task_index)
1184 {
1185         _EXTERN_FUNC_ENTER;
1186
1187         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
1188
1189         err = _task_spec_validate_set_control_flow_input_parameters(container_task_spec, from_task_index, to_task_index);
1190         if (err != SYNC_AGENT_EC_OK) {
1191                 goto error_part;
1192         }
1193
1194         ec_child_tasks_info_t *child_task_info = ec_task_spec_find_child_tasks_info(container_task_spec);
1195         ec_graph_edge_pool_t *control_edge_pool = child_task_info->control_edge_pool;
1196         sync_agent_ec_uint *control_flow_in_degree_array = child_task_info->child_task_control_flow_in_degree;
1197
1198         /* add edge and in_degree count */
1199         if (ec_graph_edge_pool_add_edge(control_edge_pool, (sync_agent_ec_constpointer) ((intptr_t)from_task_index), (sync_agent_ec_constpointer) ((intptr_t)to_task_index))) {
1200                 control_flow_in_degree_array[to_task_index]++;
1201         }
1202
1203         _EXTERN_FUNC_EXIT;
1204
1205  error_part:
1206         return err;
1207 }
1208
1209 sync_agent_ec_error_e ec_task_spec_set_control_flow_on_dynamic_case(sync_agent_ec_int dynamic_case, sync_agent_ec_task_spec_s * dynamic_container_task_spec, sync_agent_ec_int from_task_index, sync_agent_ec_int to_task_index)
1210 {
1211         _EXTERN_FUNC_ENTER;
1212
1213         sync_agent_ec_error_e err = SYNC_AGENT_EC_OK;
1214
1215         err = _task_spec_validate_set_control_flow_input_parameters_on_dynamic_case(dynamic_case, dynamic_container_task_spec, from_task_index, to_task_index);
1216         if (err != SYNC_AGENT_EC_OK) {
1217                 goto error_part;
1218         }
1219
1220         ec_graph_edge_pool_t *control_edge_pool;
1221         ec_child_tasks_info_t *child_task_info = ec_task_spec_find_case_specific_child_tasks_info(dynamic_container_task_spec, dynamic_case);
1222         if (child_task_info != NULL) {
1223                 control_edge_pool = child_task_info->control_edge_pool;
1224         } else {
1225                 err = SYNC_AGENT_EC_INVALID_TASK;
1226                 goto error_part;
1227         }
1228         sync_agent_ec_uint *control_flow_in_degree_array = child_task_info->child_task_control_flow_in_degree;
1229
1230         /* add edge and in_degree count */
1231         if (ec_graph_edge_pool_add_edge(control_edge_pool, (sync_agent_ec_constpointer) ((intptr_t)from_task_index), (sync_agent_ec_constpointer) ((intptr_t)to_task_index))) {
1232                 control_flow_in_degree_array[to_task_index]++;
1233         }
1234
1235         _EXTERN_FUNC_EXIT;
1236
1237  error_part:
1238         return err;
1239 }
1240
1241 sync_agent_ec_task_spec_s *ec_alloc_dynamic_container_task_spec_outline(sync_agent_ec_char * task_name, sync_agent_ec_pointer usr_post_task_func_data, sync_agent_post_task_cb post_func, sync_agent_ec_uint param_cnt,
1242                                                                         sync_agent_ec_param_spec_s ** param_spec_array, sync_agent_calculate_case_cb calculate_case_func, sync_agent_ec_uint case_cnt, sync_agent_ec_int * case_array,
1243                                                                         sync_agent_ec_uint * child_task_cnt_array, sync_agent_ec_task_spec_s *** child_task_array_per_case_array)
1244 {
1245         _EXTERN_FUNC_ENTER;
1246
1247         sync_agent_ec_task_spec_s *task_spec = NULL;
1248
1249         task_spec = _task_spec_new_default_task_spec(task_name, usr_post_task_func_data, post_func, param_cnt, param_spec_array);
1250
1251         if (task_spec == NULL) {
1252                 return NULL;
1253         }
1254         task_spec->task_type = EC_TASK_DYNAMIC_CONTAINER;
1255         task_spec->u.dynmaic_container_task_specific = _task_spec_new_dynamic_container_task_specific(param_cnt, calculate_case_func, case_cnt, case_array, child_task_cnt_array, child_task_array_per_case_array);
1256
1257         if (task_spec->u.dynmaic_container_task_specific == NULL) {
1258                 goto error_part;
1259         }
1260
1261         _EXTERN_FUNC_EXIT;
1262
1263         return task_spec;
1264
1265  error_part:
1266         _task_spec_free_task_spec(task_spec);
1267         return NULL;
1268 }