Fixed to compare after conversion to localtime in alert_localtime logic
[platform/core/pim/calendar-service.git] / server / cal_server_alarm.c
index 956e940..3ee36be 100644 (file)
@@ -18,7 +18,6 @@
  */
 
 #include <stdlib.h>
-
 #include <sys/time.h>
 #include <unistd.h>
 #include <alarm.h>
 #include "cal_db_util.h"
 #include "cal_db.h"
 #include "cal_db_query.h"
+#include "cal_server_service.h"
+#include "cal_server_ondemand.h"
 #include "cal_server_dbus.h"
+#include "cal_server_alarm.h"
+
+#define CAL_SERVER_ALARM_THREAD_NAME "cal_server_alarm"
 
-#define CAL_SEARCH_LOOP_MAX 4
+GThread *_cal_server_alarm_thread = NULL;
+GCond _cal_server_alarm_cond;
+GMutex _cal_server_alarm_mutex;
+static bool server_killed = false;
+static bool signal_called = false;
 
 struct _alarm_data_s {
        int event_id;
@@ -49,8 +57,12 @@ struct _alarm_data_s {
        int system_type;
 };
 
+struct alarm_ud {
+       GList *alarm_list;
+};
+
 /* this api is necessary for repeat instance. */
-static int _cal_server_alarm_unset_alerted_alarmmgr_id(int alarm_id)
+static int cal_server_alarm_unset_alerted_alarmmgr_id(int alarm_id)
 {
        char query[CAL_DB_SQL_MAX_LEN] = {0};
        int ret = 0;
@@ -85,7 +97,7 @@ static int _cal_server_alarm_clear_all_cb(alarm_id_t alarm_id, void *data)
        int ret;
 
        DBG("remove alarm id(%d)", alarm_id);
-       _cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
+       cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
        ret = alarmmgr_remove_alarm(alarm_id);
        if (ret != ALARMMGR_RESULT_SUCCESS) {
                /* LCOV_EXCL_START */
@@ -126,13 +138,25 @@ static int _cal_server_alarm_update_alarm_id(int alarm_id, int event_id, int tic
        return CALENDAR_ERROR_NONE;
 }
 
-static long long int _cal_server_alarm_get_alert_utime(const char *field, int event_id, time_t current)
+static time_t _make_time(struct tm *time)
+{
+       time_t utc = mktime(time);
+
+       /* If an error occurs when isdst is 1, retry it after chaning isdst is 0 */
+       if (utc < 0 && time->tm_isdst != 0 ) {
+               time->tm_isdst = 0;
+               utc = mktime(time);
+       }
+       return utc;
+}
+
+static long long int _get_event_alert_utime(const char *field, int event_id, time_t current)
 {
        int ret = 0;
        char query[CAL_DB_SQL_MAX_LEN] = {0};
        snprintf(query, sizeof(query), "SELECT %s FROM %s "
                        "WHERE event_id=%d AND %s>%ld ORDER BY %s LIMIT 1",
-                       field, CAL_TABLE_NORMAL_INSTANCE, event_id, field, current, field);
+                       field, CAL_TABLE_UTIME_INSTANCE, event_id, field, current, field);
 
        sqlite3_stmt *stmt = NULL;
        ret = cal_db_util_query_prepare(query, &stmt);
@@ -152,17 +176,23 @@ static long long int _cal_server_alarm_get_alert_utime(const char *field, int ev
        return utime;
 }
 
-static int _cal_server_alarm_get_alert_localtime(const char *field, int event_id, time_t current)
+static int _get_event_alert_localtime(const char *field, int event_id, time_t current)
 {
        int ret = 0;
        char query[CAL_DB_SQL_MAX_LEN] = {0};
        struct tm st = {0};
-       tzset();
-       localtime_r(&current, &st);
-       time_t mod_current = timegm(&st);
+       struct tm now_s = {0};
+       char buf[256] = {0};
+
+       localtime_r(&current, &now_s);
+       snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d", (int)(now_s.tm_year + 1900),
+                               (int)(now_s.tm_mon + 1), (int)now_s.tm_mday, (int)now_s.tm_hour,
+                               (int)now_s.tm_min, (int)now_s.tm_sec);
+       DBG("Current time : (%s)", buf);
+
        snprintf(query, sizeof(query), "SELECT %s FROM %s "
-                       "WHERE event_id=%d AND strftime('%%s', %s)>%ld ORDER BY %s LIMIT 1",
-                       field, CAL_TABLE_ALLDAY_INSTANCE, event_id, field, mod_current, field);
+                       "WHERE event_id=%d AND (strftime('%%s', %s) - strftime('%%s', '%s') > 0) ORDER BY %s LIMIT 1",
+                       field, CAL_TABLE_LOCALTIME_INSTANCE, event_id, field, buf, field);
 
        sqlite3_stmt *stmt = NULL;
        ret = cal_db_util_query_prepare(query, &stmt);
@@ -178,6 +208,7 @@ static int _cal_server_alarm_get_alert_localtime(const char *field, int event_id
        if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
                datetime = (const char *)sqlite3_column_text(stmt, 0);
 
+
        if (NULL == datetime || '\0' == *datetime) {
                /* LCOV_EXCL_START */
                ERR("Invalid datetime [%s]", datetime);
@@ -197,15 +228,109 @@ static int _cal_server_alarm_get_alert_localtime(const char *field, int event_id
        st.tm_hour = h;
        st.tm_min = n;
        st.tm_sec = s;
+       st.tm_isdst = cal_time_is_dst_savings();
+
+       return (long long int)_make_time(&st);
+}
+
+static int64_t _get_todo_alert_utime(const char *field, int id, time_t now_t)
+{
+       int ret = 0;
+       char query[CAL_DB_SQL_MAX_LEN] = {0};
+       snprintf(query, sizeof(query), "SELECT %s FROM "CAL_TABLE_SCHEDULE" "
+                       "WHERE id=%d AND %s>%ld ORDER BY %s LIMIT 1", field, id, field, now_t, field);
+
+       sqlite3_stmt *stmt = NULL;
+       ret = cal_db_util_query_prepare(query, &stmt);
+       if (CALENDAR_ERROR_NONE != ret) {
+               /* LCOV_EXCL_START */
+               ERR("cal_db_util_query_prepare() Fail(%d)", ret);
+               SECURE("query[%s]", query);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+
+       int64_t utime = 0;
+       ret = cal_db_util_stmt_step(stmt);
+       switch (ret) {
+       case CAL_SQLITE_ROW:
+               utime = (int64_t)sqlite3_column_int64(stmt, 0);
+               break;
+               /* LCOV_EXCL_START
+       case SQLITE_DONE:
+               ERR("No data");
+               break;*/ //Svace:371986
+       default:
+               ERR("Invalid return(%d)", ret);
+               break;
+               /* LCOV_EXCL_STOP */
+       }
 
-       return (long long int)mktime(&st);
+       sqlite3_finalize(stmt);
+       return utime;
 }
 
+static int _get_todo_alert_localtime(const char *field, int event_id, time_t current)
+{
+       int ret = 0;
+       char query[CAL_DB_SQL_MAX_LEN] = {0};
+       struct tm st = {0};
+       struct tm now_s = {0};
+       char buf[256] = {0};
+
+       localtime_r(&current, &now_s);
+       snprintf(buf, sizeof(buf), "%04d-%02d-%02dT%02d:%02d:%02d", (int)(now_s.tm_year + 1900),
+                               (int)(now_s.tm_mon + 1), (int)now_s.tm_mday, (int)now_s.tm_hour,
+                               (int)now_s.tm_min, (int)now_s.tm_sec);
+       DBG("Current time : (%s)", buf);
+
+       snprintf(query, sizeof(query), "SELECT %s FROM %s "
+                       "WHERE id=%d AND (strftime('%%s', %s) - strftime('%%s', '%s') > 0) ORDER BY %s LIMIT 1",
+                       field, CAL_TABLE_SCHEDULE, event_id, field, buf, field);
+
+       sqlite3_stmt *stmt = NULL;
+       ret = cal_db_util_query_prepare(query, &stmt);
+       if (CALENDAR_ERROR_NONE != ret) {
+               /* LCOV_EXCL_START */
+               ERR("cal_db_util_query_prepare() Fail(%d)", ret);
+               SECURE("query[%s]", query);
+               return ret;
+               /* LCOV_EXCL_STOP */
+       }
+
+       const char *datetime = NULL;
+       if (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt))
+               datetime = (const char *)sqlite3_column_text(stmt, 0);
+
+       if (NULL == datetime || '\0' == *datetime) {
+               /* LCOV_EXCL_START */
+               ERR("Invalid datetime [%s]", datetime);
+               sqlite3_finalize(stmt);
+               return 0;
+               /* LCOV_EXCL_STOP */
+       }
+
+       int y = 0, m = 0, d = 0;
+       int h = 0, n = 0, s = 0;
+       sscanf(datetime, CAL_FORMAT_LOCAL_DATETIME, &y, &m, &d, &h, &n, &s);
+       sqlite3_finalize(stmt);
+
+       st.tm_year = y - 1900;
+       st.tm_mon = m - 1;
+       st.tm_mday = d;
+       st.tm_hour = h;
+       st.tm_min = n;
+       st.tm_sec = s;
+       st.tm_isdst = cal_time_is_dst_savings();
+
+       return (long long int)_make_time(&st);
+}
 /*
- * to get aler time, time(NULL) is not accurate. 1 secs diff could be occured.
+ * time(NULL) is not appropriate as parameter.
+ * 1 seconds could be flowed before calling function.(1 sec time diff)
  * so, searching DB is neccessary to find alert time.
  */
-int cal_server_alarm_get_alert_time(int alarm_id, time_t *tt_alert)
+static int cal_server_alarm_get_alert_time(int alarm_id, time_t *tt_alert)
 {
        int ret = 0;
        RETV_IF(NULL == tt_alert, CALENDAR_ERROR_INVALID_PARAMETER);
@@ -249,14 +374,6 @@ int cal_server_alarm_get_alert_time(int alarm_id, time_t *tt_alert)
                dtend_type = sqlite3_column_int(stmt, 8);
        }
 
-       if (NULL == tt_alert) {
-               /* LCOV_EXCL_START */
-               ERR("Invalid parameter: tt_alert is NULL");
-               sqlite3_finalize(stmt);
-               return CALENDAR_ERROR_INVALID_PARAMETER;
-               /* LCOV_EXCL_STOP */
-       }
-
        if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == unit) {
                if (CALENDAR_TIME_UTIME == type) {
                        *tt_alert = utime;
@@ -272,8 +389,9 @@ int cal_server_alarm_get_alert_time(int alarm_id, time_t *tt_alert)
                                st.tm_hour = h;
                                st.tm_min = n;
                                st.tm_sec = s;
-                               *tt_alert = mktime(&st);
-                               DBG("datetime[%s] to %02d:%02d:%02d (%d)", datetime, h, n, s, *tt_alert);
+                               st.tm_isdst = cal_time_is_dst_savings();
+                               *tt_alert = _make_time(&st);
+                               DBG("datetime[%s] to %02d:%02d:%02d (%ld)", datetime, h, n, s, *tt_alert);
                        }
                }
                sqlite3_finalize(stmt);
@@ -282,6 +400,7 @@ int cal_server_alarm_get_alert_time(int alarm_id, time_t *tt_alert)
        sqlite3_finalize(stmt);
 
        time_t current = time(NULL);
+
        current += (tick * unit);
        current -= 2; /* in case time passed */
 
@@ -289,11 +408,11 @@ int cal_server_alarm_get_alert_time(int alarm_id, time_t *tt_alert)
        case CALENDAR_BOOK_TYPE_EVENT:
                switch (dtstart_type) {
                case CALENDAR_TIME_UTIME:
-                       utime = _cal_server_alarm_get_alert_utime("dtstart_utime", event_id, current);
+                       utime = _get_event_alert_utime("dtstart_utime", event_id, current);
                        break;
 
                case CALENDAR_TIME_LOCALTIME:
-                       utime = _cal_server_alarm_get_alert_localtime("dtstart_datetime", event_id, current);
+                       utime = _get_event_alert_localtime("dtstart_datetime", event_id, current);
                        break;
                }
                break;
@@ -301,18 +420,19 @@ int cal_server_alarm_get_alert_time(int alarm_id, time_t *tt_alert)
        case CALENDAR_BOOK_TYPE_TODO:
                switch (dtend_type) {
                case CALENDAR_TIME_UTIME:
-                       utime = _cal_server_alarm_get_alert_utime("dtend_utime", event_id, current);
+                       utime = _get_todo_alert_utime("dtend_utime", event_id, current);
                        break;
 
                case CALENDAR_TIME_LOCALTIME:
-                       utime = _cal_server_alarm_get_alert_localtime("dtend_datetime", event_id, current);
+                       utime = _get_todo_alert_localtime("dtend_datetime", event_id, current);
                        break;
                }
                break;
        }
-       DBG("alert_time(%d) = utime(%lld) - (tick(%d) * unit(%d))", *tt_alert, utime, tick, unit);
-
        *tt_alert = utime - (tick * unit);
+
+       DBG("alert_time(%ld) = utime(%lld) - (tick(%d) * unit(%d))", *tt_alert, utime, tick, unit);
+
        return CALENDAR_ERROR_NONE;
 }
 
@@ -327,10 +447,12 @@ static void _cal_server_alarm_get_upcoming_specific_utime(time_t utime, bool get
 {
        int ret = 0;
        char query[CAL_DB_SQL_MAX_LEN] = {0};
-       snprintf(query, sizeof(query), "SELECT event_id,remind_tick_unit,remind_tick,"
-                       "alarm_type,alarm_utime,alarm_datetime "
-                       "FROM %s WHERE remind_tick_unit =%d AND alarm_type =%d AND alarm_utime %s %ld %s",
-                       CAL_TABLE_ALARM, CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_UTIME,
+       snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
+                       "A.alarm_type, A.alarm_utime, A.alarm_datetime "
+                       "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
+                       "WHERE S.link_base_id = 0 AND A.remind_tick_unit = %d AND A.alarm_type = %d "
+                       "AND A.alarm_utime %s %ld %s",
+                       CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_UTIME,
                        true == get_all ? "=" : ">", utime,
                        true == get_all ? "" : "ORDER BY alarm_utime ASC LIMIT 1");
 
@@ -373,10 +495,12 @@ static void _cal_server_alarm_get_upcoming_specific_localtime(const char *dateti
 {
        int ret = 0;
        char query[CAL_DB_SQL_MAX_LEN] = {0};
-       snprintf(query, sizeof(query), "SELECT event_id,remind_tick_unit,remind_tick,"
-                       "alarm_type,alarm_utime,alarm_datetime "
-                       "FROM %s WHERE remind_tick_unit=%d AND alarm_type=%d AND alarm_datetime %s '%s' %s",
-                       CAL_TABLE_ALARM, CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_LOCALTIME,
+       snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
+                       "A.alarm_type, A.alarm_utime, A.alarm_datetime "
+                       "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
+                       "WHERE S.link_base_id = 0 AND A.remind_tick_unit = %d AND A.alarm_type = %d "
+                       "AND A.alarm_datetime %s '%s' %s",
+                       CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_TIME_LOCALTIME,
                        true == get_all ? "=" : ">", datetime,
                        true == get_all ? "" : "ORDER BY alarm_datetime ASC LIMIT 1");
 
@@ -421,7 +545,8 @@ static void _cal_server_alarm_get_upcoming_specific_localtime(const char *dateti
                st.tm_hour = h;
                st.tm_min = n;
                st.tm_sec = s;
-               ad->alert_utime = (long long int)mktime(&st);
+               st.tm_isdst = cal_time_is_dst_savings();
+               ad->alert_utime = (long long int)_make_time(&st);
                if (false == get_all) break;
        }
        sqlite3_finalize(stmt);
@@ -432,14 +557,16 @@ static void _cal_server_alarm_get_upcoming_nonspecific_event_utime(time_t utime,
        int ret = 0;
        /*
         * A:alarm
-        * B:normal instance
+        * B:utime
         */
        char query[CAL_DB_SQL_MAX_LEN] = {0};
        snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick, "
                        "A.alarm_type,B.dtstart_utime,A.alarm_datetime "
-                       "FROM %s as A, %s as B ON A.event_id = B.event_id "
-                       "WHERE A.remind_tick_unit >%d AND (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
-                       CAL_TABLE_ALARM, CAL_TABLE_NORMAL_INSTANCE, CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
+                       "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_UTIME_INSTANCE" as B, "CAL_TABLE_SCHEDULE" as S "
+                       "ON A.event_id = B.event_id AND B.event_id = S.id "
+                       "WHERE S.link_base_id = 0 AND A.remind_tick_unit > %d "
+                       "AND (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
+                       CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
                        true == get_all ? "=" : ">", utime,
                        true == get_all ? "" : "ORDER BY (B.dtstart_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1");
 
@@ -484,15 +611,16 @@ static void _cal_server_alarm_get_upcoming_nonspecific_event_localtime(const cha
        int ret = 0;
        /*
         * A:alarm
-        * B:allday
+        * B:localtime
         */
        char query[CAL_DB_SQL_MAX_LEN] = {0};
-       snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick, "
-                       "A.alarm_type,A.alarm_utime,B.dtstart_datetime "
-                       "FROM %s as A, %s as B ON A.event_id = B.event_id "
-                       "WHERE A.remind_tick_unit >%d AND "
+       snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick, "
+                       "A.alarm_type, A.alarm_utime, B.dtstart_datetime "
+                       "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_LOCALTIME_INSTANCE" as B, "CAL_TABLE_SCHEDULE" as S "
+                       "ON A.event_id = B.event_id AND B.event_id = S.id "
+                       "WHERE S.link_base_id = 0 AND A.remind_tick_unit >%d AND "
                        "(strftime('%%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
-                       CAL_TABLE_ALARM, CAL_TABLE_ALLDAY_INSTANCE, CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
+                       CALENDAR_ALARM_TIME_UNIT_SPECIFIC,
                        datetime, true == get_all ? "=" : ">",
                        true == get_all ? "" : "ORDER BY (strftime('%s', B.dtstart_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
        sqlite3_stmt *stmt = NULL;
@@ -536,7 +664,8 @@ static void _cal_server_alarm_get_upcoming_nonspecific_event_localtime(const cha
                st.tm_hour = h;
                st.tm_min = n;
                st.tm_sec = s;
-               ad->alert_utime = (long long int)mktime(&st) - (ad->tick * ad->unit);
+               st.tm_isdst = cal_time_is_dst_savings();
+               ad->alert_utime = (long long int)_make_time(&st) - (ad->tick * ad->unit);
                if (false == get_all) break;
        }
        sqlite3_finalize(stmt);
@@ -547,18 +676,17 @@ static void _cal_server_alarm_get_upcoming_nonspecific_todo_utime(time_t utime,
        int ret = 0;
        /*
         * A:alarm
-        * B:todo(normal)
+        * S:todo(utime)
         */
        char query[CAL_DB_SQL_MAX_LEN] = {0};
-       snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick,"
-                       "A.alarm_type,B.dtend_utime,A.alarm_datetime "
-                       "FROM %s as A, %s as B ON A.event_id = B.id "
-                       "WHERE A.remind_tick_unit >%d AND B.type =%d "
-                       "AND (B.dtend_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
-                       CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE,
+       snprintf(query, sizeof(query), "SELECT A.event_id, A.remind_tick_unit, A.remind_tick,"
+                       "A.alarm_type, S.dtend_utime, A.alarm_datetime "
+                       "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as S ON A.event_id = S.id "
+                       "WHERE A.remind_tick_unit > %d AND S.type = %d "
+                       "AND (S.dtend_utime - (A.remind_tick_unit * A.remind_tick)) %s %ld %s",
                        CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
                        true == get_all ? "=" : ">", utime,
-                       true == get_all ? "" : "ORDER BY (B.dtend_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
+                       true == get_all ? "" : "ORDER BY (S.dtend_utime - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
 
        sqlite3_stmt *stmt = NULL;
        ret = cal_db_util_query_prepare(query, &stmt);
@@ -601,15 +729,14 @@ static void _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(const char
        int ret = 0;
        /*
         * A:alarm
-        * B:todo(allday)
+        * B:todo(localtime)
         */
        char query[CAL_DB_SQL_MAX_LEN] = {0};
        snprintf(query, sizeof(query), "SELECT A.event_id,A.remind_tick_unit,A.remind_tick,"
                        "A.alarm_type,A.alarm_utime,B.dtend_datetime "
-                       "FROM %s as A, %s as B ON A.event_id = B.id "
+                       "FROM "CAL_TABLE_ALARM" as A, "CAL_TABLE_SCHEDULE" as B ON A.event_id = B.id "
                        "WHERE A.remind_tick_unit >%d AND B.type =%d "
                        "AND (strftime('%%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick) - strftime('%%s', '%s') %s 0) %s",
-                       CAL_TABLE_ALARM, CAL_TABLE_SCHEDULE,
                        CALENDAR_ALARM_TIME_UNIT_SPECIFIC, CALENDAR_BOOK_TYPE_TODO,
                        datetime, true == get_all ? "=" : ">",
                        true == get_all ? "" : "ORDER BY (strftime('%s', B.dtend_datetime) - (A.remind_tick_unit * A.remind_tick)) LIMIT 1 ");
@@ -655,7 +782,8 @@ static void _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(const char
                st.tm_hour = h;
                st.tm_min = n;
                st.tm_sec = s;
-               ad->alert_utime = (long long int)mktime(&st) - (ad->tick * ad->unit);
+               st.tm_isdst = cal_time_is_dst_savings();
+               ad->alert_utime = (long long int)_make_time(&st) - (ad->tick * ad->unit);
                if (false == get_all) break;
        }
        sqlite3_finalize(stmt);
@@ -663,6 +791,7 @@ static void _cal_server_alarm_get_upcoming_nonspecific_todo_localtime(const char
 
 static void _cal_server_alarm_get_latest(time_t utime, bool get_all, GList **out_l)
 {
+       int ret = 0;
        CAL_FN_CALL();
        RET_IF(NULL == out_l);
 
@@ -671,9 +800,14 @@ static void _cal_server_alarm_get_latest(time_t utime, bool get_all, GList **out
        localtime_r(&utime, &st_local);
 
        char datetime[CAL_STR_SHORT_LEN32] = {0};
-       snprintf(datetime, sizeof(datetime), CAL_FORMAT_LOCAL_DATETIME,
+       ret = snprintf(datetime, sizeof(datetime), CAL_FORMAT_LOCAL_DATETIME,
                        st_local.tm_year +1900, st_local.tm_mon + 1, st_local.tm_mday,
                        st_local.tm_hour, st_local.tm_min, st_local.tm_sec);
+
+       if(ret < 0){
+               WARN("datetime is truncated (%s)",datetime);
+       }
+
        DBG("get alert to register with given time (%ld) datetime[%s]", utime, datetime);
 
        GList *l = NULL;
@@ -701,8 +835,8 @@ static gint _cal_server_alarm_sort_cb(gconstpointer a, gconstpointer b)
 static GFunc _cal_server_alarm_print_cb(gpointer data, gpointer user_data)
 {
        struct _alarm_data_s *ad = (struct _alarm_data_s *)data;
-       DBG("id(%d) unit(%d) tick(%d) type(%d) time(%lld) datetime[%s]",
-                       ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime);
+       DBG("id(%d) unit(%d) tick(%d) type(%d) time(%lld) datetime[%s] alert_utime[%lld]",
+                       ad->event_id, ad->unit, ad->tick, ad->type, ad->time, ad->datetime, ad->alert_utime);
        return 0;
 }
 
@@ -713,6 +847,8 @@ static int _cal_server_alarm_register(GList *alarm_list)
 
        int ret = CALENDAR_ERROR_NONE;
        GList *l = g_list_first(alarm_list);
+       RETV_IF(NULL == l, CALENDAR_ERROR_INVALID_PARAMETER);
+
        struct _alarm_data_s *ad = (struct _alarm_data_s *)l->data;
        RETVM_IF(NULL == ad, CALENDAR_ERROR_DB_FAILED, "No data");
 
@@ -775,10 +911,6 @@ static int _cal_server_alarm_register(GList *alarm_list)
        return CALENDAR_ERROR_NONE;
 }
 
-struct alarm_ud {
-       GList *alarm_list;
-};
-
 static bool __app_matched_cb(app_control_h app_control, const char *package, void *user_data)
 {
        CAL_FN_CALL();
@@ -851,6 +983,10 @@ static bool __app_matched_cb(app_control_h app_control, const char *package, voi
        }
        GList *cursor = g_list_first(alarm_list);
        for (i = 0; i < len; i++) {
+               if (NULL == cursor) {
+                       ERR("cursor is NULL");
+                       break;
+               }
                struct _alarm_data_s *ad = (struct _alarm_data_s *)cursor->data;
                if (NULL == ad) {
                        WARN("No data");
@@ -885,7 +1021,6 @@ static bool __app_matched_cb(app_control_h app_control, const char *package, voi
        app_control_send_launch_request(ac, NULL, NULL);
        app_control_destroy(ac);
 
-       g_list_free_full(alarm_list, free);
        for (i = 0; i < len; i++) {
                free(ids[i]);
                ids[i] = NULL;
@@ -977,22 +1112,23 @@ static void _cal_server_alarm_noti_with_callback(GList *alarm_list)
        }
 }
 
-int cal_server_alarm_register_next_alarm(time_t utime)
+static void cal_server_alarm_register_next_alarm(time_t utime)
 {
+       CAL_FN_CALL();
+
        GList *l = NULL;
        _cal_server_alarm_get_latest(utime, false, &l);
        if (NULL == l)
-               return CALENDAR_ERROR_NONE;
+               return;
 
        l = g_list_sort(l, _cal_server_alarm_sort_cb);
        g_list_foreach(l, (GFunc)_cal_server_alarm_print_cb, NULL);
        _cal_server_alarm_register(l);
 
        g_list_free_full(l, free);
-       return CALENDAR_ERROR_NONE;
 }
 
-void cal_server_alarm_alert(time_t tt_alert)
+static void cal_server_alarm_alert(time_t tt_alert)
 {
        GList *l = NULL;
        _cal_server_alarm_get_latest(tt_alert, true, &l);
@@ -1001,105 +1137,188 @@ void cal_server_alarm_alert(time_t tt_alert)
 
        _cal_server_alarm_noti_with_callback(l);
        _cal_server_alarm_noti_with_control(l);
-       /* DO NOT FREE LIST, list is freed in callback */
+       g_list_free_full(l, free);
 }
 
 static int _alert_cb(alarm_id_t alarm_id, void *data)
 {
        CAL_FN_CALL();
-       DBG("alarm_id (%ld)", alarm_id);
+       DBG("alarm_id (%d)", (int)alarm_id);
 
        time_t tt_alert = 0;
        cal_server_alarm_get_alert_time(alarm_id, &tt_alert);
        cal_server_alarm_alert(tt_alert);
-       _cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
-       cal_server_alarm_register_next_alarm(tt_alert);
+       cal_server_alarm_unset_alerted_alarmmgr_id(alarm_id);
+       cal_server_alarm_start();
        return 0;
 }
 
-static void _cal_server_alarm_timechange_cb(keynode_t *node, void *data)
+static void _timechanged_cb(keynode_t *node, void *data)
 {
-       time_t t = time(NULL);
-       cal_server_alarm_alert(t);
-       cal_server_alarm_register_next_alarm(t);
+       cal_server_alarm_alert(time(NULL));
+       cal_server_alarm_start();
 }
 
-void _cal_server_alarm_set_timechange(void)
+static void _cal_server_alarm_set_timechange(void)
 {
-       vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED,
-                       _cal_server_alarm_timechange_cb, NULL);
-       vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT,
-                       _cal_server_alarm_timechange_cb, NULL);
-       vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT,
-                       _cal_server_alarm_timechange_cb, NULL);
-       vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE,
-                       _cal_server_alarm_timechange_cb, NULL);
+       vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, _timechanged_cb, NULL);
+       vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, _timechanged_cb, NULL);
+       vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE, _timechanged_cb, NULL);
+       vconf_notify_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, _timechanged_cb, NULL);
 }
 
-void _cal_server_alarm_unset_timechange(void)
+static void _cal_server_alarm_unset_timechange(void)
 {
-       vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED,
-                       _cal_server_alarm_timechange_cb);
-       vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT,
-                       _cal_server_alarm_timechange_cb);
-       vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT,
-                       _cal_server_alarm_timechange_cb);
-       vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE,
-                       _cal_server_alarm_timechange_cb);
+       vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, _timechanged_cb);
+       vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_GMT, _timechanged_cb);
+       vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_ZONE, _timechanged_cb);
+       vconf_ignore_key_changed(VCONFKEY_TELEPHONY_NITZ_EVENT_GMT, _timechanged_cb);
 }
 
 static void _changed_cb(const char* view_uri, void* data)
 {
-       CAL_FN_CALL();
-       cal_server_alarm_register_next_alarm(time(NULL));
+       DBG("Receive alarm change signal");
+       cal_server_alarm_start();
 }
 
 static int _cal_server_alarm_set_inotify(calendar_db_changed_cb callback)
 {
-       cal_inotify_subscribe(CAL_NOTI_TYPE_EVENT, CAL_NOTI_EVENT_CHANGED, callback, NULL);
-       cal_inotify_subscribe(CAL_NOTI_TYPE_TODO, CAL_NOTI_TODO_CHANGED, callback, NULL);
+       cal_inotify_subscribe(CAL_NOTI_TYPE_EVENT, CAL_NOTI_FILE_EVENT, callback, NULL);
+       cal_inotify_subscribe(CAL_NOTI_TYPE_TODO, CAL_NOTI_FILE_TODO, callback, NULL);
        return 0;
 }
 
 static void _cal_server_alarm_unset_inotify(calendar_db_changed_cb callback)
 {
-       cal_inotify_unsubscribe(CAL_NOTI_EVENT_CHANGED, callback, NULL);
-       cal_inotify_unsubscribe(CAL_NOTI_TODO_CHANGED, callback, NULL);
+       cal_inotify_unsubscribe(CAL_NOTI_FILE_EVENT, callback, NULL);
+       cal_inotify_unsubscribe(CAL_NOTI_FILE_TODO, callback, NULL);
 }
 
