4 * Copyright (c) 2000 - 2012 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.
27 #include "ctsvc_internal.h"
28 #include "ctsvc_inotify.h"
29 #include "ctsvc_handle.h"
30 #include "ctsvc_db_schema.h"
31 #include "ctsvc_db_sqlite.h"
32 #include "ctsvc_server_service.h"
33 #include "ctsvc_server_bg.h"
34 #include "ctsvc_server_utils.h"
35 #include "ctsvc_db_utils.h"
36 #include "ctsvc_db_plugin_addressbook_helper.h"
37 #include "ctsvc_db_access_control.h"
39 #define CTSVC_SERVER_BG_DELETE_COUNT 50
40 #define CTSVC_SERVER_BG_DELETE_STEP_TIME 1
41 #define CTSVC_SERVER_BG_DELETE_THREAD "ctsvc_server_bg_delete"
43 #define CTSVC_SERVER_BG_BASE_CPU_USAGE 10 /* Delete contacts when cpu usage is under the value */
46 STEP_1, /* get contact_ids */
47 STEP_2, /* delete data */
48 STEP_3, /* delete activity */
49 STEP_4, /* delete search_index, contact(image by trigger) */
50 } __ctsvc_delete_step_e;
54 int current_contact_id;
55 __ctsvc_delete_step_e step;
56 } __ctsvc_delete_data_s;
58 static GThread *__ctsvc_server_bg_delete_thread = NULL;
59 static GCond __ctsvc_server_bg_delete_cond;
60 static GMutex __ctsvc_server_bg_delete_mutex;
62 static account_subscribe_h account = NULL;
64 static int __ctsvc_server_bg_contact_delete_step1(__ctsvc_delete_data_s *data)
66 char query[CTS_SQL_MIN_LEN] = {0,};
72 if (data->contact_ids == NULL) {
74 snprintf(query, sizeof(query), "SELECT contact_id FROM "CTS_TABLE_CONTACTS" WHERE deleted = 1");
75 ret = ctsvc_query_prepare(query, &stmt);
76 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
78 while (1 == (ret = ctsvc_stmt_step(stmt))) {
80 id = ctsvc_stmt_get_int(stmt, 0);
81 data->contact_ids = g_slist_append(data->contact_ids, GINT_TO_POINTER(id));
83 ctsvc_stmt_finalize(stmt);
84 if (ret < CONTACTS_ERROR_NONE)
88 count = g_slist_length(data->contact_ids);
90 return CONTACTS_ERROR_NO_DATA;
92 cursor = g_slist_nth(data->contact_ids, 0);
94 data->current_contact_id = GPOINTER_TO_INT(cursor->data);
95 data->contact_ids = g_slist_remove(data->contact_ids, GINT_TO_POINTER(data->current_contact_id));
97 return CONTACTS_ERROR_NONE;
99 return CONTACTS_ERROR_NO_DATA;
104 static int __ctsvc_server_bg_contact_delete_step2(__ctsvc_delete_data_s *data)
108 char query[CTS_SQL_MIN_LEN] = {0};
110 cts_stmt stmt = NULL;
115 snprintf(query, sizeof(query),
116 "SELECT id FROM "CTS_TABLE_DATA" WHERE contact_id = %d AND is_my_profile = 0 LIMIT %d",
117 data->current_contact_id, CTSVC_SERVER_BG_DELETE_COUNT);
119 ret = ctsvc_query_prepare(query, &stmt);
120 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
122 while (1 == (ret = ctsvc_stmt_step(stmt))) {
124 id = ctsvc_stmt_get_int(stmt, 0);
125 list = g_slist_append(list, GINT_TO_POINTER(id));
127 ctsvc_stmt_finalize(stmt);
129 count = g_slist_length(list);
132 return CONTACTS_ERROR_NO_DATA;
135 ret = ctsvc_begin_trans();
136 if (ret != CONTACTS_ERROR_NONE) {
139 return CONTACTS_ERROR_DB;
142 cursor = g_slist_nth(list, 0);
144 int id = GPOINTER_TO_INT(cursor->data);
145 snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_DATA" WHERE id = %d", id);
147 ret = ctsvc_query_exec(query);
148 if (ret != CONTACTS_ERROR_NONE) {
149 /* LCOV_EXCL_START */
151 ctsvc_end_trans(false);
156 cursor = g_slist_next(cursor);
159 ret = ctsvc_end_trans(true);
164 /* remove activities */
165 static int __ctsvc_server_bg_contact_delete_step3(__ctsvc_delete_data_s *data)
170 char query[CTS_SQL_MIN_LEN] = {0};
172 cts_stmt stmt = NULL;
177 snprintf(query, sizeof(query),
178 "SELECT id FROM "CTS_TABLE_ACTIVITIES" WHERE contact_id = %d LIMIT %d",
179 data->current_contact_id, CTSVC_SERVER_BG_DELETE_COUNT);
181 ret = ctsvc_query_prepare(query, &stmt);
182 RETVM_IF(NULL == stmt, ret, "ctsvc_query_prepare() Fail(%d)", ret);
184 while (1 == (ret = ctsvc_stmt_step(stmt))) {
186 id = ctsvc_stmt_get_int(stmt, 0);
187 list = g_slist_append(list, GINT_TO_POINTER(id));
189 ctsvc_stmt_finalize(stmt);
191 count = g_slist_length(list);
194 return CONTACTS_ERROR_NO_DATA;
197 ret = ctsvc_begin_trans();
198 if (ret != CONTACTS_ERROR_NONE) {
201 return CONTACTS_ERROR_DB;
204 cursor = g_slist_nth(list, 0);
206 int id = GPOINTER_TO_INT(cursor->data);
207 snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_ACTIVITIES" WHERE id = %d", id);
209 ret = ctsvc_query_exec(query);
210 if (ret != CONTACTS_ERROR_NONE) {
211 /* LCOV_EXCL_START */
213 ctsvc_end_trans(false);
218 cursor = g_slist_next(cursor);
221 ret = ctsvc_end_trans(true);
226 static int __ctsvc_server_bg_contact_delete_step4(__ctsvc_delete_data_s *data)
229 char query[CTS_SQL_MIN_LEN] = {0};
231 ret = ctsvc_begin_trans();
232 RETVM_IF(CONTACTS_ERROR_NONE != ret, CONTACTS_ERROR_DB, "DB Fail");
234 snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_SEARCH_INDEX" WHERE contact_id = %d",
235 data->current_contact_id);
236 ret = ctsvc_query_exec(query);
237 if (CONTACTS_ERROR_NONE != ret) {
238 /* LCOV_EXCL_START */
240 ctsvc_end_trans(false);
245 snprintf(query, sizeof(query), "DELETE FROM "CTS_TABLE_CONTACTS" WHERE contact_id = %d",
246 data->current_contact_id);
247 ret = ctsvc_query_exec(query);
248 if (CONTACTS_ERROR_NONE != ret) {
249 /* LCOV_EXCL_START */
251 ctsvc_end_trans(false);
256 ret = ctsvc_end_trans(true);
260 static bool __ctsvc_server_bg_contact_delete_step(int ret, __ctsvc_delete_data_s *data)
262 if (ret != CONTACTS_ERROR_NONE && ret != CONTACTS_ERROR_NO_DATA) {
263 /* LCOV_EXCL_START */
264 if (data->contact_ids)
265 g_slist_free(data->contact_ids);
266 ERR("Fail(%d)", ret);
271 switch (data->step) {
273 if (ret == CONTACTS_ERROR_NO_DATA) {
274 /* LCOV_EXCL_START */
275 if (data->contact_ids)
276 g_slist_free(data->contact_ids);
277 ERR("step_1 no_data");
284 if (ret == CONTACTS_ERROR_NO_DATA)
288 if (ret == CONTACTS_ERROR_NO_DATA)
302 static bool __ctsvc_server_db_delete_run(__ctsvc_delete_data_s *data)
305 int ret = CONTACTS_ERROR_NONE;
307 RETV_IF(NULL == data, false);
309 switch (data->step) {
311 /* get deleted contact id list */
312 ret = __ctsvc_server_bg_contact_delete_step1(data);
315 /* delete data of current contact id (MAX CTSVC_SERVER_BG_DELETE_COUNT) */
316 ret = __ctsvc_server_bg_contact_delete_step2(data);
319 /* delete activity of current contact id (MAX CTSVC_SERVER_BG_DELETE_COUNT each time) */
320 ret = __ctsvc_server_bg_contact_delete_step3(data);
323 /* delete search index of current contact id */
324 ret = __ctsvc_server_bg_contact_delete_step4(data);
327 /* LCOV_EXCL_START */
329 if (data->contact_ids)
330 g_slist_free(data->contact_ids);
335 return __ctsvc_server_bg_contact_delete_step(ret, data);
339 unsigned long int cpu_work_time;
340 unsigned long int cpu_total_time;
343 static process_stat* __ctsvc_get_cpu_stat()
347 long unsigned int cpu_time[10];
348 process_stat *result = NULL;
350 FILE *fstat = fopen("/proc/stat", "r");
354 memset(cpu_time, 0x0, sizeof(cpu_time));
355 ret = fscanf(fstat, "%*s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
356 &cpu_time[0], &cpu_time[1], &cpu_time[2], &cpu_time[3],
357 &cpu_time[4], &cpu_time[5], &cpu_time[6], &cpu_time[7],
358 &cpu_time[8], &cpu_time[9]);
364 result = calloc(1, sizeof(process_stat));
365 if (NULL == result) {
366 /* LCOV_EXCL_START */
367 ERR("calloc() Fail");
371 for (i = 0; i < 10; i++) {
373 result->cpu_work_time += cpu_time[i];
374 result->cpu_total_time += cpu_time[i];
380 static bool __ctsvc_cpu_is_busy()
382 unsigned long int total_time_diff;
383 unsigned long int work_time_diff;
384 process_stat *result1 = NULL;
385 process_stat *result2 = NULL;
388 result1 = __ctsvc_get_cpu_stat();
390 result2 = __ctsvc_get_cpu_stat();
391 if (result1 == NULL || result2 == NULL) {
397 total_time_diff = result2->cpu_total_time - result1->cpu_total_time;
398 work_time_diff = result2->cpu_work_time - result1->cpu_work_time;
403 cpu_usage = ((double)work_time_diff/(double)total_time_diff) * 100;
404 INFO("cpu usage : %.2lf (%ld/%ld)", cpu_usage, work_time_diff, total_time_diff);
405 if (CTSVC_SERVER_BG_BASE_CPU_USAGE < cpu_usage)
410 static gpointer __ctsvc_server_bg_delete(gpointer user_data)
414 __ctsvc_delete_data_s *callback_data = NULL;
417 callback_data = calloc(1, sizeof(__ctsvc_delete_data_s));
418 if (callback_data == NULL) {
419 /* LCOV_EXCL_START */
424 callback_data->step = STEP_1;
426 ret = ctsvc_connect();
427 if (CONTACTS_ERROR_NONE != ret) {
428 /* LCOV_EXCL_START */
429 ERR("contacts_connect() fail(%d)", ret);
434 ctsvc_set_client_access_info(NULL, NULL);
436 ctsvc_server_stop_timeout();
438 if (__ctsvc_cpu_is_busy()) { /* sleep 1 sec in function */
439 /* LCOV_EXCL_START */
440 ERR("Now CPU is busy.. waiting");
441 sleep(CTSVC_SERVER_BG_DELETE_STEP_TIME*59); /* sleep 60 sec(1 min) totally */
445 if (__ctsvc_server_db_delete_run(callback_data) == false) {
452 ctsvc_unset_client_access_info();
454 ret = ctsvc_disconnect();
456 if (CONTACTS_ERROR_NONE != ret)
457 /* LCOV_EXCL_START */
458 ERR("contacts_disconnect Fail(%d)", ret);
460 ctsvc_server_start_timeout();
462 g_mutex_lock(&__ctsvc_server_bg_delete_mutex);
464 g_cond_wait(&__ctsvc_server_bg_delete_cond, &__ctsvc_server_bg_delete_mutex);
465 g_mutex_unlock(&__ctsvc_server_bg_delete_mutex);
468 ctsvc_server_start_timeout();
472 void ctsvc_server_bg_delete_start()
476 if (__ctsvc_server_bg_delete_thread == NULL) {
477 g_mutex_init(&__ctsvc_server_bg_delete_mutex);
478 g_cond_init(&__ctsvc_server_bg_delete_cond);
479 __ctsvc_server_bg_delete_thread = g_thread_new(CTSVC_SERVER_BG_DELETE_THREAD,
480 __ctsvc_server_bg_delete, NULL);
483 /* don't use mutex. */
484 g_cond_signal(&__ctsvc_server_bg_delete_cond);
487 static void __ctsvc_server_addressbook_deleted_cb(const char *view_uri, void *data)
489 /* access control update */
490 ctsvc_reset_all_client_access_info();
492 ctsvc_server_bg_delete_start();
495 static void __ctsvc_server_contact_deleted_cb(const char *view_uri, void *data)
497 ctsvc_server_bg_delete_start();
500 static bool __ctsvc_server_account_delete_cb(const char *event_type, int account_id, void *user_data)
503 INFO("event_type : %s, account_id : %d", event_type, account_id);
505 if (STRING_EQUAL == strcmp(event_type, ACCOUNT_NOTI_NAME_DELETE)) {
506 ctsvc_server_stop_timeout();
507 ctsvc_addressbook_delete(account_id);
509 ctsvc_server_start_timeout();
513 void ctsvc_server_bg_add_cb()
517 ret = ctsvc_inotify_subscribe(_contacts_address_book._uri, __ctsvc_server_addressbook_deleted_cb, NULL);
518 DBG("call ctsvc_inotify_subscribe (_contacts_address_book) : return (%d)", ret);
520 ret = ctsvc_inotify_subscribe(_contacts_contact._uri, __ctsvc_server_contact_deleted_cb, NULL);
521 DBG("call ctsvc_inotify_subscribe (_contacts_contact): return (%d)", ret);
523 ret = account_subscribe_create(&account);
524 if (ACCOUNT_ERROR_NONE == ret) {
525 ret = account_subscribe_notification(account, __ctsvc_server_account_delete_cb, NULL);
526 if (ACCOUNT_ERROR_NONE != ret)
527 /* LCOV_EXCL_START */
528 ERR("account_subscribe_notification() Fail(%d)", ret);
531 /* LCOV_EXCL_START */
532 ERR("account_subscribe_create() Fail(%d)", ret);
537 void ctsvc_server_bg_remove_cb()
541 ret = ctsvc_inotify_unsubscribe(_contacts_address_book._uri, __ctsvc_server_addressbook_deleted_cb, NULL);
542 ERR("call ctsvc_inotify_unsubscribe (_contacts_address_book): return (%d)", ret);
543 ret = ctsvc_inotify_unsubscribe(_contacts_contact._uri, __ctsvc_server_contact_deleted_cb, NULL);
544 ERR("call ctsvc_inotify_unsubscribe (_contacts_contact) : return (%d)", ret);
547 account_unsubscribe_notification(account); /* unsubscirbe & destroy */