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