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