-int cal_server_alarm_init(void)
+static int cal_server_alarm_init(void)
 {
-       CAL_FN_CALL();
-
        int ret = 0;
+
        _cal_server_alarm_set_timechange();
        _cal_server_alarm_set_inotify(_changed_cb);
 
-       ret = alarmmgr_init("calendar-service");
+       ret = alarmmgr_set_cb(_alert_cb, NULL);
        if (ret < 0) {
                /* LCOV_EXCL_START */
-               ERR("alarmmgr_init() Fail(%d)", ret);
+               ERR("alarmmgr_set_cb() Fail(%d)", ret);
                return CALENDAR_ERROR_SYSTEM;
                /* LCOV_EXCL_STOP */
        }
 
-       ret = alarmmgr_set_cb(_alert_cb, NULL);
+       ret = alarmmgr_init("calendar-service");
        if (ret < 0) {
                /* LCOV_EXCL_START */
-               ERR("alarmmgr_set_cb() Fail(%d)", ret);
+               ERR("alarmmgr_init() Fail(%d)", ret);
                return CALENDAR_ERROR_SYSTEM;
                /* LCOV_EXCL_STOP */
        }
 
-       cal_server_alarm_register_next_alarm(time(NULL));
        return CALENDAR_ERROR_NONE;
 }
 
