4 * Copyright (c) 2012 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <unistd.h> /* usleep */
26 #include "cal_typedef.h"
27 #include "cal_internal.h"
29 #include "cal_db_util.h"
31 #include "cal_access_control.h"
32 #include "cal_server_contacts.h"
33 #include "cal_server_service.h"
34 #include "cal_server_ondemand.h"
36 #define CAL_SERVER_CONTACTS_SYNC_THREAD_NAME "cal_server_contacts_sync"
37 #define BULK_MAX_COUNT 100
38 #define SYNC_USLEEP 500
40 GThread *_cal_server_contacts_sync_thread = NULL;
41 GCond _cal_server_contacts_sync_cond;
42 GMutex _cal_server_contacts_sync_mutex;
44 static int _cal_server_contacts_set_new_event(int id, char *label, int calendar_type,
45 int date, char *type_str, int account_id, calendar_record_h *out_event)
49 calendar_record_h event = NULL;
50 calendar_time_s st = {0};
51 calendar_time_s et = {0};
55 DBG("date(%d)", date);
56 st.type = CALENDAR_TIME_LOCALTIME;
57 st.time.date.year = date / 10000;
58 st.time.date.month = (date % 10000) / 100;
59 st.time.date.mday = date % 100;
60 st.time.date.hour = 0;
61 st.time.date.minute = 0;
62 st.time.date.second = 0;
64 et.type = CALENDAR_TIME_LOCALTIME;
65 cal_time_get_next_date(&st, &et);
67 snprintf(buf, sizeof(buf), "%d", st.time.date.mday);
69 ret = calendar_record_create(_calendar_event._uri, &event);
70 RETVM_IF(CALENDAR_ERROR_NONE != ret, ret, "calendar_record_create() Fail");
72 ret = calendar_record_set_str(event, _calendar_event.summary, label);
73 if (CALENDAR_ERROR_NONE != ret) {
75 ERR("calendar_record_set_str() Fail:summary");
76 calendar_record_destroy(event, true);
80 ret = calendar_record_set_int(event, _calendar_event.calendar_book_id,
81 DEFAULT_BIRTHDAY_CALENDAR_BOOK_ID);
82 if (CALENDAR_ERROR_NONE != ret) {
84 ERR("calendar_record_set_int() Fail:calendar_book_id");
85 calendar_record_destroy(event, true);
89 ret = calendar_record_set_caltime(event, _calendar_event.start_time, st);
90 if (CALENDAR_ERROR_NONE != ret) {
92 ERR("calendar_record_set_caltime() Fail:start_time");
93 calendar_record_destroy(event, true);
97 ret = calendar_record_set_caltime(event, _calendar_event.end_time, et);
98 if (CALENDAR_ERROR_NONE != ret) {
100 ERR("calendar_record_set_caltime() Fail:end_time");
101 calendar_record_destroy(event, true);
105 ret = calendar_record_set_int(event, _calendar_event.person_id, id);
106 if (CALENDAR_ERROR_NONE != ret) {
107 /* LCOV_EXCL_START */
108 ERR("calendar_record_set_int() Fail:person_id");
109 calendar_record_destroy(event, true);
113 ret = calendar_record_set_str(event, _calendar_event.sync_data1, type_str);
114 if (CALENDAR_ERROR_NONE != ret) {
115 /* LCOV_EXCL_START */
116 ERR("calendar_record_set_str() Fail:sync_data1");
117 calendar_record_destroy(event, true);
121 ret = calendar_record_set_int(event, _calendar_event.freq, CALENDAR_RECURRENCE_YEARLY);
122 if (CALENDAR_ERROR_NONE != ret) {
123 /* LCOV_EXCL_START */
124 ERR("calendar_record_set_int() Fail:freq");
125 calendar_record_destroy(event, true);
129 ret = calendar_record_set_int(event, _calendar_event.interval, 1);
130 if (CALENDAR_ERROR_NONE != ret) {
131 /* LCOV_EXCL_START */
132 ERR("calendar_record_set_int() Fail:interval");
133 calendar_record_destroy(event, true);
137 if (CONTACTS_EVENT_CALENDAR_TYPE_CHINESE == calendar_type) {
138 ret = calendar_record_set_int(event, _calendar_event.calendar_system_type,
139 CALENDAR_SYSTEM_EAST_ASIAN_LUNISOLAR);
140 if (CALENDAR_ERROR_NONE != ret) {
141 /* LCOV_EXCL_START */
142 ERR("calendar_record_set_int() Fail:calendar_system_type");
143 calendar_record_destroy(event, true);
148 ret = calendar_record_set_str(event, _calendar_event.bymonthday, buf);
149 if (CALENDAR_ERROR_NONE != ret) {
150 /* LCOV_EXCL_START */
151 ERR("calendar_record_set_str() Fail:bymonthday");
152 calendar_record_destroy(event, true);
157 ret = calendar_record_set_int(event, _calendar_event.range_type, CALENDAR_RANGE_NONE);
158 if (CALENDAR_ERROR_NONE != ret) {
159 /* LCOV_EXCL_START */
160 ERR("calendar_record_set_int() Fail:range type");
161 calendar_record_destroy(event, true);
166 if (0 < account_id) {
167 snprintf(buf, sizeof(buf), "%d", account_id);
168 ret = calendar_record_set_str(event, _calendar_event.sync_data4, buf);
169 if (CALENDAR_ERROR_NONE != ret) {
170 /* LCOV_EXCL_START */
171 ERR("calendar_record_set_str() Fail:sync data4");
172 calendar_record_destroy(event, true);
180 return CALENDAR_ERROR_NONE;
183 static int cal_server_contacts_delete_event(int contact_id, int **out_array, int *out_count)
187 int max_count = BULK_MAX_COUNT;
189 RETV_IF(NULL == out_array, CALENDAR_ERROR_INVALID_PARAMETER);
190 RETV_IF(NULL == out_count, CALENDAR_ERROR_INVALID_PARAMETER);
192 array = calloc(max_count, sizeof(int));
194 /* LCOV_EXCL_START */
195 ERR("calloc() Fail");
196 return CALENDAR_ERROR_OUT_OF_MEMORY;
200 char query[CAL_DB_SQL_MAX_LEN] = {0};
201 sqlite3_stmt *stmt = NULL;
202 snprintf(query, sizeof(query), "SELECT id FROM %s WHERE contact_id=%d",
203 CAL_TABLE_SCHEDULE, contact_id);
204 ret = cal_db_util_query_prepare(query, &stmt);
205 if (CALENDAR_ERROR_NONE != ret) {
206 /* LCOV_EXCL_START */
207 ERR("cal_db_util_query_prepare() Fail(%d)", ret);
208 SECURE("query[%s]", query);
215 while (CAL_SQLITE_ROW == cal_db_util_stmt_step(stmt)) {
216 int event_id = sqlite3_column_int(stmt, 0);
218 /* LCOV_EXCL_START */
219 ERR("event id is invalid");
224 if (max_count <= index) {
226 array = realloc(array, max_count *sizeof(int));
228 /* LCOV_EXCL_START */
229 ERR("realloc() Fail");
234 array[index] = event_id;
237 sqlite3_finalize(stmt);
242 return CALENDAR_ERROR_NONE;
245 static int cal_server_contacts_insert_event(int id, calendar_list_h out_insert)
250 RETV_IF(NULL == out_insert, CALENDAR_ERROR_INVALID_PARAMETER);
252 contacts_record_h contact = NULL;
253 ret = contacts_db_get_record(_contacts_contact._uri, id, &contact);
254 if (CONTACTS_ERROR_NONE != ret) {
255 /* LCOV_EXCL_START */
256 ERR("contacts_db_get_record() Fail(%d)", ret);
257 return CALENDAR_ERROR_SYSTEM;
260 int address_book_id = 0;
261 ret = contacts_record_get_int(contact, _contacts_contact.address_book_id, &address_book_id);
262 if (CONTACTS_ERROR_NONE != ret) {
263 /* LCOV_EXCL_START */
264 ERR("contacts_record_get_int() Fail(%d)", ret);
265 contacts_record_destroy(contact, true);
266 return CALENDAR_ERROR_SYSTEM;
269 if (0 < address_book_id) { /* default phone addressbook is 0 */
270 DBG("address_book_id(%d)", address_book_id);
271 contacts_record_h address_book = NULL;
272 ret = contacts_db_get_record(_contacts_address_book._uri, address_book_id, &address_book);
273 if (CONTACTS_ERROR_NONE != ret) {
274 /* LCOV_EXCL_START */
275 DBG("contacts_db_get_record() Fail(%d)", ret);
276 contacts_record_destroy(contact, true);
277 return CALENDAR_ERROR_SYSTEM;
280 ret = contacts_record_get_int(address_book, _contacts_address_book.account_id, &account_id);
281 contacts_record_destroy(address_book, true);
282 if (CONTACTS_ERROR_NONE != ret) {
283 /* LCOV_EXCL_START */
284 DBG("contacts_record_get_inti() Fail(%d)", ret);
285 contacts_record_destroy(contact, true);
286 return CALENDAR_ERROR_SYSTEM;
289 DBG("account_id[%d]", account_id);
293 contacts_record_h contact_event = NULL;
294 while (CONTACTS_ERROR_NONE == contacts_record_get_child_record_at_p(contact,
295 _contacts_contact.event, index++, &contact_event)) {
297 ret = contacts_record_get_int(contact_event, _contacts_event.type, &type);
298 BREAK_IF(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Fail(%d)", ret);
301 ret = contacts_record_get_int(contact_event, _contacts_event.date, &date);
302 BREAK_IF(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Fail(%d)", ret);
304 int calendar_type = 0;
305 ret = contacts_record_get_int(contact_event, _contacts_event.calendar_type, &calendar_type);
306 BREAK_IF(CONTACTS_ERROR_NONE != ret, "contacts_record_get_int() Fail(%d)", ret);
308 bool is_proper_type = true;
309 char *type_str = NULL;
311 case CONTACTS_EVENT_TYPE_BIRTH:
312 type_str = "birthday";
314 case CONTACTS_EVENT_TYPE_ANNIVERSARY:
315 type_str = "anniversary";
317 case CONTACTS_EVENT_TYPE_OTHER:
320 case CONTACTS_EVENT_TYPE_CUSTOM:
321 ret = contacts_record_get_str_p(contact_event, _contacts_event.label, &type_str);
322 if (CONTACTS_ERROR_NONE != ret) {
323 /* LCOV_EXCL_START */
324 ERR("contacts_record_get_str_p() Fail(%d)", ret);
325 is_proper_type = false;
331 DBG("Invalid type(%d)", type);
332 is_proper_type = false;
336 if (false == is_proper_type)
339 char *display = NULL;
340 ret = contacts_record_get_str_p(contact, _contacts_contact.display_name, &display);
341 BREAK_IF(CONTACTS_ERROR_NONE != ret, "contacts_record_get_str_p() Fail(%d)", ret);
342 SEC_DBG("id(%d) display[%s] type(%d)", id, display, type);
344 calendar_record_h out_event = NULL;
345 _cal_server_contacts_set_new_event(id, display, calendar_type, date, type_str,
346 account_id, &out_event);
348 calendar_list_add(out_insert, out_event);
351 contacts_record_destroy(contact, true);
355 static void _cal_server_contacts_get_event_list(contacts_list_h contacts_list,
356 calendar_list_h out_insert, int **out_delete, int *out_count)
358 RET_IF(NULL == out_delete);
359 RET_IF(NULL == out_count);
363 contacts_list_first(contacts_list);
365 contacts_record_h updated = NULL;
366 contacts_list_get_current_record_p(contacts_list, &updated);
369 contacts_record_get_int(updated, _contacts_contact_updated_info.contact_id, &contact_id);
372 contacts_record_get_int(updated, _contacts_contact_updated_info.type, &status);
374 int *delete_array = NULL;
375 int delete_count = 0;
378 case CONTACTS_CHANGE_INSERTED:
379 cal_server_contacts_insert_event(contact_id, out_insert);
381 case CONTACTS_CHANGE_UPDATED:
382 cal_server_contacts_delete_event(contact_id, &delete_array, &delete_count);
383 cal_server_contacts_insert_event(contact_id, out_insert);
385 case CONTACTS_CHANGE_DELETED:
386 cal_server_contacts_delete_event(contact_id, &delete_array, &delete_count);
389 /* LCOV_EXCL_START */
395 if (0 < delete_count) {
398 array = calloc(delete_count, sizeof(int));
400 array = realloc(array, (count +delete_count) *sizeof(int));
403 /* LCOV_EXCL_START */
404 ERR("calloc() Fail");
409 memcpy(array +count, delete_array, delete_count *sizeof(int));
410 count += delete_count;
413 } while (CONTACTS_ERROR_NONE == contacts_list_next(contacts_list));
418 static int _cal_server_contacts_sync(void)
424 int contacts_ver = -1;
425 char query[CAL_DB_SQL_MAX_LEN] = {0};
426 snprintf(query, sizeof(query), "SELECT contacts_ver FROM %s", CAL_TABLE_VERSION);
427 ret = cal_db_util_query_get_first_int_result(query, NULL, &contacts_ver);
428 if (CALENDAR_ERROR_NONE != ret) {
429 /* LCOV_EXCL_START */
430 ERR("cal_db_util_query_get_first_int_result() Fail(%d)", ret);
434 DBG("contacts_ver(%d)", contacts_ver);
436 contacts_list_h contacts_list = NULL;
438 ret = contacts_db_get_changes_by_version(_contacts_contact_updated_info._uri,
439 -1, contacts_ver, &contacts_list, &latest_ver);
440 if (CONTACTS_ERROR_NONE != ret) {
441 /* LCOV_EXCL_START */
442 ERR("contacts_db_get_changes_by_version() Fail(%d)", ret);
443 contacts_list_destroy(contacts_list, true);
448 if (NULL == contacts_list) {
449 DBG("contacts_list is NULL");
450 contacts_list_destroy(contacts_list, true);
451 return CALENDAR_ERROR_NO_DATA;
453 DBG("get changes and get the latest contacts version(%d)\n", latest_ver);
456 ret = contacts_list_get_count(contacts_list, &count);
458 if (contacts_ver == latest_ver) {
459 contacts_list_destroy(contacts_list, true);
460 return CALENDAR_ERROR_NO_DATA;
463 DBG("contacts count(%d)", count);
465 /* make event list */
466 calendar_list_h insert_list = NULL;
467 calendar_list_create(&insert_list);
468 int *delete_array = NULL;
469 int delete_count = 0;
470 _cal_server_contacts_get_event_list(contacts_list, insert_list, &delete_array, &delete_count);
472 ret = cal_db_util_begin_trans();
473 if (CALENDAR_ERROR_NONE != ret) {
474 /* LCOV_EXCL_START */
475 ERR("cal_db_util_begin_trans() Fail(%d)", ret);
476 contacts_list_destroy(contacts_list, true);
477 calendar_list_destroy(insert_list, true);
479 cal_db_util_end_trans(false);
484 ret = cal_db_delete_records(_calendar_event._uri, delete_array, delete_count);
485 ret = cal_db_insert_records(insert_list, NULL, NULL);
487 snprintf(query, sizeof(query), "UPDATE %s SET contacts_ver=%d", CAL_TABLE_VERSION, latest_ver);
488 ret = cal_db_util_query_exec(query);
489 if (CALENDAR_ERROR_NONE != ret) {
490 /* LCOV_EXCL_START */
491 ERR("cal_db_util_query_exec() Fail(%d)", ret);
492 contacts_list_destroy(contacts_list, true);
493 calendar_list_destroy(insert_list, true);
495 cal_db_util_end_trans(false);
499 cal_db_util_notify(CAL_NOTI_TYPE_EVENT);
500 contacts_list_destroy(contacts_list, true);
501 calendar_list_destroy(insert_list, true);
503 cal_db_util_end_trans(true);
506 return CALENDAR_ERROR_NONE;
509 void cal_server_contacts_delete(int account_id)
514 calendar_list_h list = NULL;
515 calendar_record_h event = NULL;
516 calendar_query_h query = NULL;
517 calendar_filter_h filter = NULL;
519 int *record_id_array = NULL;
522 snprintf(buf, sizeof(buf), "%d", account_id);
524 ret = calendar_query_create(_calendar_event._uri, &query);
525 RETM_IF(CALENDAR_ERROR_NONE != ret, "calendar_query_create() Fail");
526 ret = calendar_filter_create(_calendar_event._uri, &filter);
527 if (CALENDAR_ERROR_NONE != ret) {
528 /* LCOV_EXCL_START */
529 ERR("calendar_filter_create() Fail");
530 calendar_query_destroy(query);
534 ret = calendar_filter_add_str(filter, _calendar_event.sync_data4,
535 CALENDAR_MATCH_EXACTLY, buf);
536 if (CALENDAR_ERROR_NONE != ret) {
537 /* LCOV_EXCL_START */
538 ERR("calendar_filter_add_str() Fail(%d)", ret);
539 calendar_filter_destroy(filter);
540 calendar_query_destroy(query);
544 ret = calendar_filter_add_operator(filter, CALENDAR_FILTER_OPERATOR_AND);
545 if (CALENDAR_ERROR_NONE != ret) {
546 /* LCOV_EXCL_START */
547 ERR("calendar_filter_add_operator() Fail(%d)", ret);
548 calendar_filter_destroy(filter);
549 calendar_query_destroy(query);
553 ret = calendar_filter_add_int(filter, _calendar_event.calendar_book_id,
554 CALENDAR_MATCH_EQUAL, DEFAULT_BIRTHDAY_CALENDAR_BOOK_ID);
555 if (CALENDAR_ERROR_NONE != ret) {
556 /* LCOV_EXCL_START */
557 ERR("calendar_filter_add_int() Fail(%d)", ret);
558 calendar_filter_destroy(filter);
559 calendar_query_destroy(query);
563 ret = calendar_query_set_filter(query, filter);
564 if (CALENDAR_ERROR_NONE != ret) {
565 /* LCOV_EXCL_START */
566 ERR("calendar_query_set_filter() Fail");
567 calendar_filter_destroy(filter);
568 calendar_query_destroy(query);
572 unsigned int projection = _calendar_event.id;
573 ret = calendar_query_set_projection(query, &projection , 1);
574 if (CALENDAR_ERROR_NONE != ret) {
575 /* LCOV_EXCL_START */
576 ERR("calendar_query_set_projection() Fail");
577 calendar_filter_destroy(filter);
578 calendar_query_destroy(query);
583 ret = cal_db_get_records_with_query(query, 0, 0, &list);
584 if (CALENDAR_ERROR_NONE != ret) {
585 /* LCOV_EXCL_START */
586 ERR("cal_db_get_records_with_query() Fail");
587 calendar_list_destroy(list, true);
588 calendar_filter_destroy(filter);
589 calendar_query_destroy(query);
593 ret = calendar_list_get_count(list, &count);
594 if (CALENDAR_ERROR_NONE != ret) {
595 /* LCOV_EXCL_START */
596 ERR("calendar_list_get_count() Fail");
597 calendar_list_destroy(list, true);
598 calendar_filter_destroy(filter);
599 calendar_query_destroy(query);
603 DBG("event count(%d)\n", count);
606 record_id_array = (int *)calloc(count, sizeof(int));
607 if (NULL == record_id_array) {
608 /* LCOV_EXCL_START */
609 ERR("calloc() Fail");
610 calendar_list_destroy(list, true);
611 calendar_filter_destroy(filter);
612 calendar_query_destroy(query);
617 calendar_list_first(list);
619 if (CALENDAR_ERROR_NONE == calendar_list_get_current_record_p(list, &event)) {
624 calendar_record_get_int(event, _calendar_event.id, &event_id);
625 DBG("delete event_id(%d)\n", event_id);
626 record_id_array[i] = event_id;
629 } while (CALENDAR_ERROR_NO_DATA != calendar_list_next(list));
632 ret = cal_db_delete_records(_calendar_event._uri, record_id_array, i);
633 if (CALENDAR_ERROR_NONE != ret)
634 DBG("cal_db_delete_records() Fail(%d)", ret);
635 free(record_id_array);
637 calendar_list_destroy(list, true);
638 calendar_filter_destroy(filter);
639 calendar_query_destroy(query);
642 static gpointer _cal_server_contacts_sync_main(gpointer user_data)
644 int ret = CALENDAR_ERROR_NONE;
648 * while syncing with contacts, calendar-service could be stopped by on-demand.
649 * so, on-demand timeout is stopped.
651 cal_server_ondemand_hold();
654 if (CALENDAR_ERROR_NONE != ret) {
655 /* LCOV_EXCL_START */
656 ERR("cal_connect() Fail(%d)", ret);
657 cal_server_ondemand_start();
662 cal_access_control_set_client_info(NULL, "calendar-service");
665 if (CALENDAR_ERROR_NONE != _cal_server_contacts_sync()) {
670 cal_access_control_unset_client_info();
674 g_mutex_lock(&_cal_server_contacts_sync_mutex);
676 cal_server_ondemand_release();
677 cal_server_ondemand_start();
678 g_cond_wait(&_cal_server_contacts_sync_cond, &_cal_server_contacts_sync_mutex);
679 g_mutex_unlock(&_cal_server_contacts_sync_mutex);
685 static void cal_server_contacts_sync_start(void)
689 if (NULL == _cal_server_contacts_sync_thread) {
690 g_mutex_init(&_cal_server_contacts_sync_mutex);
691 g_cond_init(&_cal_server_contacts_sync_cond);
692 _cal_server_contacts_sync_thread = g_thread_new(CAL_SERVER_CONTACTS_SYNC_THREAD_NAME,
693 _cal_server_contacts_sync_main, NULL);
696 /* don't use mutex. */
697 g_cond_signal(&_cal_server_contacts_sync_cond);
700 static void _changed_cb(const char* view_uri, void *user_data)
702 cal_server_contacts_sync_start();
705 int cal_server_contacts_init(void)
709 ret = contacts_connect();
710 if (CONTACTS_ERROR_NONE != ret) {
711 /* LCOV_EXCL_START */
712 ERR("contacts_connect() Fail(%d)", ret);
717 ret = contacts_db_add_changed_cb(_contacts_event._uri, _changed_cb, NULL);
718 if (CONTACTS_ERROR_NONE != ret)
719 WARN("contacts_db_add_changed_cb() Fail(%d)", ret);
721 ret = contacts_db_add_changed_cb(_contacts_name._uri, _changed_cb, NULL);
722 if (CONTACTS_ERROR_NONE != ret)
723 WARN("contacts_db_add_changed_cb() Fail(%d)", ret);
725 cal_server_contacts_sync_start();
727 return CALENDAR_ERROR_NONE;
730 void cal_server_contacts_deinit(void)
732 contacts_db_remove_changed_cb(_contacts_event._uri, _changed_cb, NULL);
733 contacts_db_remove_changed_cb(_contacts_name._uri, _changed_cb, NULL);
735 contacts_disconnect();