modify mutex not to miss the signal while working alarm_main
[platform/core/pim/calendar-service.git] / server / cal_server_alarm.c
1 /*
2  * Calendar Service
3  *
4  * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdlib.h>
21 #include <sys/time.h>
22 #include <unistd.h>
23 #include <alarm.h>
24 #include <vconf.h>
25 #include <app.h>
26
27 #include "calendar.h"
28 #include "cal_typedef.h"
29 #include "cal_internal.h"
30 #include "cal_time.h"
31 #include "cal_inotify.h"
32 #include "cal_db_util.h"
33 #include "cal_db.h"
34 #include "cal_db_query.h"
35 #include "cal_server_service.h"
36 #include "cal_server_ondemand.h"
37 #include "cal_server_dbus.h"
38 #include "cal_server_alarm.h"
39
40 #define CAL_SERVER_ALARM_THREAD_NAME "cal_server_alarm"
41
42 GThread *_cal_server_alarm_thread = NULL;
43 GCond _cal_server_alarm_cond;
44 GMutex _cal_server_alarm_mutex;
45 static bool server_killed = false;
46 static bool signal_called = false;
47
48 struct _alarm_data_s {
49         int event_id;
50         long long int alert_utime; /* to compare */
51         int unit;
52         int tick;
53         int type; /* utime, localtime */
54         long long int time;
55         int record; /* todo, event */
56         char datetime[CAL_STR_SHORT_LEN32];
57         int system_type;
58 };
59
60 struct alarm_ud {
61         GList *alarm_list;
62 };
63
64 /* this api is necessary for repeat instance. */
65 static int cal_server_alarm_unset_alerted_alarmmgr_id(int alarm_id)
66 {
67         char query[CAL_DB_SQL_MAX_LEN] = {0};
68         int ret = 0;
69
70         ret = cal_db_util_begin_trans();
71         if (CALENDAR_ERROR_NONE != ret) {
72                 /* LCOV_EXCL_START */
73                 ERR("cal_db_util_begin_trans() Fail");
74                 return CALENDAR_ERROR_DB_FAILED;
75                 /* LCOV_EXCL_STOP */
76         }
77
78         DBG("alarm_id(%d)", alarm_id);
79
80         snprintf(query, sizeof(query), "UPDATE %s SET alarm_id = 0 WHERE alarm_id =%d ",
81                         CAL_TABLE_ALARM, alarm_id);
82         ret = cal_db_util_query_exec(query);
83         if (CALENDAR_ERROR_NONE != ret) {
84                 /* LCOV_EXCL_START */
85                 ERR("cal_db_util_query_exec() Fail(%d)", ret);
86                 SECURE("[%s]", query);
87                 cal_db_util_end_trans(false);
88                 return ret;
89                 /* LCOV_EXCL_STOP */
90         }
91         cal_db_util_end_trans(true);
92         return CALENDAR_ERROR_NONE;
93 }
94
95 static int _cal_server_alarm_clear_all_cb(alarm_id_t alarm_id, void *data)
96 {
97         int ret;
98
99         DBG("remove alarm id(%d)", alarm_id);
100         cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
101         ret = alarmmgr_remove_alarm(alarm_id);
102         if (ret != ALARMMGR_RESULT_SUCCESS) {
103                 /* LCOV_EXCL_START */
104                 ERR("alarmmgr_remove_alarm() Fail(ret:%d)", ret);
105                 return ret;
106                 /* LCOV_EXCL_STOP */
107         }
108         return CALENDAR_ERROR_NONE;
109 }
110
111 static int _cal_server_alarm_update_alarm_id(int alarm_id, int event_id, int tick, int unit)
112 {
113         char query[CAL_DB_SQL_MAX_LEN] = {0};
114         int ret = 0;
115
116         ret = cal_db_util_begin_trans();
117         if (CALENDAR_ERROR_NONE != ret) {
118                 /* LCOV_EXCL_START */
119                 ERR("cal_db_util_begin_trans() Fail");
120                 return CALENDAR_ERROR_DB_FAILED;
121                 /* LCOV_EXCL_STOP */
122         }
123
124         DBG("Update alarm_id(%d) in alarm table", alarm_id);
125         snprintf(query, sizeof(query), "UPDATE %s SET alarm_id =%d "
126                         "WHERE event_id =%d AND remind_tick =%d AND remind_tick_unit =%d",
127                         CAL_TABLE_ALARM, alarm_id, event_id, tick, unit);
128         ret = cal_db_util_query_exec(query);
129         if (CALENDAR_ERROR_NONE != ret) {
130                 /* LCOV_EXCL_START */
131                 ERR("cal_db_util_query_exec() Fail(%d)", ret);
132                 SECURE("[%s]", query);
133                 cal_db_util_end_trans(false);
134                 return ret;
135                 /* LCOV_EXCL_STOP */
136         }
137         cal_db_util_end_trans(true);
138         return CALENDAR_ERROR_NONE;
139 }
140
141 static long long int _get_event_alert_utime(const char *field, int event_id, time_t current)
142 {
143         int ret = 0;
144         char query[CAL_DB_SQL_MAX_LEN] = {0};
145         snprintf(query, sizeof(query), "SELECT %s FROM %s "
146                         "WHERE event_id=%d AND %s>%ld ORDER BY %s LIMIT 1",
147                         field, CAL_TABLE_UTIME_INSTANCE, event_id, field, current, field);
148
149         sqlite3_stmt *stmt = NULL;
150         ret = cal_db_util_query_prepare(query, &stmt);
151         if (CALENDAR_ERROR_NONE != ret) {
152                 /* LCOV_EXCL_START */
153                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
154                 SECURE("query[%s]", query);
155                 return ret;
156                 /* LCOV_EXCL_STOP */
157         }
158
159         long long int utime = 0;
160         if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
161                 utime = sqlite3_column_int(stmt, 0);
162
163         sqlite3_finalize(stmt);
164         return utime;
165 }
166
167 static int _get_event_alert_localtime(const char *field, int event_id, time_t current)
168 {
169         int ret = 0;
170         char query[CAL_DB_SQL_MAX_LEN] = {0};
171         struct tm st = {0};
172         tzset();
173         localtime_r(&current, &st);
174         time_t mod_current = timegm(&st);
175         snprintf(query, sizeof(query), "SELECT %s FROM %s "
176                         "WHERE event_id=%d AND strftime('%%s', %s)>%ld ORDER BY %s LIMIT 1",
177                         field, CAL_TABLE_LOCALTIME_INSTANCE, event_id, field, mod_current, field);
178
179         sqlite3_stmt *stmt = NULL;
180         ret = cal_db_util_query_prepare(query, &stmt);
181         if (CALENDAR_ERROR_NONE != ret) {
182                 /* LCOV_EXCL_START */
183                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
184                 SECURE("query[%s]", query);
185                 return ret;
186                 /* LCOV_EXCL_STOP */
187         }
188
189         const char *datetime = NULL;
190         if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
191                 datetime = (const char *)sqlite3_column_text(stmt, 0);
192
193         if (NULL == datetime || '\0' == *datetime) {
194                 /* LCOV_EXCL_START */
195                 ERR("Invalid datetime [%s]", datetime);
196                 sqlite3_finalize(stmt);
197                 return 0;
198                 /* LCOV_EXCL_STOP */
199         }
200
201         int y = 0, m = 0, d = 0;
202         int h = 0, n = 0, s = 0;
203         sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
204         sqlite3_finalize(stmt);
205
206         st.tm_year = y - 1900;
207         st.tm_mon = m - 1;
208         st.tm_mday = d;
209         st.tm_hour = h;
210         st.tm_min = n;
211         st.tm_sec = s;
212
213         return (long long int)mktime(&st);
214 }
215
216 static int64_t _get_todo_alert_utime(const char *field, int id, time_t now_t)
217 {
218         int ret = 0;
219         char query[CAL_DB_SQL_MAX_LEN] = {0};
220         snprintf(query, sizeof(query), "SELECT %s FROM "CAL_TABLE_SCHEDULE" "
221                         "WHERE id=%d AND %s>%ld ORDER BY %s LIMIT 1", field, id, field, now_t, field);
222
223         sqlite3_stmt *stmt = NULL;
224         ret = cal_db_util_query_prepare(query, &stmt);
225         if (CALENDAR_ERROR_NONE != ret) {
226                 /* LCOV_EXCL_START */
227                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
228                 SECURE("query[%s]", query);
229                 return ret;
230                 /* LCOV_EXCL_STOP */
231         }
232
233         int64_t utime = 0;
234         ret = cal_db_util_stmt_step(stmt);
235         switch (ret) {
236         case CAL_SQLITE_ROW:
237                 utime = (int64_t)sqlite3_column_int64(stmt, 0);
238                 break;
239                 /* LCOV_EXCL_START */
240         case SQLITE_DONE:
241                 ERR("No data");
242                 break;
243         default:
244                 ERR("Invalid return(%d)", ret);
245                 break;
246                 /* LCOV_EXCL_STOP */
247         }
248
249         sqlite3_finalize(stmt);
250         return utime;
251 }
252
253 static int _get_todo_alert_localtime(const char *field, int event_id, time_t current)
254 {
255         int ret = 0;
256         char query[CAL_DB_SQL_MAX_LEN] = {0};
257         struct tm st = {0};
258         tzset();
259         localtime_r(&current, &st);
260         time_t mod_current = timegm(&st);
261         snprintf(query, sizeof(query), "SELECT %s FROM %s "
262                         "WHERE id=%d AND strftime('%%s', %s)>%ld ORDER BY %s LIMIT 1",
263                         field, CAL_TABLE_SCHEDULE, event_id, field, mod_current, field);
264
265         sqlite3_stmt *stmt = NULL;
266         ret = cal_db_util_query_prepare(query, &stmt);
267         if (CALENDAR_ERROR_NONE != ret) {
268                 /* LCOV_EXCL_START */
269                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
270                 SECURE("query[%s]", query);
271                 return ret;
272                 /* LCOV_EXCL_STOP */
273         }
274
275         const char *datetime = NULL;
276         if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
277                 datetime = (const char *)sqlite3_column_text(stmt, 0);
278
279         if (NULL == datetime || '\0' == *datetime) {
280                 /* LCOV_EXCL_START */
281                 ERR("Invalid datetime [%s]", datetime);
282                 sqlite3_finalize(stmt);
283                 return 0;
284                 /* LCOV_EXCL_STOP */
285         }
286
287         int y = 0, m = 0, d = 0;
288         int h = 0, n = 0, s = 0;
289         sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
290         sqlite3_finalize(stmt);
291
292         st.tm_year = y - 1900;
293         st.tm_mon = m - 1;
294         st.tm_mday = d;
295         st.tm_hour = h;
296         st.tm_min = n;
297         st.tm_sec = s;
298
299         return (long long int)mktime(&st);
300 }
301 /*
302  * time(NULL) is not appropriate as parameter.
303  * 1 seconds could be flowed before calling function.(1 sec time diff)
304  * so, searching DB is neccessary to find alert time.
305  */
306 static int cal_server_alarm_get_alert_time(int alarm_id, time_t *tt_alert)
307 {
308         int ret = 0;
309         RETV_IF(NULL == tt_alert, CALENDAR_ERROR_INVALID_PARAMETER);
310
311         char query[CAL_DB_SQL_MAX_LEN] = {0};
312         snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, "
313                         "A.alarm_type, A.alarm_utime, A.alarm_datetime, B.type, B.dtstart_type, "
314                         "B.dtend_type FROM %s as A, %s as B ON A.event_id =B.id WHERE alarm_id =%d ",
315                         CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE, alarm_id);
316
317         sqlite3_stmt *stmt = NULL;
318         ret = cal_db_util_query_prepare(query, &stmt);
319         if (CALENDAR_ERROR_NONE != ret) {
320                 /* LCOV_EXCL_START */
321                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
322                 SECURE("query[%s]", query);
323                 return ret;
324                 /* LCOV_EXCL_STOP */
325         }
326
327         int event_id = 0;
328         int unit = 0;
329         int tick = 0;
330         int type = 0;
331         long long int utime = 0;
332         const char *datetime = NULL;
333         int record_type = 0;
334         int dtstart_type = 0;
335         int dtend_type = 0;
336         struct tm st = {0};
337
338         if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
339                 event_id = sqlite3_column_int(stmt, 0);
340                 unit = sqlite3_column_int(stmt, 1);
341                 tick = sqlite3_column_int(stmt, 2);
342                 type = sqlite3_column_int(stmt, 3);
343                 utime = sqlite3_column_int64(stmt, 4);
344                 datetime = (const char *)sqlite3_column_text(stmt, 5);
345                 record_type = sqlite3_column_int(stmt, 6);
346                 dtstart_type = sqlite3_column_int(stmt, 7);
347                 dtend_type = sqlite3_column_int(stmt, 8);
348         }
349
350         if (NULL == tt_alert) {
351                 /* LCOV_EXCL_START */
352                 ERR("Invalid parameter: tt_alert is NULL");
353                 sqlite3_finalize(stmt);
354                 return CALENDAR_ERROR_INVALID_PARAMETER;
355                 /* LCOV_EXCL_STOP */
356         }
357
358         if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == unit) {
359                 if (CALENDAR_TIME_UTIME == type) {
360                         *tt_alert = utime;
361                 } else {
362                         int y = 0, m = 0, d = 0;
363                         int h = 0, n = 0, s = 0;
364                         if (datetime) {
365                                 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
366
367                                 st.tm_year = y - 1900;
368                                 st.tm_mon = m - 1;
369                                 st.tm_mday = d;
370                                 st.tm_hour = h;
371                                 st.tm_min = n;
372                                 st.tm_sec = s;
373                                 *tt_alert = mktime(&st);
374                                 DBG("datetime[%s] to %02d:%02d:%02d (%d)", datetime, h, n, s, *tt_alert);
375                         }
376                 }
377                 sqlite3_finalize(stmt);
378                 return CALENDAR_ERROR_NONE;
379         }
380         sqlite3_finalize(stmt);
381
382         time_t current = time(NULL);
383         current += (tick * unit);
384         current -= 2; /* in case time passed */
385
386         switch (record_type) {
387         case CALENDAR_BOOK_TYPE_EVENT:
388                 switch (dtstart_type) {
389                 case CALENDAR_TIME_UTIME:
390                         utime = _get_event_alert_utime("dtstart_utime", event_id, current);
391                         break;
392
393                 case CALENDAR_TIME_LOCALTIME:
394                         utime = _get_event_alert_localtime("dtstart_datetime", event_id, current);
395                         break;
396                 }
397                 break;
398
399         case CALENDAR_BOOK_TYPE_TODO:
400                 switch (dtend_type) {
401                 case CALENDAR_TIME_UTIME:
402                         utime = _get_todo_alert_utime("dtend_utime", event_id, current);
403                         break;
404
405                 case CALENDAR_TIME_LOCALTIME:
406                         utime = _get_todo_alert_localtime("dtend_datetime", event_id, current);
407                         break;
408                 }
409                 break;
410         }
411         DBG("alert_time(%d) = utime(%lld) - (tick(%d) * unit(%d))", *tt_alert, utime, tick, unit);
412
413         *tt_alert = utime - (tick * unit);
414         return CALENDAR_ERROR_NONE;
415 }
416
417 /*
418  * bool get_all is
419  * true : to get all alarms including same time event.
420  * (ig. if 3 diffrent alarms exist at 06:30, list has 3 data)
421  * false : to get only one alarm to register in alarm-manager.
422  * (ig. if 3 diffrent alarms exist at 06:30, list has only one)
423  */
424 static void _cal_server_alarm_get_upcoming_specific_utime(time_t utime, bool get_all, GList **l)
425 {
426         int ret = 0;
427         char query[CAL_DB_SQL_MAX_LEN] = {0};
428         snprintf(query, sizeof(query), "SELECT event_id,remind_tick_unit,remind_tick,"
429                         "alarm_type,alarm_utime,alarm_datetime "
430                         "FROM %s WHERE remind_tick_unit =%d AND alarm_type =%d AND alarm_utime %s %ld %s",
431                         CAL_TABLE_ALARM, CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_UTIME,
432                         true == get_all ? "=" : ">", utime,
433                         true == get_all ? "" : "ORDER BY alarm_utime ASC LIMIT 1");
434
435         sqlite3_stmt *stmt = NULL;
436         ret = cal_db_util_query_prepare(query, &stmt);
437         if (CALENDAR_ERROR_NONE != ret) {
438                 /* LCOV_EXCL_START */
439                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
440                 SECURE("query[%s]", query);
441                 return;
442                 /* LCOV_EXCL_STOP */
443         }
444
445         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
446                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
447                 if (NULL == ad) {
448                         /* LCOV_EXCL_START */
449                         ERR("calloc() Fail");
450                         sqlite3_finalize(stmt);
451                         return;
452                         /* LCOV_EXCL_STOP */
453                 }
454
455                 ad->event_id = sqlite3_column_int(stmt, 0);
456                 ad->unit = sqlite3_column_int(stmt, 1);
457                 ad->tick = sqlite3_column_int(stmt, 2);
458                 ad->type = sqlite3_column_int(stmt, 3);
459                 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
460                 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
461                 *l = g_list_append(*l, ad);
462                 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
463                                 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
464                 ad->alert_utime = ad->time;
465                 if (false == get_all) break;
466         }
467         sqlite3_finalize(stmt);
468 }
469
470 static void _cal_server_alarm_get_upcoming_specific_localtime(const char *datetime, bool get_all, GList **l)
471 {
472         int ret = 0;
473         char query[CAL_DB_SQL_MAX_LEN] = {0};
474         snprintf(query, sizeof(query), "SELECT event_id,remind_tick_unit,remind_tick,"
475                         "alarm_type,alarm_utime,alarm_datetime "
476                         "FROM %s WHERE remind_tick_unit=%d AND alarm_type=%d AND alarm_datetime %s '%s' %s",
477                         CAL_TABLE_ALARM, CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_LOCALTIME,
478                         true == get_all ? "=" : ">", datetime,
479                         true == get_all ? "" : "ORDER BY alarm_datetime ASC LIMIT 1");
480
481         sqlite3_stmt *stmt = NULL;
482         ret = cal_db_util_query_prepare(query, &stmt);
483         if (CALENDAR_ERROR_NONE != ret) {
484                 /* LCOV_EXCL_START */
485                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
486                 SECURE("query[%s]", query);
487                 return;
488                 /* LCOV_EXCL_STOP */
489         }
490
491         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
492                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
493                 if (NULL == ad) {
494                         /* LCOV_EXCL_START */
495                         ERR("calloc() Fail");
496                         sqlite3_finalize(stmt);
497                         return;
498                         /* LCOV_EXCL_STOP */
499                 }
500
501                 ad->event_id = sqlite3_column_int(stmt, 0);
502                 ad->unit = sqlite3_column_int(stmt, 1);
503                 ad->tick = sqlite3_column_int(stmt, 2);
504                 ad->type = sqlite3_column_int(stmt, 3);
505                 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
506                 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
507                 *l = g_list_append(*l, ad);
508                 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
509                                 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
510
511                 int y = 0, m = 0, d = 0;
512                 int h = 0, n = 0, s = 0;
513                 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
514
515                 struct tm st = {0};
516                 st.tm_year = y - 1900;
517                 st.tm_mon = m -1;
518                 st.tm_mday = d;
519                 st.tm_hour = h;
520                 st.tm_min = n;
521                 st.tm_sec = s;
522                 ad->alert_utime = (long long int)mktime(&st);
523                 if (false == get_all) break;
524         }
525         sqlite3_finalize(stmt);
526 }
527
528 static void _cal_server_alarm_get_upcoming_nonspecific_event_utime(time_t utime, bool get_all, GList **l)
529 {
530         int ret = 0;
531         /*
532          * A:alarm
533          * B:utime
534          */
535         char query[CAL_DB_SQL_MAX_LEN] = {0};
536         snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick, "
537                         "A.alarm_type,B.dtstart_utime,A.alarm_datetime "
538                         "FROM %s as A, %s as B ON A.event_id = B.event_id "
539                         "WHERE A.remind_tick_unit >%d AND (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
540                         CAL_TABLE_ALARM, CAL_TABLE_UTIME_INSTANCE, CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
541                         true == get_all ? "=" : ">", utime,
542                         true == get_all ? "" : "ORDER BY (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1");
543
544         sqlite3_stmt *stmt = NULL;
545         ret = cal_db_util_query_prepare(query, &stmt);
546         if (CALENDAR_ERROR_NONE != ret) {
547                 /* LCOV_EXCL_START */
548                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
549                 SECURE("query[%s]", query);
550                 return;
551                 /* LCOV_EXCL_STOP */
552         }
553
554         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
555                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
556                 if (NULL == ad) {
557                         /* LCOV_EXCL_START */
558                         ERR("calloc() Fail");
559                         sqlite3_finalize(stmt);
560                         return;
561                         /* LCOV_EXCL_STOP */
562                 }
563
564                 ad->event_id = sqlite3_column_int(stmt, 0);
565                 ad->unit = sqlite3_column_int(stmt, 1);
566                 ad->tick = sqlite3_column_int(stmt, 2);
567                 ad->type = sqlite3_column_int(stmt, 3);
568                 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
569                 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
570                 *l = g_list_append(*l, ad);
571                 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
572                                 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
573
574                 ad->alert_utime = ad->time - (ad->tick * ad->unit);
575                 if (false == get_all) break;
576         }
577         sqlite3_finalize(stmt);
578 }
579
580 static void _cal_server_alarm_get_upcoming_nonspecific_event_localtime(const char *datetime, bool get_all, GList **l)
581 {
582         int ret = 0;
583         /*
584          * A:alarm
585          * B:localtime
586          */
587         char query[CAL_DB_SQL_MAX_LEN] = {0};
588         snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick, "
589                         "A.alarm_type,A.alarm_utime,B.dtstart_datetime "
590                         "FROM %s as A, %s as B ON A.event_id = B.event_id "
591                         "WHERE A.remind_tick_unit >%d AND "
592                         "(strftime('%%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
593                         CAL_TABLE_ALARM, CAL_TABLE_LOCALTIME_INSTANCE, CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
594                         datetime, true == get_all ? "=" : ">",
595                         true == get_all ? "" : "ORDER BY (strftime('%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
596         sqlite3_stmt *stmt = NULL;
597         ret = cal_db_util_query_prepare(query, &stmt);
598         if (CALENDAR_ERROR_NONE != ret) {
599                 /* LCOV_EXCL_START */
600                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
601                 SECURE("query[%s]", query);
602                 return;
603                 /* LCOV_EXCL_STOP */
604         }
605
606         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
607                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
608                 if (NULL == ad) {
609                         /* LCOV_EXCL_START */
610                         ERR("calloc() Fail");
611                         sqlite3_finalize(stmt);
612                         return;
613                         /* LCOV_EXCL_STOP */
614                 }
615
616                 ad->event_id = sqlite3_column_int(stmt, 0);
617                 ad->unit = sqlite3_column_int(stmt, 1);
618                 ad->tick = sqlite3_column_int(stmt, 2);
619                 ad->type = sqlite3_column_int(stmt, 3);
620                 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
621                 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
622                 *l = g_list_append(*l, ad);
623                 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
624                                 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
625
626                 int y = 0, m = 0, d = 0;
627                 int h = 0, n = 0, s = 0;
628                 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
629
630                 struct tm st = {0};
631                 st.tm_year = y - 1900;
632                 st.tm_mon = m -1;
633                 st.tm_mday = d;
634                 st.tm_hour = h;
635                 st.tm_min = n;
636                 st.tm_sec = s;
637                 ad->alert_utime = (long long int)mktime(&st) - (ad->tick * ad->unit);
638                 if (false == get_all) break;
639         }
640         sqlite3_finalize(stmt);
641 }
642
643 static void _cal_server_alarm_get_upcoming_nonspecific_todo_utime(time_t utime, bool get_all, GList **l)
644 {
645         int ret = 0;
646         /*
647          * A:alarm
648          * B:todo(utime)
649          */
650         char query[CAL_DB_SQL_MAX_LEN] = {0};
651         snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick,"
652                         "A.alarm_type,B.dtend_utime,A.alarm_datetime "
653                         "FROM %s as A, %s as B ON A.event_id = B.id "
654                         "WHERE A.remind_tick_unit >%d AND B.type =%d "
655                         "AND (B.dtend_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
656                         CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE,
657                         CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
658                         true == get_all ? "=" : ">", utime,
659                         true == get_all ? "" : "ORDER BY (B.dtend_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
660
661         sqlite3_stmt *stmt = NULL;
662         ret = cal_db_util_query_prepare(query, &stmt);
663         if (CALENDAR_ERROR_NONE != ret) {
664                 /* LCOV_EXCL_START */
665                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
666                 SECURE("query[%s]", query);
667                 return;
668                 /* LCOV_EXCL_STOP */
669         }
670
671         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
672                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
673                 if (NULL == ad) {
674                         /* LCOV_EXCL_START */
675                         ERR("calloc() Fail");
676                         sqlite3_finalize(stmt);
677                         return;
678                         /* LCOV_EXCL_STOP */
679                 }
680
681                 ad->event_id = sqlite3_column_int(stmt, 0);
682                 ad->unit = sqlite3_column_int(stmt, 1);
683                 ad->tick = sqlite3_column_int(stmt, 2);
684                 ad->type = sqlite3_column_int(stmt, 3);
685                 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
686                 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
687                 *l = g_list_append(*l, ad);
688                 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
689                                 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
690
691                 ad->alert_utime = ad->time - (ad->tick * ad->unit);
692                 if (false == get_all) break;
693         }
694         sqlite3_finalize(stmt);
695 }
696
697 static void _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(const char *datetime, bool get_all, GList **l)
698 {
699         int ret = 0;
700         /*
701          * A:alarm
702          * B:todo(localtime)
703          */
704         char query[CAL_DB_SQL_MAX_LEN] = {0};
705         snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick,"
706                         "A.alarm_type,A.alarm_utime,B.dtend_datetime "
707                         "FROM %s as A, %s as B ON A.event_id = B.id "
708                         "WHERE A.remind_tick_unit >%d AND B.type =%d "
709                         "AND (strftime('%%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
710                         CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE,
711                         CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
712                         datetime, true == get_all ? "=" : ">",
713                         true == get_all ? "" : "ORDER BY (strftime('%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
714
715         sqlite3_stmt *stmt = NULL;
716         ret = cal_db_util_query_prepare(query, &stmt);
717         if (CALENDAR_ERROR_NONE != ret) {
718                 /* LCOV_EXCL_START */
719                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
720                 SECURE("query[%s]", query);
721                 return;
722                 /* LCOV_EXCL_STOP */
723         }
724
725         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
726                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
727                 if (NULL == ad) {
728                         /* LCOV_EXCL_START */
729                         ERR("calloc() Fail");
730                         sqlite3_finalize(stmt);
731                         return;
732                         /* LCOV_EXCL_STOP */
733                 }
734
735                 ad->event_id = sqlite3_column_int(stmt, 0);
736                 ad->unit = sqlite3_column_int(stmt, 1);
737                 ad->tick = sqlite3_column_int(stmt, 2);
738                 ad->type = sqlite3_column_int(stmt, 3);
739                 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
740                 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
741                 *l = g_list_append(*l, ad);
742                 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
743                                 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
744
745                 int y = 0, m = 0, d = 0;
746                 int h = 0, n = 0, s = 0;
747                 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
748
749                 struct tm st = {0};
750                 st.tm_year = y - 1900;
751                 st.tm_mon = m -1;
752                 st.tm_mday = d;
753                 st.tm_hour = h;
754                 st.tm_min = n;
755                 st.tm_sec = s;
756                 ad->alert_utime = (long long int)mktime(&st) - (ad->tick * ad->unit);
757                 if (false == get_all) break;
758         }
759         sqlite3_finalize(stmt);
760 }
761
762 static void _cal_server_alarm_get_latest(time_t utime, bool get_all, GList **out_l)
763 {
764         CAL_FN_CALL();
765         RET_IF(NULL == out_l);
766
767         tzset();
768         struct tm st_local = {0};
769         localtime_r(&utime, &st_local);
770
771         char datetime[CAL_STR_SHORT_LEN32] = {0};
772         snprintf(datetime, sizeof(datetime), CAL_FORMAT_LOCAL_DATETIME,
773                         st_local.tm_year +1900, st_local.tm_mon + 1, st_local.tm_mday,
774                         st_local.tm_hour, st_local.tm_min, st_local.tm_sec);
775         DBG("get alert to register with given time (%ld) datetime[%s]", utime, datetime);
776
777         GList *l = NULL;
778
779         _cal_server_alarm_get_upcoming_specific_utime(utime, get_all, &l);
780         _cal_server_alarm_get_upcoming_nonspecific_event_utime(utime, get_all, &l);
781         _cal_server_alarm_get_upcoming_nonspecific_todo_utime(utime, get_all, &l);
782
783         _cal_server_alarm_get_upcoming_specific_localtime(datetime, get_all, &l);
784         _cal_server_alarm_get_upcoming_nonspecific_event_localtime(datetime, get_all, &l);
785         _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(datetime, get_all, &l);
786
787         *out_l = l;
788 }
789
790 static gint _cal_server_alarm_sort_cb(gconstpointer a, gconstpointer b)
791 {
792         struct _alarm_data_s *p1 = (struct _alarm_data_s *)a;
793         struct _alarm_data_s *p2 = (struct _alarm_data_s *)b;
794         DBG("%lld) > (%lld)", p1->alert_utime, p2->alert_utime);
795
796         return p1->alert_utime < p2->alert_utime ? -1 : 1;
797 }
798
799 static GFunc _cal_server_alarm_print_cb(gpointer data, gpointer user_data)
800 {
801         struct _alarm_data_s *ad = (struct _alarm_data_s *)data;
802         DBG("id(%d) unit(%d) tick(%d) type(%d) time(%lld) datetime[%s]",
803                         ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
804         return 0;
805 }
806
807 static int _cal_server_alarm_register(GList *alarm_list)
808 {
809         CAL_FN_CALL();
810         RETV_IF(NULL == alarm_list, CALENDAR_ERROR_INVALID_PARAMETER);
811
812         int ret = CALENDAR_ERROR_NONE;
813         GList *l = g_list_first(alarm_list);
814         struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
815         RETVM_IF(NULL == ad, CALENDAR_ERROR_DB_FAILED, "No data");
816
817         /* clear all alarm which set by mine. */
818         ret = alarmmgr_enum_alarm_ids(_cal_server_alarm_clear_all_cb, NULL);
819         if (ret != ALARMMGR_RESULT_SUCCESS) {
820                 /* LCOV_EXCL_START */
821                 ERR("alarmmgr_enum_alarm_ids() Fail");
822                 return ret;
823                 /* LCOV_EXCL_STOP */
824         }
825
826         time_t mod_time = (time_t)ad->alert_utime;
827         alarm_entry_t *alarm_info = NULL;
828         alarm_info = alarmmgr_create_alarm();
829         if (NULL == alarm_info) {
830                 /* LCOV_EXCL_START */
831                 ERR("Failed to create alarm");
832                 return CALENDAR_ERROR_DB_FAILED;
833                 /* LCOV_EXCL_STOP */
834         }
835         tzset();
836         struct tm st_alarm = {0};
837
838         switch (ad->system_type) {
839         case CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR:
840                 gmtime_r(&mod_time, &st_alarm);
841                 break;
842
843         default:
844                 tzset();
845                 localtime_r(&mod_time, &st_alarm);
846                 break;
847         }
848
849         alarm_date_t date = {0};
850         date.year = st_alarm.tm_year + 1900;
851         date.month = st_alarm.tm_mon + 1;
852         date.day = st_alarm.tm_mday;
853         date.hour = st_alarm.tm_hour;
854         date.min = st_alarm.tm_min;
855         date.sec = st_alarm.tm_sec;
856         alarmmgr_set_time(alarm_info, date);
857         DBG(COLOR_CYAN" >>> registered record id (%d) at %04d/%02d/%02d %02d:%02d:%02d "COLOR_END" (utime(%lld), datetime[%s], tick(%d) unit(%d))",
858                         ad->event_id, date.year, date.month, date.day, date.hour, date.min, date.sec,
859                         ad->time, ad->datetime, ad->tick, ad->unit);
860
861         int alarm_id = 0;
862         ret = alarmmgr_add_alarm_with_localtime(alarm_info, NULL, &alarm_id);
863         if (ret < 0) {
864                 /* LCOV_EXCL_START */
865                 ERR("alarmmgr_add_alarm_with_localtime Fail (%d)", ret);
866                 alarmmgr_free_alarm(alarm_info);
867                 return ret;
868                 /* LCOV_EXCL_STOP */
869         }
870         DBG("alarmmgr id (%d)", alarm_id);
871         _cal_server_alarm_update_alarm_id(alarm_id, ad->event_id, ad->tick, ad->unit);
872         alarmmgr_free_alarm(alarm_info);
873         return CALENDAR_ERROR_NONE;
874 }
875
876 static bool __app_matched_cb(app_control_h app_control, const char *package, void *user_data)
877 {
878         CAL_FN_CALL();
879
880         int ret = 0;
881         int i;
882
883         RETV_IF(NULL == user_data, true);
884
885         char *mime = NULL;
886         ret = app_control_get_mime(app_control, &mime);
887         RETVM_IF(APP_CONTROL_ERROR_NONE != ret, true, "app_control_get_mime() Fail(%d)", ret);
888
889         const char *reminder_mime = "application/x-tizen.calendar.reminder";
890         if (strncmp(mime, reminder_mime, strlen(reminder_mime))) { /* not same */
891                 DBG("get mime[%s] is not [%s]", mime, reminder_mime);
892                 free(mime);
893                 return true;
894         }
895         free(mime);
896
897         struct alarm_ud *au = (struct alarm_ud *)user_data;
898         GList *alarm_list = au->alarm_list;
899         if (NULL == alarm_list) {
900                 /* LCOV_EXCL_START */
901                 ERR("No list");
902                 return true;
903                 /* LCOV_EXCL_STOP */
904         }
905         int len = 0;
906         len = g_list_length(alarm_list);
907         if (0 == len) {
908                 DBG("len is 0, no alarm list");
909                 return true;
910         }
911
912         app_control_h ac = NULL;
913         ret = app_control_create(&ac);
914         if (APP_CONTROL_ERROR_NONE != ret) {
915                 /* LCOV_EXCL_START */
916                 ERR("app_control_create() Fail(%d)", ret);
917                 return true;
918                 /* LCOV_EXCL_STOP */
919         }
920         ret = app_control_set_operation(ac,  APP_CONTROL_OPERATION_DEFAULT);
921         if (APP_CONTROL_ERROR_NONE != ret) {
922                 /* LCOV_EXCL_START */
923                 ERR("app_control_create() Fail(%d)", ret);
924                 app_control_destroy(ac);
925                 return true;
926                 /* LCOV_EXCL_STOP */
927         }
928         ret = app_control_set_app_id(ac, package);
929         if (APP_CONTROL_ERROR_NONE != ret) {
930                 /* LCOV_EXCL_START */
931                 ERR("app_control_set_app_id() Fail(%d)", ret);
932                 app_control_destroy(ac);
933                 return true;
934                 /* LCOV_EXCL_STOP */
935         }
936
937         char **ids = NULL;
938         ids = calloc(len, sizeof(char *));
939         if (NULL == ids) {
940                 /* LCOV_EXCL_START */
941                 ERR("calloc() Fail");
942                 app_control_destroy(ac);
943                 return true;
944                 /* LCOV_EXCL_STOP */
945         }
946         GList *cursor = g_list_first(alarm_list);
947         for (i = 0; i < len; i++) {
948                 struct _alarm_data_s *ad = (struct _alarm_data_s *)cursor->data;
949                 if (NULL == ad) {
950                         WARN("No data");
951                         cursor = g_list_next(cursor);
952                         continue;
953                 }
954                 DBG("pkg[%s] time[%lld] tick[%d] unit[%d] record_type[%d]",
955                                 package, ad->time, ad->tick, ad->unit, ad->record);
956
957                 int slen = 0;
958                 char extra[CAL_STR_MIDDLE_LEN] = {0};
959                 slen = snprintf(extra, sizeof(extra), "%s=%d", "id", ad->event_id);
960                 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%lld", "time", ad->time);
961                 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "tick", ad->tick);
962                 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "unit", ad->unit);
963                 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "type", ad->record);
964
965                 /*
966                  * key: id, value: id=4&time=123123&..
967                  */
968                 char buf_id[CAL_STR_MIDDLE_LEN] = {0};
969                 snprintf(buf_id, sizeof(buf_id), "%d", ad->event_id);
970                 app_control_add_extra_data(ac, buf_id, extra);
971                 DBG("value[%s] id[%s]", extra, buf_id);
972
973                 /* append ids */
974                 ids[i] = strdup(buf_id);
975
976                 cursor = g_list_next(cursor);
977         }
978         app_control_add_extra_data_array(ac, "ids", (const char **)ids, len);
979         app_control_send_launch_request(ac, NULL, NULL);
980         app_control_destroy(ac);
981
982         g_list_free_full(alarm_list, free);
983         for (i = 0; i < len; i++) {
984                 free(ids[i]);
985                 ids[i] = NULL;
986         }
987         free(ids);
988
989         return true;
990 }
991
992 static void _cal_server_alarm_noti_with_control(GList *alarm_list)
993 {
994         CAL_FN_CALL();
995
996         int ret = 0;
997         RETM_IF(NULL == alarm_list, "No alarm list");
998
999         app_control_h app_control = NULL;
1000         ret = app_control_create(&app_control);
1001         if (APP_CONTROL_ERROR_NONE != ret) {
1002                 /* LCOV_EXCL_START */
1003                 ERR("app_control_create() Fail(%d)", ret);
1004                 return;
1005                 /* LCOV_EXCL_STOP */
1006         }
1007         ret = app_control_set_operation(app_control, APP_CONTROL_OPERATION_VIEW);
1008         if (APP_CONTROL_ERROR_NONE != ret) {
1009                 /* LCOV_EXCL_START */
1010                 ERR("app_control_set_operation() Fail(%d)", ret);
1011                 app_control_destroy(app_control);
1012                 return;
1013                 /* LCOV_EXCL_STOP */
1014         }
1015         ret = app_control_set_mime(app_control, "application/x-tizen.calendar.reminder");
1016         if (APP_CONTROL_ERROR_NONE != ret) {
1017                 /* LCOV_EXCL_START */
1018                 ERR("app_control_set_mime() Fail(%d)", ret);
1019                 app_control_destroy(app_control);
1020                 return;
1021                 /* LCOV_EXCL_STOP */
1022         }
1023
1024         struct alarm_ud *au = calloc(1, sizeof(struct alarm_ud));
1025         if (NULL == au) {
1026                 /* LCOV_EXCL_START */
1027                 ERR("calloc() Fail");
1028                 app_control_destroy(app_control);
1029                 return;
1030                 /* LCOV_EXCL_STOP */
1031         }
1032         au->alarm_list = alarm_list;
1033         ret = app_control_foreach_app_matched(app_control, __app_matched_cb, au);
1034         if (APP_CONTROL_ERROR_NONE != ret) {
1035                 /* LCOV_EXCL_START */
1036                 ERR("app_control_foreach_app_matched() Fail(%d)", ret);
1037                 free(au);
1038                 app_control_destroy(app_control);
1039                 return;
1040                 /* LCOV_EXCL_STOP */
1041         }
1042         free(au);
1043         app_control_destroy(app_control);
1044 }
1045
1046 static void _cal_server_alarm_noti_with_callback(GList *alarm_list)
1047 {
1048         RETM_IF(NULL == alarm_list, "No alarm list");
1049
1050         GList *l = g_list_first(alarm_list);
1051         while (l) {
1052                 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
1053                 if (NULL == ad) {
1054                         WARN("No data");
1055                         l = g_list_next(l);
1056                         continue;
1057                 }
1058                 DBG("callback time[%lld] tick[%d] unit[%d] record_type[%d]",
1059                                 ad->time, ad->tick, ad->unit, ad->record);
1060
1061                 int len = 0;
1062                 char extra[CAL_STR_MIDDLE_LEN] = {0};
1063                 len = snprintf(extra, sizeof(extra), "%s=%d", "id", ad->event_id);
1064                 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%lld", "time", ad->time);
1065                 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "tick", ad->tick);
1066                 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "unit", ad->unit);
1067                 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "type", ad->record);
1068                 cal_dbus_publish_reminder(len, extra);
1069
1070                 l = g_list_next(l);
1071         }
1072 }
1073
1074 static void cal_server_alarm_register_next_alarm(time_t utime)
1075 {
1076         CAL_FN_CALL();
1077
1078         GList *l = NULL;
1079         _cal_server_alarm_get_latest(utime, false, &l);
1080         if (NULL == l)
1081                 return;
1082
1083         l = g_list_sort(l, _cal_server_alarm_sort_cb);
1084         g_list_foreach(l, (GFunc)_cal_server_alarm_print_cb, NULL);
1085         _cal_server_alarm_register(l);
1086
1087         g_list_free_full(l, free);
1088 }
1089
1090 static void cal_server_alarm_alert(time_t tt_alert)
1091 {
1092         GList *l = NULL;
1093         _cal_server_alarm_get_latest(tt_alert, true, &l);
1094         if (NULL == l)
1095                 return;
1096
1097         _cal_server_alarm_noti_with_callback(l);
1098         _cal_server_alarm_noti_with_control(l);
1099         /* DO NOT FREE LIST, list is freed in callback */
1100 }
1101
1102 static int _alert_cb(alarm_id_t alarm_id, void *data)
1103 {
1104         CAL_FN_CALL();
1105         DBG("alarm_id (%ld)", alarm_id);
1106
1107         time_t tt_alert = 0;
1108         cal_server_alarm_get_alert_time(alarm_id, &tt_alert);
1109         cal_server_alarm_alert(tt_alert);
1110         cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
1111         cal_server_alarm_start();
1112         return 0;
1113 }
1114
1115 static void _timechanged_cb(keynode_t *node, void *data)
1116 {
1117         cal_server_alarm_alert(time(NULL));
1118         cal_server_alarm_start();
1119 }
1120
1121 static void _cal_server_alarm_set_timechange(void)
1122 {
1123         vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, _timechanged_cb, NULL);
1124         vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, _timechanged_cb, NULL);
1125         vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE, _timechanged_cb, NULL);
1126         vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, _timechanged_cb, NULL);
1127 }
1128
1129 static void _cal_server_alarm_unset_timechange(void)
1130 {
1131         vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, _timechanged_cb);
1132         vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, _timechanged_cb);
1133         vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE, _timechanged_cb);
1134         vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, _timechanged_cb);
1135 }
1136
1137 static void _changed_cb(const char* view_uri, void* data)
1138 {
1139         DBG("Receive alarm change signal");
1140         cal_server_alarm_start();
1141 }
1142
1143 static int _cal_server_alarm_set_inotify(calendar_db_changed_cb callback)
1144 {
1145         cal_inotify_subscribe(CAL_NOTI_TYPE_EVENT, CAL_NOTI_FILE_EVENT, callback, NULL);
1146         cal_inotify_subscribe(CAL_NOTI_TYPE_TODO, CAL_NOTI_FILE_TODO, callback, NULL);
1147         return 0;
1148 }
1149
1150 static void _cal_server_alarm_unset_inotify(calendar_db_changed_cb callback)
1151 {
1152         cal_inotify_unsubscribe(CAL_NOTI_FILE_EVENT, callback, NULL);
1153         cal_inotify_unsubscribe(CAL_NOTI_FILE_TODO, callback, NULL);
1154 }
1155
1156 static int cal_server_alarm_init(void)
1157 {
1158         int ret = 0;
1159
1160         _cal_server_alarm_set_timechange();
1161         _cal_server_alarm_set_inotify(_changed_cb);
1162
1163         ret = alarmmgr_init("calendar-service");
1164         if (ret < 0) {
1165                 /* LCOV_EXCL_START */
1166                 ERR("alarmmgr_init() Fail(%d)", ret);
1167                 return CALENDAR_ERROR_SYSTEM;
1168                 /* LCOV_EXCL_STOP */
1169         }
1170
1171         ret = alarmmgr_set_cb(_alert_cb, NULL);
1172         if (ret < 0) {
1173                 /* LCOV_EXCL_START */
1174                 ERR("alarmmgr_set_cb() Fail(%d)", ret);
1175                 return CALENDAR_ERROR_SYSTEM;
1176                 /* LCOV_EXCL_STOP */
1177         }
1178
1179         return CALENDAR_ERROR_NONE;
1180 }
1181
1182 static gpointer _cal_server_alarm_main(gpointer user_data)
1183 {
1184         int ret = 0;
1185         bool is_initialized = false;
1186
1187         while (1) {
1188                 g_mutex_lock(&_cal_server_alarm_mutex);
1189                 /*
1190                  * While syncing with contacts,
1191                  * because calendar-service could be stopped by on-demand,
1192                  * holding on-demand is needed.
1193                  */
1194                 cal_server_ondemand_hold();
1195
1196                 do {
1197                         if (false == is_initialized) {
1198                                 ret = cal_server_alarm_init();
1199                                 if (CALENDAR_ERROR_NONE != ret) {
1200                                         /* LCOV_EXCL_START */
1201                                         ERR("cal_server_alarm_init() Fail(%d)", ret);
1202                                         break;
1203                                         /* LCOV_EXCL_STOP */
1204                                 }
1205                                 DBG("init alarm");
1206                                 is_initialized = true;
1207                         }
1208
1209                         ret = cal_connect();
1210                         if (CALENDAR_ERROR_NONE != ret) {
1211                                 /* LCOV_EXCL_START */
1212                                 ERR("cal_connect() Fail(%d)", ret);
1213                                 break;
1214                                 /* LCOV_EXCL_STOP */
1215                         }
1216
1217                         cal_server_alarm_register_next_alarm(time(NULL));
1218                         cal_disconnect();
1219
1220                 } while (0);
1221
1222                 cal_server_ondemand_release();
1223                 cal_server_ondemand_start();
1224
1225                 while (false == signal_called)
1226                         g_cond_wait(&_cal_server_alarm_cond, &_cal_server_alarm_mutex);
1227                 signal_called = false;
1228                 g_mutex_unlock(&_cal_server_alarm_mutex);
1229
1230                 if (server_killed)
1231                         break;
1232         }
1233         DBG("end alarm thread");
1234         g_thread_exit(NULL);
1235
1236         return NULL;
1237 }
1238
1239 void cal_server_alarm_send_signal(void)
1240 {
1241         g_mutex_lock(&_cal_server_alarm_mutex);
1242         signal_called = true;
1243         g_cond_signal(&_cal_server_alarm_cond);
1244         g_mutex_unlock(&_cal_server_alarm_mutex);
1245 }
1246
1247 void cal_server_alarm_start(void)
1248 {
1249         CAL_FN_CALL();
1250
1251         if (NULL == _cal_server_alarm_thread) {
1252                 g_mutex_init(&_cal_server_alarm_mutex);
1253                 g_cond_init(&_cal_server_alarm_cond);
1254                 _cal_server_alarm_thread = g_thread_new(CAL_SERVER_ALARM_THREAD_NAME,
1255                                 _cal_server_alarm_main, NULL);
1256         }
1257         cal_server_alarm_send_signal();
1258 }
1259
1260 static void cal_server_alarm_deinit(void)
1261 {
1262         alarmmgr_fini();
1263         _cal_server_alarm_unset_inotify(_changed_cb);
1264         _cal_server_alarm_unset_timechange();
1265 }
1266
1267 void cal_server_alarm_end(void)
1268 {
1269         CAL_FN_CALL();
1270
1271         server_killed = true;
1272
1273         cal_server_alarm_deinit();
1274         cal_server_alarm_send_signal();
1275
1276         g_cond_clear(&_cal_server_alarm_cond);
1277         g_thread_join(_cal_server_alarm_thread);
1278         g_thread_unref(_cal_server_alarm_thread);
1279         _cal_server_alarm_thread = NULL;
1280 }