-void cal_server_alarm_deinit(void)
+static gpointer _cal_server_alarm_main(gpointer user_data)
+{
+       DBG("thread alarm: start");
+
+       int ret = 0;
+       bool is_initialized = false;
+
+       while (1) {
+               g_mutex_lock(&_cal_server_alarm_mutex);
+               /*
+                * While syncing with contacts,
+                * because calendar-service could be stopped by on-demand,
+                * holding on-demand is needed.
+                */
+               cal_server_ondemand_hold();
+
+               do {
+                       if (false == is_initialized) {
+                               ret = cal_server_alarm_init();
+                               if (CALENDAR_ERROR_NONE != ret) {
+                                       /* LCOV_EXCL_START */
+                                       ERR("cal_server_alarm_init() Fail(%d)", ret);
+                                       break;
+                                       /* LCOV_EXCL_STOP */
+                               }
+                               DBG("thread alarm: init");
+                               is_initialized = true;
+                       }
+
+                       ret = cal_connect();
+                       if (CALENDAR_ERROR_NONE != ret) {
+                               /* LCOV_EXCL_START */
+                               ERR("cal_connect() Fail(%d)", ret);
+                               break;
+                               /* LCOV_EXCL_STOP */
+                       }
+
+                       cal_server_alarm_register_next_alarm(time(NULL));
+                       cal_disconnect();
+
+               } while (0);
+
+               cal_server_ondemand_release();
+               cal_server_ondemand_start();
+
+               DBG("thread alarm: wait");
+               while (false == signal_called)
+                       g_cond_wait(&_cal_server_alarm_cond, &_cal_server_alarm_mutex);
+               signal_called = false;
+               g_mutex_unlock(&_cal_server_alarm_mutex);
+
+               if (server_killed)
+                       break;
+       }
+       DBG("thread alarm: end");
+       g_thread_exit(NULL);
+
+       return NULL;
+}
+
+void cal_server_alarm_send_signal(void)
+{
+       g_mutex_lock(&_cal_server_alarm_mutex);
+       signal_called = true;
+       g_cond_signal(&_cal_server_alarm_cond);
+       g_mutex_unlock(&_cal_server_alarm_mutex);
+}
+
+void cal_server_alarm_start(void)
+{
+       CAL_FN_CALL();
+
+       if (NULL == _cal_server_alarm_thread) {
+               g_mutex_init(&_cal_server_alarm_mutex);
+               g_cond_init(&_cal_server_alarm_cond);
+               _cal_server_alarm_thread = g_thread_new(CAL_SERVER_ALARM_THREAD_NAME,
+                               _cal_server_alarm_main, NULL);
+       }
+       cal_server_alarm_send_signal();
+}
+
+static void cal_server_alarm_deinit(void)
 {
        alarmmgr_fini();
        _cal_server_alarm_unset_inotify(_changed_cb);
        _cal_server_alarm_unset_timechange();
-
 }
 
+void cal_server_alarm_end(void)
+{
+       CAL_FN_CALL();
+
+       server_killed = true;
+
+       cal_server_alarm_deinit();
+       cal_server_alarm_send_signal();
+
+       g_cond_clear(&_cal_server_alarm_cond);
+       g_thread_join(_cal_server_alarm_thread);
+       g_thread_unref(_cal_server_alarm_thread);
+       _cal_server_alarm_thread = NULL;
+}