Fix warning : invalid argument in format
[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 (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == unit) {
351                 if (CALENDAR_TIME_UTIME == type) {
352                         *tt_alert = utime;
353                 } else {
354                         int y = 0, m = 0, d = 0;
355                         int h = 0, n = 0, s = 0;
356                         if (datetime) {
357                                 sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
358
359                                 st.tm_year = y - 1900;
360                                 st.tm_mon = m - 1;
361                                 st.tm_mday = d;
362                                 st.tm_hour = h;
363                                 st.tm_min = n;
364                                 st.tm_sec = s;
365                                 *tt_alert = mktime(&st);
366                                 DBG("datetime[%s] to %02d:%02d:%02d (%ld)", datetime, h, n, s, *tt_alert);
367                         }
368                 }
369                 sqlite3_finalize(stmt);
370                 return CALENDAR_ERROR_NONE;
371         }
372         sqlite3_finalize(stmt);
373
374         time_t current = time(NULL);
375         current += (tick * unit);
376         current -= 2; /* in case time passed */
377
378         switch (record_type) {
379         case CALENDAR_BOOK_TYPE_EVENT:
380                 switch (dtstart_type) {
381                 case CALENDAR_TIME_UTIME:
382                         utime = _get_event_alert_utime("dtstart_utime", event_id, current);
383                         break;
384
385                 case CALENDAR_TIME_LOCALTIME:
386                         utime = _get_event_alert_localtime("dtstart_datetime", event_id, current);
387                         break;
388                 }
389                 break;
390
391         case CALENDAR_BOOK_TYPE_TODO:
392                 switch (dtend_type) {
393                 case CALENDAR_TIME_UTIME:
394                         utime = _get_todo_alert_utime("dtend_utime", event_id, current);
395                         break;
396
397                 case CALENDAR_TIME_LOCALTIME:
398                         utime = _get_todo_alert_localtime("dtend_datetime", event_id, current);
399                         break;
400                 }
401                 break;
402         }
403         DBG("alert_time(%ld) = utime(%lld) - (tick(%d) * unit(%d))", *tt_alert, utime, tick, unit);
404
405         *tt_alert = utime - (tick * unit);
406         return CALENDAR_ERROR_NONE;
407 }
408
409 /*
410  * bool get_all is
411  * true : to get all alarms including same time event.
412  * (ig. if 3 diffrent alarms exist at 06:30, list has 3 data)
413  * false : to get only one alarm to register in alarm-manager.
414  * (ig. if 3 diffrent alarms exist at 06:30, list has only one)
415  */
416 static void _cal_server_alarm_get_upcoming_specific_utime(time_t utime, bool get_all, GList **l)
417 {
418         int ret = 0;
419         char query[CAL_DB_SQL_MAX_LEN] = {0};
420         snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
421                         "A.alarm_type, A.alarm_utime, A.alarm_datetime "
422                         "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
423                         "WHERE S.link_base_id = 0 AND A.remind_tick_unit = %d AND A.alarm_type = %d "
424                         "AND A.alarm_utime %s %ld %s",
425                         CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_UTIME,
426                         true == get_all ? "=" : ">", utime,
427                         true == get_all ? "" : "ORDER BY alarm_utime ASC LIMIT 1");
428
429         sqlite3_stmt *stmt = NULL;
430         ret = cal_db_util_query_prepare(query, &stmt);
431         if (CALENDAR_ERROR_NONE != ret) {
432                 /* LCOV_EXCL_START */
433                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
434                 SECURE("query[%s]", query);
435                 return;
436                 /* LCOV_EXCL_STOP */
437         }
438
439         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
440                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
441                 if (NULL == ad) {
442                         /* LCOV_EXCL_START */
443                         ERR("calloc() Fail");
444                         sqlite3_finalize(stmt);
445                         return;
446                         /* LCOV_EXCL_STOP */
447                 }
448
449                 ad->event_id = sqlite3_column_int(stmt, 0);
450                 ad->unit = sqlite3_column_int(stmt, 1);
451                 ad->tick = sqlite3_column_int(stmt, 2);
452                 ad->type = sqlite3_column_int(stmt, 3);
453                 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
454                 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
455                 *l = g_list_append(*l, ad);
456                 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
457                                 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
458                 ad->alert_utime = ad->time;
459                 if (false == get_all) break;
460         }
461         sqlite3_finalize(stmt);
462 }
463
464 static void _cal_server_alarm_get_upcoming_specific_localtime(const char *datetime, bool get_all, GList **l)
465 {
466         int ret = 0;
467         char query[CAL_DB_SQL_MAX_LEN] = {0};
468         snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
469                         "A.alarm_type, A.alarm_utime, A.alarm_datetime "
470                         "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
471                         "WHERE S.link_base_id = 0 AND A.remind_tick_unit = %d AND A.alarm_type = %d "
472                         "AND A.alarm_datetime %s '%s' %s",
473                         CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_LOCALTIME,
474                         true == get_all ? "=" : ">", datetime,
475                         true == get_all ? "" : "ORDER BY alarm_datetime ASC LIMIT 1");
476
477         sqlite3_stmt *stmt = NULL;
478         ret = cal_db_util_query_prepare(query, &stmt);
479         if (CALENDAR_ERROR_NONE != ret) {
480                 /* LCOV_EXCL_START */
481                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
482                 SECURE("query[%s]", query);
483                 return;
484                 /* LCOV_EXCL_STOP */
485         }
486
487         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
488                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
489                 if (NULL == ad) {
490                         /* LCOV_EXCL_START */
491                         ERR("calloc() Fail");
492                         sqlite3_finalize(stmt);
493                         return;
494                         /* LCOV_EXCL_STOP */
495                 }
496
497                 ad->event_id = sqlite3_column_int(stmt, 0);
498                 ad->unit = sqlite3_column_int(stmt, 1);
499                 ad->tick = sqlite3_column_int(stmt, 2);
500                 ad->type = sqlite3_column_int(stmt, 3);
501                 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
502                 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
503                 *l = g_list_append(*l, ad);
504                 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
505                                 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
506
507                 int y = 0, m = 0, d = 0;
508                 int h = 0, n = 0, s = 0;
509                 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
510
511                 struct tm st = {0};
512                 st.tm_year = y - 1900;
513                 st.tm_mon = m -1;
514                 st.tm_mday = d;
515                 st.tm_hour = h;
516                 st.tm_min = n;
517                 st.tm_sec = s;
518                 ad->alert_utime = (long long int)mktime(&st);
519                 if (false == get_all) break;
520         }
521         sqlite3_finalize(stmt);
522 }
523
524 static void _cal_server_alarm_get_upcoming_nonspecific_event_utime(time_t utime, bool get_all, GList **l)
525 {
526         int ret = 0;
527         /*
528          * A:alarm
529          * B:utime
530          */
531         char query[CAL_DB_SQL_MAX_LEN] = {0};
532         snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick, "
533                         "A.alarm_type,B.dtstart_utime,A.alarm_datetime "
534                         "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_UTIME_INSTANCE" as B, "CAL_TABLE_SCHEDULE" as S "
535                         "ON A.event_id = B.event_id AND B.event_id = S.id "
536                         "WHERE S.link_base_id = 0 AND A.remind_tick_unit > %d "
537                         "AND (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
538                         CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
539                         true == get_all ? "=" : ">", utime,
540                         true == get_all ? "" : "ORDER BY (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1");
541
542         sqlite3_stmt *stmt = NULL;
543         ret = cal_db_util_query_prepare(query, &stmt);
544         if (CALENDAR_ERROR_NONE != ret) {
545                 /* LCOV_EXCL_START */
546                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
547                 SECURE("query[%s]", query);
548                 return;
549                 /* LCOV_EXCL_STOP */
550         }
551
552         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
553                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
554                 if (NULL == ad) {
555                         /* LCOV_EXCL_START */
556                         ERR("calloc() Fail");
557                         sqlite3_finalize(stmt);
558                         return;
559                         /* LCOV_EXCL_STOP */
560                 }
561
562                 ad->event_id = sqlite3_column_int(stmt, 0);
563                 ad->unit = sqlite3_column_int(stmt, 1);
564                 ad->tick = sqlite3_column_int(stmt, 2);
565                 ad->type = sqlite3_column_int(stmt, 3);
566                 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
567                 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
568                 *l = g_list_append(*l, ad);
569                 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
570                                 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
571
572                 ad->alert_utime = ad->time - (ad->tick * ad->unit);
573                 if (false == get_all) break;
574         }
575         sqlite3_finalize(stmt);
576 }
577
578 static void _cal_server_alarm_get_upcoming_nonspecific_event_localtime(const char *datetime, bool get_all, GList **l)
579 {
580         int ret = 0;
581         /*
582          * A:alarm
583          * B:localtime
584          */
585         char query[CAL_DB_SQL_MAX_LEN] = {0};
586         snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, "
587                         "A.alarm_type, A.alarm_utime, B.dtstart_datetime "
588                         "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_LOCALTIME_INSTANCE" as B, "CAL_TABLE_SCHEDULE" as S "
589                         "ON A.event_id = B.event_id AND B.event_id = S.id "
590                         "WHERE S.link_base_id = 0 AND A.remind_tick_unit >%d AND "
591                         "(strftime('%%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
592                         CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
593                         datetime, true == get_all ? "=" : ">",
594                         true == get_all ? "" : "ORDER BY (strftime('%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
595         sqlite3_stmt *stmt = NULL;
596         ret = cal_db_util_query_prepare(query, &stmt);
597         if (CALENDAR_ERROR_NONE != ret) {
598                 /* LCOV_EXCL_START */
599                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
600                 SECURE("query[%s]", query);
601                 return;
602                 /* LCOV_EXCL_STOP */
603         }
604
605         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
606                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
607                 if (NULL == ad) {
608                         /* LCOV_EXCL_START */
609                         ERR("calloc() Fail");
610                         sqlite3_finalize(stmt);
611                         return;
612                         /* LCOV_EXCL_STOP */
613                 }
614
615                 ad->event_id = sqlite3_column_int(stmt, 0);
616                 ad->unit = sqlite3_column_int(stmt, 1);
617                 ad->tick = sqlite3_column_int(stmt, 2);
618                 ad->type = sqlite3_column_int(stmt, 3);
619                 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
620                 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
621                 *l = g_list_append(*l, ad);
622                 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
623                                 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
624
625                 int y = 0, m = 0, d = 0;
626                 int h = 0, n = 0, s = 0;
627                 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
628
629                 struct tm st = {0};
630                 st.tm_year = y - 1900;
631                 st.tm_mon = m -1;
632                 st.tm_mday = d;
633                 st.tm_hour = h;
634                 st.tm_min = n;
635                 st.tm_sec = s;
636                 ad->alert_utime = (long long int)mktime(&st) - (ad->tick * ad->unit);
637                 if (false == get_all) break;
638         }
639         sqlite3_finalize(stmt);
640 }
641
642 static void _cal_server_alarm_get_upcoming_nonspecific_todo_utime(time_t utime, bool get_all, GList **l)
643 {
644         int ret = 0;
645         /*
646          * A:alarm
647          * S:todo(utime)
648          */
649         char query[CAL_DB_SQL_MAX_LEN] = {0};
650         snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
651                         "A.alarm_type, S.dtend_utime, A.alarm_datetime "
652                         "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
653                         "WHERE A.remind_tick_unit > %d AND S.type = %d "
654                         "AND (S.dtend_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
655                         CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
656                         true == get_all ? "=" : ">", utime,
657                         true == get_all ? "" : "ORDER BY (S.dtend_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
658
659         sqlite3_stmt *stmt = NULL;
660         ret = cal_db_util_query_prepare(query, &stmt);
661         if (CALENDAR_ERROR_NONE != ret) {
662                 /* LCOV_EXCL_START */
663                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
664                 SECURE("query[%s]", query);
665                 return;
666                 /* LCOV_EXCL_STOP */
667         }
668
669         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
670                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
671                 if (NULL == ad) {
672                         /* LCOV_EXCL_START */
673                         ERR("calloc() Fail");
674                         sqlite3_finalize(stmt);
675                         return;
676                         /* LCOV_EXCL_STOP */
677                 }
678
679                 ad->event_id = sqlite3_column_int(stmt, 0);
680                 ad->unit = sqlite3_column_int(stmt, 1);
681                 ad->tick = sqlite3_column_int(stmt, 2);
682                 ad->type = sqlite3_column_int(stmt, 3);
683                 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
684                 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
685                 *l = g_list_append(*l, ad);
686                 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
687                                 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
688
689                 ad->alert_utime = ad->time - (ad->tick * ad->unit);
690                 if (false == get_all) break;
691         }
692         sqlite3_finalize(stmt);
693 }
694
695 static void _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(const char *datetime, bool get_all, GList **l)
696 {
697         int ret = 0;
698         /*
699          * A:alarm
700          * B:todo(localtime)
701          */
702         char query[CAL_DB_SQL_MAX_LEN] = {0};
703         snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick,"
704                         "A.alarm_type,A.alarm_utime,B.dtend_datetime "
705                         "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as B ON A.event_id = B.id "
706                         "WHERE A.remind_tick_unit >%d AND B.type =%d "
707                         "AND (strftime('%%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
708                         CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
709                         datetime, true == get_all ? "=" : ">",
710                         true == get_all ? "" : "ORDER BY (strftime('%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
711
712         sqlite3_stmt *stmt = NULL;
713         ret = cal_db_util_query_prepare(query, &stmt);
714         if (CALENDAR_ERROR_NONE != ret) {
715                 /* LCOV_EXCL_START */
716                 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
717                 SECURE("query[%s]", query);
718                 return;
719                 /* LCOV_EXCL_STOP */
720         }
721
722         while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
723                 struct _alarm_data_s *ad = calloc(1, sizeof(struct _alarm_data_s));
724                 if (NULL == ad) {
725                         /* LCOV_EXCL_START */
726                         ERR("calloc() Fail");
727                         sqlite3_finalize(stmt);
728                         return;
729                         /* LCOV_EXCL_STOP */
730                 }
731
732                 ad->event_id = sqlite3_column_int(stmt, 0);
733                 ad->unit = sqlite3_column_int(stmt, 1);
734                 ad->tick = sqlite3_column_int(stmt, 2);
735                 ad->type = sqlite3_column_int(stmt, 3);
736                 ad->time = (long long int)sqlite3_column_int64(stmt, 4);
737                 snprintf(ad->datetime, sizeof(ad->datetime), "%s", (const char *)sqlite3_column_text(stmt, 5));
738                 *l = g_list_append(*l, ad);
739                 DBG("found id(%d) unit(%d) tick(%d) type(%d) time(%lld) [%s]",
740                                 ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
741
742                 int y = 0, m = 0, d = 0;
743                 int h = 0, n = 0, s = 0;
744                 sscanf(ad->datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
745
746                 struct tm st = {0};
747                 st.tm_year = y - 1900;
748                 st.tm_mon = m -1;
749                 st.tm_mday = d;
750                 st.tm_hour = h;
751                 st.tm_min = n;
752                 st.tm_sec = s;
753                 ad->alert_utime = (long long int)mktime(&st) - (ad->tick * ad->unit);
754                 if (false == get_all) break;
755         }
756         sqlite3_finalize(stmt);
757 }
758
759 static void _cal_server_alarm_get_latest(time_t utime, bool get_all, GList **out_l)
760 {
761         CAL_FN_CALL();
762         RET_IF(NULL == out_l);
763
764         tzset();
765         struct tm st_local = {0};
766         localtime_r(&utime, &st_local);
767
768         char datetime[CAL_STR_SHORT_LEN32] = {0};
769         snprintf(datetime, sizeof(datetime), CAL_FORMAT_LOCAL_DATETIME,
770                         st_local.tm_year +1900, st_local.tm_mon + 1, st_local.tm_mday,
771                         st_local.tm_hour, st_local.tm_min, st_local.tm_sec);
772         DBG("get alert to register with given time (%ld) datetime[%s]", utime, datetime);
773
774         GList *l = NULL;
775
776         _cal_server_alarm_get_upcoming_specific_utime(utime, get_all, &l);
777         _cal_server_alarm_get_upcoming_nonspecific_event_utime(utime, get_all, &l);
778         _cal_server_alarm_get_upcoming_nonspecific_todo_utime(utime, get_all, &l);
779
780         _cal_server_alarm_get_upcoming_specific_localtime(datetime, get_all, &l);
781         _cal_server_alarm_get_upcoming_nonspecific_event_localtime(datetime, get_all, &l);
782         _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(datetime, get_all, &l);
783
784         *out_l = l;
785 }
786
787 static gint _cal_server_alarm_sort_cb(gconstpointer a, gconstpointer b)
788 {
789         struct _alarm_data_s *p1 = (struct _alarm_data_s *)a;
790         struct _alarm_data_s *p2 = (struct _alarm_data_s *)b;
791         DBG("%lld) > (%lld)", p1->alert_utime, p2->alert_utime);
792
793         return p1->alert_utime < p2->alert_utime ? -1 : 1;
794 }
795
796 static GFunc _cal_server_alarm_print_cb(gpointer data, gpointer user_data)
797 {
798         struct _alarm_data_s *ad = (struct _alarm_data_s *)data;
799         DBG("id(%d) unit(%d) tick(%d) type(%d) time(%lld) datetime[%s]",
800                         ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
801         return 0;
802 }
803
804 static int _cal_server_alarm_register(GList *alarm_list)
805 {
806         CAL_FN_CALL();
807         RETV_IF(NULL == alarm_list, CALENDAR_ERROR_INVALID_PARAMETER);
808
809         int ret = CALENDAR_ERROR_NONE;
810         GList *l = g_list_first(alarm_list);
811         RETV_IF(NULL == l, CALENDAR_ERROR_INVALID_PARAMETER);
812
813         struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
814         RETVM_IF(NULL == ad, CALENDAR_ERROR_DB_FAILED, "No data");
815
816         /* clear all alarm which set by mine. */
817         ret = alarmmgr_enum_alarm_ids(_cal_server_alarm_clear_all_cb, NULL);
818         if (ret != ALARMMGR_RESULT_SUCCESS) {
819                 /* LCOV_EXCL_START */
820                 ERR("alarmmgr_enum_alarm_ids() Fail");
821                 return ret;
822                 /* LCOV_EXCL_STOP */
823         }
824
825         time_t mod_time = (time_t)ad->alert_utime;
826         alarm_entry_t *alarm_info = NULL;
827         alarm_info = alarmmgr_create_alarm();
828         if (NULL == alarm_info) {
829                 /* LCOV_EXCL_START */
830                 ERR("Failed to create alarm");
831                 return CALENDAR_ERROR_DB_FAILED;
832                 /* LCOV_EXCL_STOP */
833         }
834         tzset();
835         struct tm st_alarm = {0};
836
837         switch (ad->system_type) {
838         case CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR:
839                 gmtime_r(&mod_time, &st_alarm);
840                 break;
841
842         default:
843                 tzset();
844                 localtime_r(&mod_time, &st_alarm);
845                 break;
846         }
847
848         alarm_date_t date = {0};
849         date.year = st_alarm.tm_year + 1900;
850         date.month = st_alarm.tm_mon + 1;
851         date.day = st_alarm.tm_mday;
852         date.hour = st_alarm.tm_hour;
853         date.min = st_alarm.tm_min;
854         date.sec = st_alarm.tm_sec;
855         alarmmgr_set_time(alarm_info, date);
856         DBG(COLOR_CYAN" >>> registered record id (%d) at %04d/%02d/%02d %02d:%02d:%02d "COLOR_END" (utime(%lld), datetime[%s], tick(%d) unit(%d))",
857                         ad->event_id, date.year, date.month, date.day, date.hour, date.min, date.sec,
858                         ad->time, ad->datetime, ad->tick, ad->unit);
859
860         int alarm_id = 0;
861         ret = alarmmgr_add_alarm_with_localtime(alarm_info, NULL, &alarm_id);
862         if (ret < 0) {
863                 /* LCOV_EXCL_START */
864                 ERR("alarmmgr_add_alarm_with_localtime Fail (%d)", ret);
865                 alarmmgr_free_alarm(alarm_info);
866                 return ret;
867                 /* LCOV_EXCL_STOP */
868         }
869         DBG("alarmmgr id (%d)", alarm_id);
870         _cal_server_alarm_update_alarm_id(alarm_id, ad->event_id, ad->tick, ad->unit);
871         alarmmgr_free_alarm(alarm_info);
872         return CALENDAR_ERROR_NONE;
873 }
874
875 static bool __app_matched_cb(app_control_h app_control, const char *package, void *user_data)
876 {
877         CAL_FN_CALL();
878
879         int ret = 0;
880         int i;
881
882         RETV_IF(NULL == user_data, true);
883
884         char *mime = NULL;
885         ret = app_control_get_mime(app_control, &mime);
886         RETVM_IF(APP_CONTROL_ERROR_NONE != ret, true, "app_control_get_mime() Fail(%d)", ret);
887
888         const char *reminder_mime = "application/x-tizen.calendar.reminder";
889         if (strncmp(mime, reminder_mime, strlen(reminder_mime))) { /* not same */
890                 DBG("get mime[%s] is not [%s]", mime, reminder_mime);
891                 free(mime);
892                 return true;
893         }
894         free(mime);
895
896         struct alarm_ud *au = (struct alarm_ud *)user_data;
897         GList *alarm_list = au->alarm_list;
898         if (NULL == alarm_list) {
899                 /* LCOV_EXCL_START */
900                 ERR("No list");
901                 return true;
902                 /* LCOV_EXCL_STOP */
903         }
904         int len = 0;
905         len = g_list_length(alarm_list);
906         if (0 == len) {
907                 DBG("len is 0, no alarm list");
908                 return true;
909         }
910
911         app_control_h ac = NULL;
912         ret = app_control_create(&ac);
913         if (APP_CONTROL_ERROR_NONE != ret) {
914                 /* LCOV_EXCL_START */
915                 ERR("app_control_create() Fail(%d)", ret);
916                 return true;
917                 /* LCOV_EXCL_STOP */
918         }
919         ret = app_control_set_operation(ac,  APP_CONTROL_OPERATION_DEFAULT);
920         if (APP_CONTROL_ERROR_NONE != ret) {
921                 /* LCOV_EXCL_START */
922                 ERR("app_control_create() Fail(%d)", ret);
923                 app_control_destroy(ac);
924                 return true;
925                 /* LCOV_EXCL_STOP */
926         }
927         ret = app_control_set_app_id(ac, package);
928         if (APP_CONTROL_ERROR_NONE != ret) {
929                 /* LCOV_EXCL_START */
930                 ERR("app_control_set_app_id() Fail(%d)", ret);
931                 app_control_destroy(ac);
932                 return true;
933                 /* LCOV_EXCL_STOP */
934         }
935
936         char **ids = NULL;
937         ids = calloc(len, sizeof(char *));
938         if (NULL == ids) {
939                 /* LCOV_EXCL_START */
940                 ERR("calloc() Fail");
941                 app_control_destroy(ac);
942                 return true;
943                 /* LCOV_EXCL_STOP */
944         }
945         GList *cursor = g_list_first(alarm_list);
946         for (i = 0; i < len; i++) {
947                 if (NULL == cursor) {
948                         ERR("cursor is NULL");
949                         break;
950                 }
951                 struct _alarm_data_s *ad = (struct _alarm_data_s *)cursor->data;
952                 if (NULL == ad) {
953                         WARN("No data");
954                         cursor = g_list_next(cursor);
955                         continue;
956                 }
957                 DBG("pkg[%s] time[%lld] tick[%d] unit[%d] record_type[%d]",
958                                 package, ad->time, ad->tick, ad->unit, ad->record);
959
960                 int slen = 0;
961                 char extra[CAL_STR_MIDDLE_LEN] = {0};
962                 slen = snprintf(extra, sizeof(extra), "%s=%d", "id", ad->event_id);
963                 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%lld", "time", ad->time);
964                 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "tick", ad->tick);
965                 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "unit", ad->unit);
966                 slen += snprintf(extra+slen, sizeof(extra)-slen, "&%s=%d", "type", ad->record);
967
968                 /*
969                  * key: id, value: id=4&time=123123&..
970                  */
971                 char buf_id[CAL_STR_MIDDLE_LEN] = {0};
972                 snprintf(buf_id, sizeof(buf_id), "%d", ad->event_id);
973                 app_control_add_extra_data(ac, buf_id, extra);
974                 DBG("value[%s] id[%s]", extra, buf_id);
975
976                 /* append ids */
977                 ids[i] = strdup(buf_id);
978
979                 cursor = g_list_next(cursor);
980         }
981         app_control_add_extra_data_array(ac, "ids", (const char **)ids, len);
982         app_control_send_launch_request(ac, NULL, NULL);
983         app_control_destroy(ac);
984
985         for (i = 0; i < len; i++) {
986                 free(ids[i]);
987                 ids[i] = NULL;
988         }
989         free(ids);
990
991         return true;
992 }
993
994 static void _cal_server_alarm_noti_with_control(GList *alarm_list)
995 {
996         CAL_FN_CALL();
997
998         int ret = 0;
999         RETM_IF(NULL == alarm_list, "No alarm list");
1000
1001         app_control_h app_control = NULL;
1002         ret = app_control_create(&app_control);
1003         if (APP_CONTROL_ERROR_NONE != ret) {
1004                 /* LCOV_EXCL_START */
1005                 ERR("app_control_create() Fail(%d)", ret);
1006                 return;
1007                 /* LCOV_EXCL_STOP */
1008         }
1009         ret = app_control_set_operation(app_control, APP_CONTROL_OPERATION_VIEW);
1010         if (APP_CONTROL_ERROR_NONE != ret) {
1011                 /* LCOV_EXCL_START */
1012                 ERR("app_control_set_operation() Fail(%d)", ret);
1013                 app_control_destroy(app_control);
1014                 return;
1015                 /* LCOV_EXCL_STOP */
1016         }
1017         ret = app_control_set_mime(app_control, "application/x-tizen.calendar.reminder");
1018         if (APP_CONTROL_ERROR_NONE != ret) {
1019                 /* LCOV_EXCL_START */
1020                 ERR("app_control_set_mime() Fail(%d)", ret);
1021                 app_control_destroy(app_control);
1022                 return;
1023                 /* LCOV_EXCL_STOP */
1024         }
1025
1026         struct alarm_ud *au = calloc(1, sizeof(struct alarm_ud));
1027         if (NULL == au) {
1028                 /* LCOV_EXCL_START */
1029                 ERR("calloc() Fail");
1030                 app_control_destroy(app_control);
1031                 return;
1032                 /* LCOV_EXCL_STOP */
1033         }
1034         au->alarm_list = alarm_list;
1035         ret = app_control_foreach_app_matched(app_control, __app_matched_cb, au);
1036         if (APP_CONTROL_ERROR_NONE != ret) {
1037                 /* LCOV_EXCL_START */
1038                 ERR("app_control_foreach_app_matched() Fail(%d)", ret);
1039                 free(au);
1040                 app_control_destroy(app_control);
1041                 return;
1042                 /* LCOV_EXCL_STOP */
1043         }
1044         free(au);
1045         app_control_destroy(app_control);
1046 }
1047
1048 static void _cal_server_alarm_noti_with_callback(GList *alarm_list)
1049 {
1050         RETM_IF(NULL == alarm_list, "No alarm list");
1051
1052         GList *l = g_list_first(alarm_list);
1053         while (l) {
1054                 struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
1055                 if (NULL == ad) {
1056                         WARN("No data");
1057                         l = g_list_next(l);
1058                         continue;
1059                 }
1060                 DBG("callback time[%lld] tick[%d] unit[%d] record_type[%d]",
1061                                 ad->time, ad->tick, ad->unit, ad->record);
1062
1063                 int len = 0;
1064                 char extra[CAL_STR_MIDDLE_LEN] = {0};
1065                 len = snprintf(extra, sizeof(extra), "%s=%d", "id", ad->event_id);
1066                 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%lld", "time", ad->time);
1067                 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "tick", ad->tick);
1068                 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "unit", ad->unit);
1069                 len += snprintf(extra+len, sizeof(extra)-len, "&%s=%d", "type", ad->record);
1070                 cal_dbus_publish_reminder(len, extra);
1071
1072                 l = g_list_next(l);
1073         }
1074 }
1075
1076 static void cal_server_alarm_register_next_alarm(time_t utime)
1077 {
1078         CAL_FN_CALL();
1079
1080         GList *l = NULL;
1081         _cal_server_alarm_get_latest(utime, false, &l);
1082         if (NULL == l)
1083                 return;
1084
1085         l = g_list_sort(l, _cal_server_alarm_sort_cb);
1086         g_list_foreach(l, (GFunc)_cal_server_alarm_print_cb, NULL);
1087         _cal_server_alarm_register(l);
1088
1089         g_list_free_full(l, free);
1090 }
1091
1092 static void cal_server_alarm_alert(time_t tt_alert)
1093 {
1094         GList *l = NULL;
1095         _cal_server_alarm_get_latest(tt_alert, true, &l);
1096         if (NULL == l)
1097                 return;
1098
1099         _cal_server_alarm_noti_with_callback(l);
1100         _cal_server_alarm_noti_with_control(l);
1101         g_list_free_full(l, free);
1102 }
1103
1104 static int _alert_cb(alarm_id_t alarm_id, void *data)
1105 {
1106         CAL_FN_CALL();
1107         DBG("alarm_id (%d)", (int)alarm_id);
1108
1109         time_t tt_alert = 0;
1110         cal_server_alarm_get_alert_time(alarm_id, &tt_alert);
1111         cal_server_alarm_alert(tt_alert);
1112         cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
1113         cal_server_alarm_start();
1114         return 0;
1115 }
1116
1117 static void _timechanged_cb(keynode_t *node, void *data)
1118 {
1119         cal_server_alarm_alert(time(NULL));
1120         cal_server_alarm_start();
1121 }
1122
1123 static void _cal_server_alarm_set_timechange(void)
1124 {
1125         vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, _timechanged_cb, NULL);
1126         vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, _timechanged_cb, NULL);
1127         vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE, _timechanged_cb, NULL);
1128         vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, _timechanged_cb, NULL);
1129 }
1130
1131 static void _cal_server_alarm_unset_timechange(void)
1132 {
1133         vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, _timechanged_cb);
1134         vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, _timechanged_cb);
1135         vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE, _timechanged_cb);
1136         vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, _timechanged_cb);
1137 }
1138
1139 static void _changed_cb(const char* view_uri, void* data)
1140 {
1141         DBG("Receive alarm change signal");
1142         cal_server_alarm_start();
1143 }
1144
1145 static int _cal_server_alarm_set_inotify(calendar_db_changed_cb callback)
1146 {
1147         cal_inotify_subscribe(CAL_NOTI_TYPE_EVENT, CAL_NOTI_FILE_EVENT, callback, NULL);
1148         cal_inotify_subscribe(CAL_NOTI_TYPE_TODO, CAL_NOTI_FILE_TODO, callback, NULL);
1149         return 0;
1150 }
1151
1152 static void _cal_server_alarm_unset_inotify(calendar_db_changed_cb callback)
1153 {
1154         cal_inotify_unsubscribe(CAL_NOTI_FILE_EVENT, callback, NULL);
1155         cal_inotify_unsubscribe(CAL_NOTI_FILE_TODO, callback, NULL);
1156 }
1157
1158 static int cal_server_alarm_init(void)
1159 {
1160         int ret = 0;
1161
1162         _cal_server_alarm_set_timechange();
1163         _cal_server_alarm_set_inotify(_changed_cb);
1164
1165         ret = alarmmgr_init("calendar-service");
1166         if (ret < 0) {
1167                 /* LCOV_EXCL_START */
1168                 ERR("alarmmgr_init() Fail(%d)", ret);
1169                 return CALENDAR_ERROR_SYSTEM;
1170                 /* LCOV_EXCL_STOP */
1171         }
1172
1173         ret = alarmmgr_set_cb(_alert_cb, NULL);
1174         if (ret < 0) {
1175                 /* LCOV_EXCL_START */
1176                 ERR("alarmmgr_set_cb() Fail(%d)", ret);
1177                 return CALENDAR_ERROR_SYSTEM;
1178                 /* LCOV_EXCL_STOP */
1179         }
1180
1181         return CALENDAR_ERROR_NONE;
1182 }
1183
1184 static gpointer _cal_server_alarm_main(gpointer user_data)
1185 {
1186         DBG("thread alarm: start");
1187
1188         int ret = 0;
1189         bool is_initialized = false;
1190
1191         while (1) {
1192                 g_mutex_lock(&_cal_server_alarm_mutex);
1193                 /*
1194                  * While syncing with contacts,
1195                  * because calendar-service could be stopped by on-demand,
1196                  * holding on-demand is needed.
1197                  */
1198                 cal_server_ondemand_hold();
1199
1200                 do {
1201                         if (false == is_initialized) {
1202                                 ret = cal_server_alarm_init();
1203                                 if (CALENDAR_ERROR_NONE != ret) {
1204                                         /* LCOV_EXCL_START */
1205                                         ERR("cal_server_alarm_init() Fail(%d)", ret);
1206                                         break;
1207                                         /* LCOV_EXCL_STOP */
1208                                 }
1209                                 DBG("thread alarm: init");
1210                                 is_initialized = true;
1211                         }
1212
1213                         ret = cal_connect();
1214                         if (CALENDAR_ERROR_NONE != ret) {
1215                                 /* LCOV_EXCL_START */
1216                                 ERR("cal_connect() Fail(%d)", ret);
1217                                 break;
1218                                 /* LCOV_EXCL_STOP */
1219                         }
1220
1221                         cal_server_alarm_register_next_alarm(time(NULL));
1222                         cal_disconnect();
1223
1224                 } while (0);
1225
1226                 cal_server_ondemand_release();
1227                 cal_server_ondemand_start();
1228
1229                 DBG("thread alarm: wait");
1230                 while (false == signal_called)
1231                         g_cond_wait(&_cal_server_alarm_cond, &_cal_server_alarm_mutex);
1232                 signal_called = false;
1233                 g_mutex_unlock(&_cal_server_alarm_mutex);
1234
1235                 if (server_killed)
1236                         break;
1237         }
1238         DBG("thread alarm: end");
1239         g_thread_exit(NULL);
1240
1241         return NULL;
1242 }
1243
1244 void cal_server_alarm_send_signal(void)
1245 {
1246         g_mutex_lock(&_cal_server_alarm_mutex);
1247         signal_called = true;
1248         g_cond_signal(&_cal_server_alarm_cond);
1249         g_mutex_unlock(&_cal_server_alarm_mutex);
1250 }
1251
1252 void cal_server_alarm_start(void)
1253 {
1254         CAL_FN_CALL();
1255
1256         if (NULL == _cal_server_alarm_thread) {
1257                 g_mutex_init(&_cal_server_alarm_mutex);
1258                 g_cond_init(&_cal_server_alarm_cond);
1259                 _cal_server_alarm_thread = g_thread_new(CAL_SERVER_ALARM_THREAD_NAME,
1260                                 _cal_server_alarm_main, NULL);
1261         }
1262         cal_server_alarm_send_signal();
1263 }
1264
1265 static void cal_server_alarm_deinit(void)
1266 {
1267         alarmmgr_fini();
1268         _cal_server_alarm_unset_inotify(_changed_cb);
1269         _cal_server_alarm_unset_timechange();
1270 }
1271
1272 void cal_server_alarm_end(void)
1273 {
1274         CAL_FN_CALL();
1275
1276         server_killed = true;
1277
1278         cal_server_alarm_deinit();
1279         cal_server_alarm_send_signal();
1280
1281         g_cond_clear(&_cal_server_alarm_cond);
1282         g_thread_join(_cal_server_alarm_thread);
1283         g_thread_unref(_cal_server_alarm_thread);
1284         _cal_server_alarm_thread = NULL;
1285 }