diff options
author | HyungKyu Song <hk76.song@samsung.com> | 2013-02-16 19:06:08 +0900 |
---|---|---|
committer | HyungKyu Song <hk76.song@samsung.com> | 2013-02-16 19:06:08 +0900 |
commit | 2fe4ba6f7e660a945ed94559110c76852c5edd47 (patch) | |
tree | 1c3b126230f27c8e1451b5669a2e7f760be29fe1 /native/ctsvc_utils.c | |
parent | a1311c9da85162a82223c73aa63e6c9b7d91c565 (diff) | |
download | contacts-service-tizen_2.0.tar.gz contacts-service-tizen_2.0.tar.bz2 contacts-service-tizen_2.0.zip |
Tizen 2.0 Releasesubmit/tizen_2.0/20130216.100704accepted/tizen_2.0/20130216.0940012.0_releasetizen_2.0
Diffstat (limited to 'native/ctsvc_utils.c')
-rw-r--r-- | native/ctsvc_utils.c | 428 |
1 files changed, 428 insertions, 0 deletions
diff --git a/native/ctsvc_utils.c b/native/ctsvc_utils.c new file mode 100644 index 0000000..2fb1051 --- /dev/null +++ b/native/ctsvc_utils.c @@ -0,0 +1,428 @@ +/* + * Contacts Service + * + * Copyright (c) 2010 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <dirent.h> +#include <sys/stat.h> +#include <sys/vfs.h> +#include <image_util.h> + +#include "contacts.h" +#include "ctsvc_internal.h" +#include "ctsvc_utils.h" +#include "ctsvc_mutex.h" +#include "ctsvc_sqlite.h" +#include "ctsvc_schema.h" +#include "ctsvc_notification.h" +#include "ctsvc_struct.h" + +#ifdef _CONTACTS_IPC_SERVER +#include "ctsvc_server_change_subject.h" +#endif + +static __thread int transaction_count = 0; +static __thread int transaction_ver = 0; +static __thread bool version_up = false; + +#define CTS_COMMIT_TRY_MAX 500000 // For 3second +int ctsvc_begin_trans(void) +{ + int ret = -1, progress; + +#ifndef _CONTACTS_IPC_SERVER + ctsvc_mutex_lock(CTS_MUTEX_TRANSACTION); +#endif + if (transaction_count <= 0) { + ret = ctsvc_query_exec("BEGIN IMMEDIATE TRANSACTION"); //taken 600ms + progress = 100000; + while (CONTACTS_ERROR_DB == ret && progress < CTS_COMMIT_TRY_MAX) { + usleep(progress); + ret = ctsvc_query_exec("BEGIN IMMEDIATE TRANSACTION"); + progress *= 2; + } + if(CONTACTS_ERROR_NONE != ret) { + CTS_ERR("ctsvc_query_exec() Failed(%d)", ret); +#ifndef _CONTACTS_IPC_SERVER + ctsvc_mutex_unlock(CTS_MUTEX_TRANSACTION); +#endif + return ret; + } + + transaction_count = 0; + + const char *query = "SELECT ver FROM "CTS_TABLE_VERSION; + ret = ctsvc_query_get_first_int_result(query, &transaction_ver); + version_up = false; + } + transaction_count++; + INFO("transaction_count : %d.", transaction_count); +#ifndef _CONTACTS_IPC_SERVER + ctsvc_mutex_unlock(CTS_MUTEX_TRANSACTION); +#endif + return CONTACTS_ERROR_NONE; +} + +int ctsvc_end_trans(bool is_success) +{ + int ret = -1, progress; + char query[CTS_SQL_MIN_LEN] = {0}; + +#ifndef _CONTACTS_IPC_SERVER + ctsvc_mutex_lock(CTS_MUTEX_TRANSACTION); +#endif + + transaction_count--; + INFO("%s, transaction_count : %d", is_success?"True": "False", transaction_count); + + if (0 != transaction_count) { + CTS_DBG("contact transaction_count : %d.", transaction_count); +#ifndef _CONTACTS_IPC_SERVER + ctsvc_mutex_unlock(CTS_MUTEX_TRANSACTION); +#endif + return CONTACTS_ERROR_NONE; + } + + if (false == is_success) { + ctsvc_nofitication_cancel(); +#ifdef _CONTACTS_IPC_SERVER + ctsvc_change_subject_clear_changed_info(); +#endif + ret = ctsvc_query_exec("ROLLBACK TRANSACTION"); + +#ifndef _CONTACTS_IPC_SERVER + ctsvc_mutex_unlock(CTS_MUTEX_TRANSACTION); +#endif + return CONTACTS_ERROR_NONE; + } + + if (version_up) { + transaction_ver++; + snprintf(query, sizeof(query), "UPDATE %s SET ver = %d", + CTS_TABLE_VERSION, transaction_ver); + ret = ctsvc_query_exec(query); + WARN_IF(CONTACTS_ERROR_NONE != ret, "ctsvc_query_exec(version up) Failed(%d)", ret); + } + + progress = 100000; + ret = ctsvc_query_exec("COMMIT TRANSACTION"); + while (CONTACTS_ERROR_DB == ret && progress<CTS_COMMIT_TRY_MAX) { + usleep(progress); + ret = ctsvc_query_exec("COMMIT TRANSACTION"); + progress *= 2; + } + if (CONTACTS_ERROR_NONE != ret) { + int tmp_ret; + CTS_ERR("ctsvc_query_exec() Failed(%d)", ret); + ctsvc_nofitication_cancel(); +#ifdef _CONTACTS_IPC_SERVER + ctsvc_change_subject_clear_changed_info(); +#endif + tmp_ret = ctsvc_query_exec("ROLLBACK TRANSACTION"); + WARN_IF(CONTACTS_ERROR_NONE != tmp_ret, "ctsvc_query_exec(ROLLBACK) Failed(%d)", tmp_ret); +#ifndef _CONTACTS_IPC_SERVER + ctsvc_mutex_unlock(CTS_MUTEX_TRANSACTION); +#endif + return ret; + } + + + ctsvc_notification_send(); +#ifdef _CONTACTS_IPC_SERVER + ctsvc_change_subject_publish_changed_info(); +#endif + +#ifndef _CONTACTS_IPC_SERVER + ctsvc_mutex_unlock(CTS_MUTEX_TRANSACTION); +#endif + + + CTS_DBG("Transaction shut down! : (%d)\n", transaction_ver); + + return CONTACTS_ERROR_NONE; +} + +const char* ctsvc_get_display_column(void) +{ + contacts_name_display_order_e order; + + contacts_setting_get_name_display_order(&order); + if (CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST == order) + return "display_name"; + else + return "reverse_display_name"; +} + +const char* ctsvc_get_sort_column(void) +{ + contacts_name_display_order_e order; + + contacts_setting_get_name_display_order(&order); + if (CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST == order) + return "display_name_language, sortkey"; + else + return "display_name_language, reverse_sortkey"; +} + +// This function is for MY profile and group image. +char* ctsvc_get_image(const char *dir, int index, char *dest, int dest_size) +{ + DIR *dp; + char *ret_val; + struct dirent *file_info; + char tmp_path[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0}; + + if (0 < index) + snprintf(tmp_path, sizeof(tmp_path), "%d", index); + + dp = opendir(dir); + if (dp) { + while ((file_info = readdir(dp)) != NULL) { + CTS_DBG("file = %s", file_info->d_name); + if ('.' != *file_info->d_name) { + if (0 == index || !strncmp(tmp_path, file_info->d_name, strlen(tmp_path))) { + if (dest) { + snprintf(dest, dest_size, "%s/%s", dir, file_info->d_name); + ret_val = dest; + } else { + snprintf(tmp_path, sizeof(tmp_path), "%s/%s", dir, file_info->d_name); + ret_val = strdup(tmp_path); + } + closedir(dp); + return ret_val; + } + } + } + closedir(dp); + } + + return NULL; +} + +static inline bool ctsvc_check_available_image_space(void){ + int ret; + struct statfs buf; + long long size; + ret = statfs(CTS_IMG_FULL_LOCATION, &buf); + + RETVM_IF(ret!=0, false, "statfs Failed(%d)", ret); + + size = buf.f_bavail * (buf.f_bsize); + + if (size > 1024*1024) // if available space to copy a image is larger than 1M + return true; + return false; +} + +static int image_size = 480; +static int __ctsvc_resize_and_copy_image(const char *src, const char *dest) +{ + image_util_error_e ret; + int width = 0, height = 0; + unsigned int size_decode = 0; + int resized_width, resized_height; + unsigned char * img_target = 0; + unsigned char * img_source = 0; + const image_util_colorspace_e colorspace = IMAGE_UTIL_COLORSPACE_I420; + + // load jpeg sample file + CTS_DBG("src : %s, dest : %s", src, dest); + ret = image_util_decode_jpeg( src, colorspace, &img_source, &width, &height, &size_decode ); + RETVM_IF(ret!=IMAGE_UTIL_ERROR_NONE, CONTACTS_ERROR_INTERNAL, "image_util_decode_jpeg failed(%d)", ret); + +#if 0 + if (0>image_size) { + int w,h; + ecore_x_window_size_get( + ecore_x_window_root_get(ecore_x_window_focus_get()) + , &w, &h); + + if (w>h) + image_size = h; + else + image_size = w; + + } +#endif + + if (width > image_size || height > image_size) { + if (image_size<=0 || width <=0 || height <= 0) { + free(img_source); + CTS_ERR("image size error(%d)", image_size); + return CONTACTS_ERROR_INTERNAL; + } + + if (width>height) { + resized_width = image_size; + resized_height = height*image_size/width; + } + else { + resized_height = image_size; + resized_width = width*image_size/height; + } + CTS_DBG("size(%d, %d) -> resize(%d,%d)", width, height, resized_width, resized_height); + + image_util_calculate_buffer_size(resized_width, resized_height, colorspace , &size_decode); + + img_target = malloc( size_decode ); + // do resize + ret = image_util_resize( img_target, &resized_width, &resized_height, + img_source, width, height, colorspace ); + if (ret!=IMAGE_UTIL_ERROR_NONE) { + CTS_ERR("image_util_resize failed(%d)", ret); + free( img_target ); + free( img_source ); + return CONTACTS_ERROR_INTERNAL; + } + + ret = image_util_encode_jpeg(img_target, resized_width, resized_height, colorspace, 100, dest ); + free( img_target ); + free( img_source ); + RETVM_IF(ret!=IMAGE_UTIL_ERROR_NONE, CONTACTS_ERROR_INTERNAL, "image_util_encode_jpeg failed(%d)", ret); + } + else { + resized_width = width; + resized_height = height; + + ret = image_util_encode_jpeg(img_source, resized_width, resized_height, colorspace, 100, dest ); + free( img_source ); + RETVM_IF(ret!=IMAGE_UTIL_ERROR_NONE, CONTACTS_ERROR_INTERNAL, "image_util_encode_jpeg failed(%d)", ret); + } + + return CONTACTS_ERROR_NONE; +} + +#define CTSVC_COPY_SIZE_MAX 4096 +int ctsvc_copy_image(const char *src, const char *dest) +{ + int ret; + int size; + int src_fd, dest_fd; + char buf[CTSVC_COPY_SIZE_MAX] = {0}; + + if (!ctsvc_check_available_image_space()) + return CONTACTS_ERROR_FILE_NO_SPACE; + + ret = __ctsvc_resize_and_copy_image(src, dest); + if (CONTACTS_ERROR_NONE == ret) + return ret; + + src_fd = open(src, O_RDONLY); + RETVM_IF(src_fd < 0, CONTACTS_ERROR_SYSTEM, "System : Open(src:%s) Failed(%d)", src, errno); + dest_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0660); + if (dest_fd < 0) { + CTS_ERR("Open(dest:%s) Failed(%d)", dest, errno); + close(src_fd); + return CONTACTS_ERROR_SYSTEM; + } + + while ((size = read(src_fd, buf, CTSVC_COPY_SIZE_MAX)) > 0) { + ret = write(dest_fd, buf, size); + if (ret <= 0) { + if (EINTR == errno) + continue; + else { + CTS_ERR("write() Failed(%d)", errno); + if (ENOSPC == errno) + ret = CONTACTS_ERROR_SYSTEM; // No space + else + ret = CONTACTS_ERROR_SYSTEM; // IO error + close(src_fd); + close(dest_fd); + unlink(dest); + return ret; + } + } + } + + ret = fchown(dest_fd, getuid(), CTS_SECURITY_FILE_GROUP); + if (0 != ret) + CTS_ERR("fchown(%s) Failed(%d)", dest, ret); + ret = fchmod(dest_fd, CTS_SECURITY_DEFAULT_PERMISSION); + if (0 != ret) + CTS_ERR("fchmod(%s) Failed(%d)", dest, ret); + close(src_fd); + close(dest_fd); + + return CONTACTS_ERROR_NONE; +} + +int ctsvc_change_image(const char *dir, int index, const char *path, char *image, int image_len) +{ + int ret; + char dest[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0}; + + if (ctsvc_get_image(dir, index, dest, sizeof(dest))) { + if (path && 0 == strcmp(dest, path)) + return CONTACTS_ERROR_NONE; + ret = unlink(dest); + RETVM_IF(ret < 0, CONTACTS_ERROR_SYSTEM, "System : unlink(%s) Failed(%d)", dest, errno); + } + + if (path) { + char *ext; + int len; + ext = strrchr(path, '.'); + if (NULL == ext || strchr(ext, '/')) + ext = ""; + + snprintf(dest, sizeof(dest), "%s/%d%s", + dir, index, ext); + ret = ctsvc_copy_image(path, dest); + RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_copy_image() Failed(%d)", ret); + len = strlen(dest) - strlen(dir); + if (image_len < len) { + CTS_ERR("The image_len is too short. It should be greater than %d", len); + return CONTACTS_ERROR_INVALID_PARAMETER; + } + snprintf(image, image_len, "%d%s", index, ext); + } + + return CONTACTS_ERROR_NONE; +} + +int ctsvc_get_next_ver(void) +{ + const char *query; + int version; + + if (0 < transaction_count) { + version_up = true; + return transaction_ver + 1; + } + + query = "SELECT ver FROM "CTS_TABLE_VERSION; + ctsvc_query_get_first_int_result(query, &version); + return (1 + version); +} + +int ctsvc_get_current_version( int* out_current_version ){ + if (transaction_count <= 0) { + int ret; + int version = 0; + const char *query = "SELECT ver FROM "CTS_TABLE_VERSION; + ret = ctsvc_query_get_first_int_result(query, &version); + *out_current_version = version; + } + else + *out_current_version = transaction_ver; + return CONTACTS_ERROR_NONE; +} + + |