Tizen 2.0 Release
[platform/core/messaging/email-service.git] / email-core / email-core-task-manager.c
1 /*\r
2 *  email-service\r
3 *\r
4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. All rights reserved.\r
5 *\r
6 * Contact: Kyuho Jo <kyuho.jo@samsung.com>, Sunghyun Kwon <sh0701.kwon@samsung.com>\r
7 *\r
8 * Licensed under the Apache License, Version 2.0 (the "License");\r
9 * you may not use this file except in compliance with the License.\r
10 * You may obtain a copy of the License at\r
11 *\r
12 * http://www.apache.org/licenses/LICENSE-2.0\r
13 *\r
14 * Unless required by applicable law or agreed to in writing, software\r
15 * distributed under the License is distributed on an "AS IS" BASIS,\r
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
17 * See the License for the specific language governing permissions and\r
18 * limitations under the License.\r
19 *\r
20 */\r
21 \r
22 /*\r
23  * email-core-task-manager.c\r
24  *\r
25  *  Created on: 2012. 11. 1.\r
26  *      Author: kyuho.jo@samsung.com\r
27  */\r
28 \r
29 #include <stdio.h>\r
30 #include <stdlib.h>\r
31 #include <pthread.h>\r
32 #include <dbus/dbus.h>\r
33 \r
34 #include "email-internal-types.h"\r
35 #include "email-utilities.h"\r
36 #include "email-core-tasks.h"\r
37 #include "email-core-task-manager.h"\r
38 #include "email-core-signal.h"\r
39 #include "email-core-global.h"\r
40 #include "email-core-utils.h"\r
41 #include "email-debug-log.h"\r
42 \r
43 /* TODO : implement a function for removing a task from task pool */\r
44 /* TODO : after fetching a task from DB, update status of the task. */\r
45 \r
46 \r
47 #define REGISTER_TASK_BINDER(TASK_NAME) emcore_register_task_handler(TASK_NAME, task_handler_##TASK_NAME, email_encode_task_parameter_##TASK_NAME, email_decode_task_parameter_##TASK_NAME)\r
48 \r
49 /*- variables - begin --------------------------------------------------------*/\r
50 static pthread_cond_t  _task_available_signal   = PTHREAD_COND_INITIALIZER;\r
51 static pthread_mutex_t _task_available_lock     = PTHREAD_MUTEX_INITIALIZER;\r
52 static pthread_mutex_t _task_manager_loop_lock  = PTHREAD_MUTEX_INITIALIZER;\r
53 static pthread_mutex_t _active_task_pool_lock   = PTHREAD_MUTEX_INITIALIZER;\r
54 \r
55 static email_active_task_t _active_task_pool[MAX_ACTIVE_TASK];\r
56 static thread_t            _thread_task_manager_loop;\r
57 static int                 _task_manager_loop_availability = 1;\r
58 /*- variables - end ----------------------------------------------------------*/\r
59 static int emcore_insert_task_to_active_task_pool(int input_task_slot_index, int input_task_id, email_task_type_t input_task_type, thread_t input_thread_id);\r
60 static int emcore_remove_task_from_active_task_pool(int input_task_id);\r
61 static int emcore_find_available_slot_in_active_task_pool(int *result_index);\r
62 static int emcore_update_task_status_on_task_table(int input_task_id, email_task_status_type_t task_status);\r
63 static int emcore_get_task_handler_reference(email_task_type_t input_task_type, email_task_handler_t **output_task_handler);\r
64 \r
65 /*- task handlers helpers - begin --------------------------------------------*/\r
66 static int emcore_initialize_task_handler(email_task_t *input_task)\r
67 {\r
68         EM_DEBUG_FUNC_BEGIN("input_task [%p]", input_task);\r
69         int err = EMAIL_ERROR_NONE;\r
70 \r
71         if(input_task == NULL) {\r
72                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");\r
73                 err = EMAIL_ERROR_INVALID_PARAM;\r
74                 goto FINISH_OFF;\r
75         }\r
76 \r
77         /* insert task to _active_task_pool */\r
78         emcore_insert_task_to_active_task_pool(input_task->active_task_id\r
79                         , input_task->task_id\r
80                         , input_task->task_type\r
81                         , THREAD_SELF());\r
82 \r
83         /* send notification for 'task start */\r
84         if( (err = emcore_send_task_status_signal(input_task->task_type, input_task->task_id, EMAIL_TASK_STATUS_STARTED, EMAIL_ERROR_NONE, 0)) != EMAIL_ERROR_NONE) {\r
85                 EM_DEBUG_EXCEPTION("emcore_send_task_status_signal failed [%d]", err);\r
86                 goto FINISH_OFF;\r
87         }\r
88 \r
89 FINISH_OFF:\r
90 \r
91         EM_DEBUG_FUNC_END("err [%d]", err);\r
92         return err;\r
93 }\r
94 \r
95 static int emcore_finalize_task_handler(email_task_t *input_task, int input_error_code)\r
96 {\r
97         EM_DEBUG_FUNC_BEGIN("input_task [%p] input_error_code [%d]",input_task ,input_error_code);\r
98         int err = EMAIL_ERROR_NONE;\r
99         email_task_status_type_t task_status = EMAIL_TASK_STATUS_FINISHED;\r
100 \r
101         if(input_task == NULL) {\r
102                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");\r
103                 err = EMAIL_ERROR_INVALID_PARAM;\r
104                 goto FINISH_OFF;\r
105         }\r
106 \r
107         if(input_error_code != EMAIL_ERROR_NONE) {\r
108                 task_status = EMAIL_TASK_STATUS_FAILED;\r
109         }\r
110 \r
111         /* remove task from task table */\r
112         if( (err = emcore_remove_task_from_task_table(input_task->task_id)) != EMAIL_ERROR_NONE) {\r
113                 EM_DEBUG_EXCEPTION("emcore_remove_task_from_active_task_pool failed [%d]", err);\r
114                 goto FINISH_OFF;\r
115         }\r
116 \r
117         /* remove task id from active task id array */\r
118         if( (err = emcore_remove_task_from_active_task_pool(input_task->task_id)) != EMAIL_ERROR_NONE) {\r
119                 EM_DEBUG_EXCEPTION("emcore_remove_task_from_active_task_pool failed [%d]", err);\r
120                 goto FINISH_OFF;\r
121         }\r
122 \r
123         /* send signal for 'task finish or failure */\r
124         if( (err = emcore_send_task_status_signal(input_task->task_type, input_task->task_id, task_status, input_error_code, 0)) != EMAIL_ERROR_NONE) {\r
125                 EM_DEBUG_EXCEPTION("emcore_send_task_status_signal failed [%d]", err);\r
126                 goto FINISH_OFF;\r
127         }\r
128 \r
129         ENTER_CRITICAL_SECTION(_task_available_lock);\r
130         WAKE_CONDITION_VARIABLE(_task_available_signal);\r
131         LEAVE_CRITICAL_SECTION(_task_available_lock);\r
132 \r
133 FINISH_OFF:\r
134         EM_DEBUG_FUNC_END("err [%d]", err);\r
135         return err;\r
136 }\r
137 \r
138 void* emcore_default_task_handler(void *intput_param)\r
139 {\r
140         EM_DEBUG_FUNC_BEGIN("intput_param [%p]", intput_param);\r
141         int err = EMAIL_ERROR_NONE;\r
142         email_task_t *task = intput_param;\r
143         email_task_handler_t *task_handler = NULL;\r
144         void *decoded_task_parameter = NULL;\r
145 \r
146         if((err = emcore_initialize_task_handler(task)) != EMAIL_ERROR_NONE) {\r
147                 EM_DEBUG_EXCEPTION("emcore_initialize_task_handler failed. [%d]", err);\r
148                 goto FINISH_OFF;\r
149         }\r
150 \r
151         /* create a thread to do this task */\r
152         if((err = emcore_get_task_handler_reference(task->task_type, &task_handler)) != EMAIL_ERROR_NONE) {\r
153                 EM_DEBUG_LOG("emcore_get_task_handler_reference returns [%d]", err);\r
154         }\r
155         else {\r
156                 /* Decode parameter */\r
157                 emcore_decode_task_parameter(task->task_type, task->task_parameter, task->task_parameter_length, &decoded_task_parameter);\r
158                 task_handler->task_handler_function(decoded_task_parameter);\r
159         }\r
160 \r
161 FINISH_OFF:\r
162         emcore_finalize_task_handler(task, err);\r
163 \r
164         if(task) {\r
165                 EM_SAFE_FREE(task->task_parameter);\r
166                 EM_SAFE_FREE(task);\r
167         }\r
168 \r
169         EM_SAFE_FREE(decoded_task_parameter);\r
170 \r
171         EM_DEBUG_FUNC_END("err [%d]", err);\r
172         return NULL;\r
173 }\r
174 /*- task handlers helpers - end   --------------------------------------------*/\r
175 \r
176 int                   _task_handler_array_size;\r
177 email_task_handler_t **_task_handler_array;\r
178 \r
179 static int emcore_register_task_handler(email_task_type_t input_task_type, void* (*input_task_handler)(void *), int (*input_task_parameter_encoder)(void*,char**,int*), int (*input_task_parameter_decoder)(char*,int,void**))\r
180 {\r
181         EM_DEBUG_FUNC_BEGIN("input_task_type [%d] input_task_handler [%p] input_task_parameter_encoder [%p] input_task_parameter_decoder [%p]", input_task_type, input_task_handler, input_task_parameter_encoder, input_task_parameter_decoder);\r
182         int err = EMAIL_ERROR_NONE;\r
183         email_task_handler_t *new_task_handler = NULL;\r
184 \r
185         new_task_handler = malloc(sizeof(email_task_handler_t));\r
186 \r
187         if (new_task_handler == NULL) {\r
188                 err = EMAIL_ERROR_OUT_OF_MEMORY;\r
189                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_OUT_OF_MEMORY");\r
190                 goto FINISH_OFF;\r
191         }\r
192 \r
193         new_task_handler->task_type              = input_task_type;\r
194         new_task_handler->task_handler_function  = input_task_handler;\r
195         new_task_handler->task_parameter_encoder = input_task_parameter_encoder;\r
196         new_task_handler->task_parameter_decoder = input_task_parameter_decoder;\r
197 \r
198         _task_handler_array_size++;\r
199 \r
200         if (_task_handler_array) {\r
201                 _task_handler_array = realloc(_task_handler_array, sizeof(email_task_handler_t*) * _task_handler_array_size);\r
202         }\r
203         else {\r
204                 _task_handler_array = malloc(sizeof(email_task_handler_t*) * _task_handler_array_size);\r
205         }\r
206 \r
207         if (_task_handler_array == NULL) {\r
208                 err = EMAIL_ERROR_OUT_OF_MEMORY;\r
209                 goto FINISH_OFF;\r
210         }\r
211 \r
212         _task_handler_array[_task_handler_array_size - 1] = new_task_handler;\r
213 \r
214 FINISH_OFF:\r
215 \r
216         EM_DEBUG_FUNC_END("err [%d]", err);\r
217         return err;\r
218 }\r
219 \r
220 \r
221 INTERNAL_FUNC int emcore_init_task_handler_array()\r
222 {\r
223         EM_DEBUG_FUNC_BEGIN();\r
224 \r
225         if (_task_handler_array == NULL) {\r
226                 _task_handler_array      = NULL;\r
227                 _task_handler_array_size = 0;\r
228 \r
229                 REGISTER_TASK_BINDER(EMAIL_ASYNC_TASK_MOVE_MAILS_TO_MAILBOX_OF_ANOTHER_ACCOUNT);\r
230                 REGISTER_TASK_BINDER(EMAIL_ASYNC_TASK_DELETE_MAILBOX_EX);\r
231                 REGISTER_TASK_BINDER(EMAIL_ASYNC_TASK_SEND_MAIL_WITH_DOWNLOADING_ATTACHMENT_OF_ORIGINAL_MAIL);\r
232         }\r
233 \r
234         EM_DEBUG_FUNC_END();\r
235         return EMAIL_ERROR_NONE;\r
236 }\r
237 \r
238 INTERNAL_FUNC int emcore_free_task_handler_array()\r
239 {\r
240         EM_DEBUG_FUNC_BEGIN();\r
241 \r
242         int i = 0;\r
243 \r
244         for(i = 0; i < _task_handler_array_size; i++) {\r
245                 free(_task_handler_array[i]);\r
246         }\r
247 \r
248         free(_task_handler_array);\r
249         _task_handler_array      = NULL;\r
250         _task_handler_array_size = 0;\r
251 \r
252         EM_DEBUG_FUNC_END();\r
253         return EMAIL_ERROR_NONE;\r
254 }\r
255 \r
256 static int emcore_get_task_handler_reference(email_task_type_t input_task_type, email_task_handler_t **output_task_handler)\r
257 {\r
258         EM_DEBUG_FUNC_BEGIN("input_task_type [%d] output_task_handler [%p]", input_task_type, output_task_handler);\r
259         int i = 0;\r
260         int err = EMAIL_ERROR_NONE;\r
261 \r
262         if (output_task_handler == NULL) {\r
263                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");\r
264                 err = EMAIL_ERROR_INVALID_PARAM;\r
265                 goto FINISH_OFF;\r
266         }\r
267 \r
268         *output_task_handler = NULL;\r
269         for (i = 0; i < _task_handler_array_size; i++) {\r
270                 if (_task_handler_array[i]->task_type == input_task_type) {\r
271                         *output_task_handler = _task_handler_array[i];\r
272                         break;\r
273                 }\r
274         }\r
275 \r
276         if (*output_task_handler == NULL) {\r
277                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_TASK_BINDER_NOT_FOUND");\r
278                 err = EMAIL_ERROR_TASK_BINDER_NOT_FOUND;\r
279                 goto FINISH_OFF;\r
280         }\r
281 \r
282 FINISH_OFF:\r
283         EM_DEBUG_FUNC_END("err [%d]", err);\r
284         return err;\r
285 }\r
286 \r
287 INTERNAL_FUNC int emcore_encode_task_parameter(email_task_type_t input_task_type, void *input_task_parameter_struct, char **output_byte_stream, int *output_stream_size)\r
288 {\r
289         EM_DEBUG_FUNC_BEGIN("input_task_type [%d] input_task_parameter_struct [%p] output_byte_stream [%p] output_stream_size [%p]", input_task_type, input_task_parameter_struct, output_byte_stream, output_stream_size);\r
290         int err = EMAIL_ERROR_NONE;\r
291         email_task_handler_t *task_handler = NULL;\r
292         int (*task_parameter_encoder)(void*, char**, int*);\r
293 \r
294         if (input_task_parameter_struct == NULL || output_byte_stream == NULL || output_stream_size == NULL) {\r
295                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");\r
296                 err = EMAIL_ERROR_INVALID_PARAM;\r
297                 goto FINISH_OFF;\r
298         }\r
299 \r
300         if ((err = emcore_get_task_handler_reference(input_task_type, &task_handler)) != EMAIL_ERROR_NONE) {\r
301                 EM_DEBUG_EXCEPTION("emcore_get_task_handler_reference failed [%d]", err);\r
302                 goto FINISH_OFF;\r
303         }\r
304 \r
305         task_parameter_encoder = task_handler->task_parameter_encoder;\r
306 \r
307         if ((err = task_parameter_encoder(input_task_parameter_struct, output_byte_stream, output_stream_size)) != EMAIL_ERROR_NONE) {\r
308                 EM_DEBUG_EXCEPTION("task_parameter_encoder failed [%d]", err);\r
309                 goto FINISH_OFF;\r
310         }\r
311 \r
312 FINISH_OFF:\r
313         EM_DEBUG_FUNC_END("err [%d]", err);\r
314         return err;\r
315 }\r
316 \r
317 INTERNAL_FUNC int emcore_decode_task_parameter(email_task_type_t input_task_type, char *input_byte_stream, int input_stream_size, void **output_task_parameter_struct)\r
318 {\r
319         EM_DEBUG_FUNC_BEGIN("input_task_type [%d] input_byte_stream [%p] input_stream_size [%d] output_task_parameter_struct [%p]", input_task_type, input_byte_stream, input_stream_size, output_task_parameter_struct);\r
320         int err = EMAIL_ERROR_NONE;\r
321         email_task_handler_t *task_handler = NULL;\r
322         int (*task_parameter_decoder)(char*, int, void**);\r
323 \r
324         if (input_byte_stream == NULL || output_task_parameter_struct == NULL) {\r
325                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");\r
326                 err = EMAIL_ERROR_INVALID_PARAM;\r
327                 goto FINISH_OFF;\r
328         }\r
329 \r
330         if ((err = emcore_get_task_handler_reference(input_task_type, &task_handler)) != EMAIL_ERROR_NONE) {\r
331                 EM_DEBUG_EXCEPTION("emcore_get_task_handler_reference failed [%d]", err);\r
332                 goto FINISH_OFF;\r
333         }\r
334 \r
335         task_parameter_decoder = task_handler->task_parameter_decoder;\r
336 \r
337         if ((err = task_parameter_decoder(input_byte_stream, input_stream_size, output_task_parameter_struct)) != EMAIL_ERROR_NONE) {\r
338                 EM_DEBUG_EXCEPTION("task_parameter_decoder failed [%d]", err);\r
339                 goto FINISH_OFF;\r
340         }\r
341 \r
342 FINISH_OFF:\r
343         EM_DEBUG_FUNC_END("err [%d]", err);\r
344         return err;\r
345 }\r
346 \r
347 int emcore_fetch_task_from_task_pool(email_task_t **output_task)\r
348 {\r
349         EM_DEBUG_FUNC_BEGIN("output_task [%p]", output_task);\r
350         int err = EMAIL_ERROR_NONE;\r
351         int output_task_count;\r
352 \r
353         if((err = emstorage_query_task("WHERE task_status == 1", " ORDER BY date_time ASC, task_priority ASC LIMIT 0, 1", output_task, &output_task_count)) != EMAIL_ERROR_NONE) {\r
354                 EM_DEBUG_EXCEPTION("emstorage_query_task failed [%d]", err);\r
355                 goto FINISH_OFF;\r
356         }\r
357 \r
358 FINISH_OFF:\r
359 \r
360         EM_DEBUG_FUNC_END("err [%d]", err);\r
361         return err;\r
362 }\r
363 \r
364 \r
365 /*-Task manager loop - begin -------------------------------------------------------------*/\r
366 \r
367 \r
368 static int emcore_insert_task_to_active_task_pool(int input_task_slot_index, int input_task_id, email_task_type_t input_task_type, thread_t input_thread_id)\r
369 {\r
370         EM_DEBUG_FUNC_BEGIN("input_task_slot_index [%d] input_task_id [%d] input_task_type [%d] input_thread_id [%d]", input_task_slot_index, input_task_id, input_task_type, input_thread_id);\r
371         int err = EMAIL_ERROR_NONE;\r
372 \r
373         ENTER_CRITICAL_SECTION(_active_task_pool_lock);\r
374         _active_task_pool[input_task_slot_index].task_id    = input_task_id;\r
375         _active_task_pool[input_task_slot_index].task_type  = input_task_type;\r
376         _active_task_pool[input_task_slot_index].thread_id  = input_thread_id;\r
377         LEAVE_CRITICAL_SECTION(_active_task_pool_lock);\r
378 \r
379         EM_DEBUG_LOG("_active_task_pool[%d].task_id [%d]", input_task_slot_index, _active_task_pool[input_task_slot_index].task_id);\r
380 \r
381         EM_DEBUG_FUNC_END("err [%d]", err);\r
382         return err;\r
383 }\r
384 \r
385 static int emcore_remove_task_from_active_task_pool(int input_task_id)\r
386 {\r
387         EM_DEBUG_FUNC_BEGIN(" input_task_id [%d]", input_task_id);\r
388         int err = EMAIL_ERROR_NONE;\r
389         int i = 0;\r
390 \r
391         ENTER_CRITICAL_SECTION(_active_task_pool_lock);\r
392         for(i = 0; i < MAX_ACTIVE_TASK; i++) {\r
393                 if(_active_task_pool[i].task_id == input_task_id) {\r
394                         _active_task_pool[i].task_id    = 0;\r
395                         _active_task_pool[i].task_type  = 0;\r
396                         _active_task_pool[i].thread_id  = 0;\r
397                         break;\r
398                 }\r
399         }\r
400         LEAVE_CRITICAL_SECTION(_active_task_pool_lock);\r
401 \r
402         if(i >= MAX_ACTIVE_TASK) {\r
403                 EM_DEBUG_LOG("couldn't find proper task in active task pool [%d]", input_task_id);\r
404                 err = EMAIL_ERROR_TASK_NOT_FOUND;\r
405         }\r
406 \r
407         EM_DEBUG_FUNC_END("err [%d]", err);\r
408         return err;\r
409 }\r
410 \r
411 INTERNAL_FUNC int emcore_get_active_task_by_thread_id(thread_t input_thread_id, email_active_task_t **output_active_task)\r
412 {\r
413         EM_DEBUG_FUNC_BEGIN(" input_thread_id [%d] output_active_task [%p]", input_thread_id, output_active_task);\r
414         int err = EMAIL_ERROR_NONE;\r
415         int i = 0;\r
416 \r
417         if (output_active_task == NULL) {\r
418                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");\r
419                 err = EMAIL_ERROR_INVALID_PARAM;\r
420                 goto FINISH_OFF;\r
421         }\r
422 \r
423         for(i = 0; i < MAX_ACTIVE_TASK; i++) {\r
424                 if(_active_task_pool[i].thread_id == input_thread_id) {\r
425                         *output_active_task = _active_task_pool + i;\r
426                         break;\r
427                 }\r
428         }\r
429 \r
430         if(i >= MAX_ACTIVE_TASK) {\r
431                 EM_DEBUG_LOG("couldn't find proper task in active task pool [%d]", input_thread_id);\r
432                 err = EMAIL_ERROR_TASK_NOT_FOUND;\r
433         }\r
434 \r
435 FINISH_OFF:\r
436 \r
437         EM_DEBUG_FUNC_END("err [%d]", err);\r
438         return err;\r
439 }\r
440 \r
441 \r
442 static int emcore_find_available_slot_in_active_task_pool(int *result_index)\r
443 {\r
444         EM_DEBUG_FUNC_BEGIN("result_index [%p]", result_index);\r
445         int i = 0;\r
446         int err = EMAIL_ERROR_NONE;\r
447 \r
448         if (result_index == NULL) {\r
449                 EM_DEBUG_EXCEPTION("EMAIL_ERROR_INVALID_PARAM");\r
450                 err = EMAIL_ERROR_INVALID_PARAM;\r
451                 goto FINISH_OFF;\r
452         }\r
453 \r
454         ENTER_CRITICAL_SECTION(_active_task_pool_lock);\r
455         for(i = 0; i < MAX_ACTIVE_TASK; i++) {\r
456                 if(_active_task_pool[i].task_id == 0) {\r
457                         break;\r
458                 }\r
459         }\r
460 \r
461         if(i >= MAX_ACTIVE_TASK) {\r
462                 EM_DEBUG_EXCEPTION("There is no available task slot");\r
463                 err = EMAIL_NO_AVAILABLE_TASK_SLOT;\r
464         }\r
465         else {\r
466                 _active_task_pool[i].task_id = -1;\r
467                 *result_index = i;\r
468         }\r
469         LEAVE_CRITICAL_SECTION(_active_task_pool_lock);\r
470 \r
471 FINISH_OFF :\r
472         EM_DEBUG_FUNC_END("err [%d]", err);\r
473         return err;\r
474 }\r
475 \r
476 void* thread_func_task_manager_loop(void *arg)\r
477 {\r
478         EM_DEBUG_FUNC_BEGIN();\r
479         int err = EMAIL_ERROR_NONE;\r
480         int thread_error;\r
481         int available_slot_index = 0;\r
482         email_task_t *new_task = NULL;\r
483 \r
484         /* while loop */\r
485         while (_task_manager_loop_availability) {\r
486                 /* fetch task from DB */\r
487                 if( ((err = emcore_fetch_task_from_task_pool(&new_task)) == EMAIL_ERROR_NONE) &&\r
488                         ((err = emcore_find_available_slot_in_active_task_pool(&available_slot_index)) == EMAIL_ERROR_NONE)     ) {\r
489 \r
490                         /* update task status as STARTED */\r
491                         if((err = emcore_update_task_status_on_task_table(new_task->task_id, EMAIL_TASK_STATUS_STARTED)) != EMAIL_ERROR_NONE) {\r
492                                 EM_DEBUG_EXCEPTION("emcore_update_task_status_on_task_table failed [%d]", err);\r
493                         }\r
494                         new_task->active_task_id = available_slot_index;\r
495 \r
496                         /* create a thread to do this task */\r
497                         THREAD_CREATE(new_task->thread_id, emcore_default_task_handler, new_task, thread_error);\r
498 \r
499                         /* new_task and task_parameter will be free in task handler. */\r
500                         new_task     = NULL;\r
501 \r
502                 }\r
503                 else {\r
504                         /* If there is no task or no available slot, sleep until someone wake you up. */\r
505                         /* Wake up case 1 : by emcore_add_task_to_task_table */\r
506                         /* Wake up case 2 : when some task terminated */\r
507                         ENTER_CRITICAL_SECTION(_task_available_lock);\r
508                         SLEEP_CONDITION_VARIABLE(_task_available_signal, _task_available_lock);\r
509                         LEAVE_CRITICAL_SECTION(_task_available_lock);\r
510                         EM_DEBUG_LOG("thread_func_task_manager_loop wake up!");\r
511                 }\r
512         }\r
513 \r
514         EM_DEBUG_FUNC_END();\r
515         return NULL;\r
516 }\r
517 \r
518 INTERNAL_FUNC int emcore_start_task_manager_loop()\r
519 {\r
520     EM_DEBUG_FUNC_BEGIN();\r
521         int thread_error;\r
522         int err = EMAIL_ERROR_NONE;\r
523 \r
524         memset(&_active_task_pool, 0, sizeof(email_active_task_t) * MAX_ACTIVE_TASK);\r
525 \r
526         if (_thread_task_manager_loop) {\r
527                 EM_DEBUG_EXCEPTION("service thread is already running...");\r
528                 err = EMAIL_ERROR_ALREADY_INITIALIZED;\r
529                 goto FINISH_OFF;\r
530         }\r
531         emcore_init_task_handler_array();\r
532 \r
533         _task_manager_loop_availability = 10;\r
534 \r
535     /* create thread */\r
536         THREAD_CREATE(_thread_task_manager_loop, thread_func_task_manager_loop, NULL, thread_error);\r
537 \r
538         if (thread_error != 0) {\r
539         EM_DEBUG_EXCEPTION("cannot create thread [%d]", thread_error);\r
540         err = EMAIL_ERROR_SYSTEM_FAILURE;\r
541         goto FINISH_OFF;\r
542     }\r
543 \r
544 FINISH_OFF :\r
545         EM_DEBUG_FUNC_END("err [%d]", err);\r
546     return err;\r
547 }\r
548 \r
549 INTERNAL_FUNC int emcore_stop_task_manager_loop()\r
550 {\r
551     EM_DEBUG_FUNC_BEGIN();\r
552 \r
553     int err = EMAIL_ERROR_NONE;\r
554 \r
555     /* TODO : cancel tasks */\r
556 \r
557     /* stop event_data loop */\r
558     _task_manager_loop_availability = 0;\r
559 \r
560         ENTER_CRITICAL_SECTION(_task_manager_loop_lock);\r
561         WAKE_CONDITION_VARIABLE(_task_available_signal);\r
562         LEAVE_CRITICAL_SECTION(_task_manager_loop_lock);\r
563 \r
564         /* wait for thread finished */\r
565         THREAD_JOIN(_thread_task_manager_loop);\r
566 \r
567         _thread_task_manager_loop = 0;\r
568 \r
569         DELETE_CRITICAL_SECTION(_task_manager_loop_lock);\r
570         DELETE_CONDITION_VARIABLE(_task_available_signal);\r
571 \r
572         /* Free _active_task_pool */\r
573 \r
574 //FINISH_OFF :\r
575 \r
576         EM_DEBUG_FUNC_END("err [%d]", err);\r
577     return err;\r
578 }\r
579 \r
580 INTERNAL_FUNC int emcore_add_task_to_task_table(email_task_type_t input_task_type, email_task_priority_t input_task_priority, char *input_task_parameter, int input_task_parameter_length, int *output_task_id)\r
581 {\r
582         EM_DEBUG_FUNC_BEGIN("input_task_type [%d] input_task_priority [%d] input_task_parameter [%p] input_task_parameter_length [%d] output_task_id [%p]", input_task_type, input_task_priority, input_task_parameter, input_task_parameter_length, output_task_id);\r
583         int err = EMAIL_ERROR_NONE;\r
584 \r
585         if((err = emstorage_add_task(input_task_type, input_task_priority, input_task_parameter, input_task_parameter_length, false, output_task_id)) != EMAIL_ERROR_NONE) {\r
586                 EM_DEBUG_EXCEPTION("emstorage_add_task failed [%d]", err);\r
587                 goto FINISH_OFF;\r
588         }\r
589 \r
590         ENTER_CRITICAL_SECTION(_task_available_lock);\r
591         WAKE_CONDITION_VARIABLE(_task_available_signal);\r
592         LEAVE_CRITICAL_SECTION(_task_available_lock);\r
593 \r
594 FINISH_OFF:\r
595         EM_DEBUG_FUNC_END("err [%d]", err);\r
596         return err;\r
597 }\r
598 \r
599 INTERNAL_FUNC int emcore_remove_task_from_task_table(int input_task_id)\r
600 {\r
601         EM_DEBUG_FUNC_BEGIN("input_task_id [%d]", input_task_id);\r
602         int err = EMAIL_ERROR_NONE;\r
603 \r
604         if((err = emstorage_delete_task(input_task_id, true)) != EMAIL_ERROR_NONE) {\r
605                 EM_DEBUG_EXCEPTION("emstorage_delete_task failed [%d]", err);\r
606                 goto FINISH_OFF;\r
607         }\r
608 \r
609 FINISH_OFF:\r
610         EM_DEBUG_FUNC_END("err [%d]", err);\r
611         return err;\r
612 }\r
613 \r
614 static int emcore_update_task_status_on_task_table(int input_task_id, email_task_status_type_t task_status)\r
615 {\r
616         EM_DEBUG_FUNC_BEGIN("input_task_id [%d] task_status [%d]", input_task_id, task_status);\r
617         int err = EMAIL_ERROR_NONE;\r
618 \r
619         if((err = emstorage_update_task_status(input_task_id, task_status, true)) != EMAIL_ERROR_NONE) {\r
620                 EM_DEBUG_EXCEPTION("emstorage_update_task_status failed [%d]", err);\r
621                 goto FINISH_OFF;\r
622         }\r
623 \r
624 FINISH_OFF:\r
625         EM_DEBUG_FUNC_END("err [%d]", err);\r
626         return err;\r
627 }\r
628 \r
629 /*-Task manager loop - end-------------------------------------------------------------*/\r