*/
#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <glib.h>
#include <stdlib.h>
#include <unistd.h>
#include <glib.h>
#include <pims-ipc-data.h>
#include "ctsvc_client_ipc.h"
+#include "ctsvc_client_service_helper.h"
#include "ctsvc_internal.h"
#include "ctsvc_list.h"
#include "ctsvc_mutex.h"
#include "ctsvc_handle.h"
-static __thread pims_ipc_h __contacts_ipc = NULL;
-static pims_ipc_h __contacts_global_ipc = NULL;
+#define CTS_STR_SHORT_LEN 1024 //short sql string length
-int ctsvc_ipc_connect_on_thread(contacts_h contact)
-{
- int ret = CONTACTS_ERROR_NONE;
- pims_ipc_data_h outdata = NULL;
+struct ctsvc_ipc_s {
+ pims_ipc_h ipc;
+ GList *list_handle;
+};
- // ipc create
- if (__contacts_ipc == NULL) {
- char sock_file[CTSVC_PATH_MAX_LEN] = {0};
- snprintf(sock_file, sizeof(sock_file), CTSVC_SOCK_PATH"/.%s", getuid(), CTSVC_IPC_SERVICE);
- __contacts_ipc = pims_ipc_create(sock_file);
- if (__contacts_ipc == NULL) {
- if (errno == EACCES) {
- CTS_ERR("pims_ipc_create() Fail(%d)", CONTACTS_ERROR_PERMISSION_DENIED);
- return CONTACTS_ERROR_PERMISSION_DENIED;
- }
- else {
- CTS_ERR("pims_ipc_create() Fail(%d)", CONTACTS_ERROR_IPC_NOT_AVALIABLE);
- return CONTACTS_ERROR_IPC_NOT_AVALIABLE;
- }
- }
- }
+static GHashTable *_ctsvc_ipc_table = NULL;
+static bool _ctsvc_ipc_disconnected = false;
+static int disconnected_cb_count = 0;
+
+static inline void _ctsvc_ipc_get_pid_str(char *buf, int buf_size)
+{
+ pid_t pid = getpid();
+ snprintf(buf, buf_size, "%d", (unsigned int)pid);
+}
+static inline void _ctsvc_ipc_get_tid_str(char *buf, int buf_size)
+{
+ pthread_t tid = pthread_self();
+ snprintf(buf, buf_size, "%d", (unsigned int)tid);
+}
- // ipc call
- if (pims_ipc_call(__contacts_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_CONNECT, NULL, &outdata) != 0) {
- CTS_ERR("pims_ipc_call Fail");
- ret = CONTACTS_ERROR_IPC;
- goto DATA_FREE;
+static struct ctsvc_ipc_s* _ctsvc_get_ipc_data()
+{
+ struct ctsvc_ipc_s *ipc_data = NULL;
+ char ipc_key[CTS_STR_SHORT_LEN] = {0};
+ RETVM_IF(NULL == _ctsvc_ipc_table, NULL, "contacts not connected");
+
+ _ctsvc_ipc_get_tid_str(ipc_key, sizeof(ipc_key));
+ ipc_data = g_hash_table_lookup(_ctsvc_ipc_table, ipc_key);
+ if (NULL == ipc_data) {
+ _ctsvc_ipc_get_pid_str(ipc_key, sizeof(ipc_key));
+ ipc_data = g_hash_table_lookup(_ctsvc_ipc_table, ipc_key);
}
+ return ipc_data;
+}
- if (outdata) {
- unsigned int size = 0;
- ret = *(int*) pims_ipc_data_get(outdata,&size);
+static pims_ipc_h _ctsvc_get_ipc_handle()
+{
+ struct ctsvc_ipc_s *ipc_data = _ctsvc_get_ipc_data();
+ if (ipc_data)
+ return ipc_data->ipc;
- pims_ipc_data_destroy(outdata);
+ return NULL;
+}
- if (ret != CONTACTS_ERROR_NONE) {
- CTS_ERR("ctsvc_ipc_server_connect return(%d)", ret);
- goto DATA_FREE;
- }
- }
+bool ctsvc_ipc_is_busy()
+{
+ bool ret = false;
- return ret;
+ pims_ipc_h ipc = _ctsvc_get_ipc_handle();
+ if (NULL == ipc) {
+ CTS_ERR("_ctsvc_get_ipc_handle() return NULL");
+ return false;
+ }
-DATA_FREE:
- pims_ipc_destroy(__contacts_ipc);
- __contacts_ipc = NULL;
+ ret = pims_ipc_is_call_in_progress(ipc);
+ if (ret)
+ CTS_ERR("global ipc channel is busy.");
return ret;
}
-int ctsvc_ipc_disconnect_on_thread(contacts_h contact, int connection_count)
+static int _ctsvc_ipc_create(pims_ipc_h *p_ipc)
{
- int ret = CONTACTS_ERROR_NONE;
+ int ret;
+ pims_ipc_data_h indata = NULL;
pims_ipc_data_h outdata = NULL;
- RETVM_IF(__contacts_ipc == NULL, CONTACTS_ERROR_IPC, "contacts not connected");
+ char sock_file[CTSVC_PATH_MAX_LEN] = {0};
+ snprintf(sock_file, sizeof(sock_file), CTSVC_SOCK_PATH"/.%s", getuid(), CTSVC_IPC_SERVICE);
+ pims_ipc_h ipc = pims_ipc_create(sock_file);
+ if (NULL == ipc) {
+ if (errno == EACCES) {
+ CTS_ERR("pims_ipc_create() Failed(%d)", CONTACTS_ERROR_PERMISSION_DENIED);
+ return CONTACTS_ERROR_PERMISSION_DENIED;
+ }
+ else {
+ CTS_ERR("pims_ipc_create() Failed(%d)", CONTACTS_ERROR_IPC_NOT_AVALIABLE);
+ return CONTACTS_ERROR_IPC_NOT_AVALIABLE;
+ }
+ }
- if (pims_ipc_call(__contacts_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_DISCONNECT, NULL, &outdata) != 0) {
- CTS_ERR("pims_ipc_call Fail");
- return CONTACTS_ERROR_IPC;
+ *p_ipc = ipc;
+ return CONTACTS_ERROR_NONE;
+
+ /* ipc call */
+ if (pims_ipc_call(ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_CONNECT, indata, &outdata) != 0) {
+ CTS_ERR("pims_ipc_call failed");
+ pims_ipc_data_destroy(indata);
+ ret = CONTACTS_ERROR_IPC;
+ goto DATA_FREE;
}
if (outdata) {
unsigned int size = 0;
ret = *(int*) pims_ipc_data_get(outdata,&size);
- pims_ipc_data_destroy(outdata);
- if (ret != CONTACTS_ERROR_NONE)
- CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc didn't destroyed!!!(%d)", ret);
+ pims_ipc_data_destroy(outdata);
- if (1 == connection_count) {
- pims_ipc_destroy(__contacts_ipc);
- __contacts_ipc = NULL;
+ if (ret != CONTACTS_ERROR_NONE) {
+ CTS_ERR("ctsvc_ipc_server_connect return(%d)", ret);
+ goto DATA_FREE;
}
}
- else {
- CTS_ERR("pims_ipc_call out data is NULL");
- return CONTACTS_ERROR_IPC;
- }
-
+ *p_ipc = ipc;
+ return CONTACTS_ERROR_NONE;
+DATA_FREE:
+ pims_ipc_destroy(ipc);
return ret;
}
-pims_ipc_h ctsvc_get_ipc_handle()
+static void _ctsvc_ipc_data_free(gpointer p)
{
- if (__contacts_ipc == NULL) {
- if (__contacts_global_ipc == NULL) {
- CTS_ERR("IPC haven't been initialized yet.");
- return NULL;
- }
- CTS_DBG("fallback to global ipc channel");
- return __contacts_global_ipc;
- }
+ struct ctsvc_ipc_s *ipc_data = p;
+ if (NULL == ipc_data)
+ return;
+
+ if (ipc_data->ipc)
+ pims_ipc_destroy(ipc_data->ipc);
- return __contacts_ipc;
+ g_list_free(ipc_data->list_handle);
+
+ free(ipc_data);
}
-bool ctsvc_ipc_is_busy()
+static int _ctsvc_ipc_connect(contacts_h contact, pims_ipc_h ipc)
{
- bool ret = false;
+ int ret;
+ pims_ipc_data_h outdata = NULL;
+ pims_ipc_data_h indata = NULL;
- if (__contacts_ipc != NULL) {
- ret = pims_ipc_is_call_in_progress(__contacts_ipc);
- if (ret)
- CTS_ERR("thread local ipc channel is busy.");
+ /* Access control : put cookie to indata */
+ indata = pims_ipc_data_create(0);
+ if (indata == NULL) {
+ CTS_ERR("pims_ipc_data_create() return NULL");
+ return CONTACTS_ERROR_OUT_OF_MEMORY;
}
- else {
- ret = pims_ipc_is_call_in_progress(__contacts_global_ipc);
- if (ret)
- CTS_ERR("global ipc channel is busy.");
+
+ ret = ctsvc_ipc_marshal_handle(contact, indata);
+ if (CONTACTS_ERROR_NONE != ret) {
+ CTS_ERR("ctsvc_ipc_marshal_handle Fail(%d)", ret);
+ pims_ipc_data_destroy(indata);
+ return ret;
}
+ /* ipc call */
+ if (pims_ipc_call(ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_CONNECT, indata, &outdata) != 0) {
+ CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc_call failed");
+ pims_ipc_data_destroy(indata);
+ return CONTACTS_ERROR_IPC;
+ }
+ pims_ipc_data_destroy(indata);
+
+ if (outdata) {
+ ctsvc_ipc_unmarshal_int(outdata, &ret);
+ pims_ipc_data_destroy(outdata);
+ RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_ipc_server_connect return(%d)", ret);
+ }
return ret;
}
int ctsvc_ipc_connect(contacts_h contact)
{
int ret = CONTACTS_ERROR_NONE;
- pims_ipc_data_h outdata = NULL;
+ struct ctsvc_ipc_s *ipc_data = NULL;
+ char ipc_key[CTS_STR_SHORT_LEN] = {0};
- // ipc create
- if (__contacts_global_ipc == NULL) {
- char sock_file[CTSVC_PATH_MAX_LEN] = {0};
- snprintf(sock_file, sizeof(sock_file), CTSVC_SOCK_PATH"/.%s", getuid(), CTSVC_IPC_SERVICE);
- __contacts_global_ipc = pims_ipc_create(sock_file);
- if (__contacts_global_ipc == NULL) {
- if (errno == EACCES) {
- CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc_create() Fail(%d)", CONTACTS_ERROR_PERMISSION_DENIED);
- return CONTACTS_ERROR_PERMISSION_DENIED;
- }
- else {
- CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc_create() Fail(%d)", CONTACTS_ERROR_IPC_NOT_AVALIABLE);
- return CONTACTS_ERROR_IPC_NOT_AVALIABLE;
- }
- }
- }
+ RETV_IF(_ctsvc_ipc_disconnected, CONTACTS_ERROR_IPC_NOT_AVALIABLE);
- /* ipc call */
- if (pims_ipc_call(__contacts_global_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_CONNECT, NULL, &outdata) != 0) {
- CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc_call Fail");
- ret = CONTACTS_ERROR_IPC;
- goto DATA_FREE;
- }
+ _ctsvc_ipc_get_tid_str(ipc_key, sizeof(ipc_key));
- if (outdata) {
- unsigned int size = 0;
- ret = *(int*) pims_ipc_data_get(outdata,&size);
- pims_ipc_data_destroy(outdata);
+ if (NULL == _ctsvc_ipc_table)
+ _ctsvc_ipc_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, _ctsvc_ipc_data_free);
+ else
+ ipc_data = g_hash_table_lookup(_ctsvc_ipc_table, ipc_key);
- if (ret != CONTACTS_ERROR_NONE) {
- CTS_ERR("ctsvc_ipc_server_connect return(%d)", ret);
- goto DATA_FREE;
+ if (NULL == ipc_data) {
+ ipc_data = calloc(1, sizeof(struct ctsvc_ipc_s));
+ ret = _ctsvc_ipc_create(&(ipc_data->ipc));
+ if (CONTACTS_ERROR_NONE != ret) {
+ _ctsvc_ipc_data_free(ipc_data);
+ return ret;
}
+ g_hash_table_insert(_ctsvc_ipc_table, strdup(ipc_key), ipc_data);
}
+ _ctsvc_ipc_connect(contact, ipc_data->ipc);
+ ipc_data->list_handle = g_list_append(ipc_data->list_handle, contact);
- return ret;
-
-DATA_FREE:
- pims_ipc_destroy(__contacts_global_ipc);
- __contacts_global_ipc = NULL;
- return ret;
+ return CONTACTS_ERROR_NONE;
}
int ctsvc_ipc_disconnect(contacts_h contact, int connection_count)
{
int ret = CONTACTS_ERROR_NONE;
+ char ipc_key[CTS_STR_SHORT_LEN] = {0};
+ struct ctsvc_ipc_s *ipc_data = NULL;
pims_ipc_data_h outdata = NULL;
+ pims_ipc_data_h indata = NULL;
- RETVM_IF(__contacts_global_ipc == NULL, CONTACTS_ERROR_IPC, "[GLOBAL_IPC_CHANNEL] contacts not connected");
+ RETV_IF(_ctsvc_ipc_disconnected, CONTACTS_ERROR_IPC_NOT_AVALIABLE);
+ RETVM_IF(NULL == _ctsvc_ipc_table, CONTACTS_ERROR_IPC, "contacts not connected");
- if (pims_ipc_call(__contacts_global_ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_DISCONNECT, NULL, &outdata) != 0) {
- CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc_call Fail");
+ _ctsvc_ipc_get_tid_str(ipc_key, sizeof(ipc_key));
+
+ ipc_data = g_hash_table_lookup(_ctsvc_ipc_table, ipc_key);
+ RETVM_IF(ipc_data == NULL, CONTACTS_ERROR_IPC, "contacts not connected");
+
+ indata = pims_ipc_data_create(0);
+ if (indata == NULL) {
+ CTS_ERR("ipc data created fail!");
+ return CONTACTS_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = ctsvc_ipc_marshal_handle(contact, indata);
+ RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_ipc_marshal_handle() Fail(%d)", ret);
+
+ if (pims_ipc_call(ipc_data->ipc, CTSVC_IPC_MODULE, CTSVC_IPC_SERVER_DISCONNECT, indata, &outdata) != 0) {
+ pims_ipc_data_destroy(indata);
+ CTS_ERR("[GLOBAL_IPC_CHANNEL] pims_ipc_call failed");
return CONTACTS_ERROR_IPC;
}
if (outdata) {
- unsigned int size = 0;
- ret = *(int*) pims_ipc_data_get(outdata,&size);
+ ctsvc_ipc_unmarshal_int(outdata, &ret);
pims_ipc_data_destroy(outdata);
if (ret != CONTACTS_ERROR_NONE) {
}
if (1 == connection_count) {
- pims_ipc_destroy(__contacts_global_ipc);
- __contacts_global_ipc = NULL;
+ g_hash_table_remove(_ctsvc_ipc_table, ipc_key);
}
}
else {
static void __ctsvc_ipc_lock()
{
- if (__contacts_ipc == NULL)
+ if (0 == ctsvc_client_get_thread_connection_count())
ctsvc_mutex_lock(CTS_MUTEX_PIMS_IPC_CALL);
}
static void __ctsvc_ipc_unlock(void)
{
- if (__contacts_ipc == NULL)
+ if (0 == ctsvc_client_get_thread_connection_count())
ctsvc_mutex_unlock(CTS_MUTEX_PIMS_IPC_CALL);
}
int ctsvc_ipc_call(char *module, char *function, pims_ipc_h data_in, pims_ipc_data_h *data_out)
{
- pims_ipc_h ipc_handle = ctsvc_get_ipc_handle();
+ pims_ipc_h ipc_handle = _ctsvc_get_ipc_handle();
__ctsvc_ipc_lock();
return ret;
}
+
+
+int ctsvc_ipc_set_disconnected_cb(void (*cb)(void *), void *user_data)
+{
+ if (0 == disconnected_cb_count++)
+ return pims_ipc_set_server_disconnected_cb(cb, user_data);
+ return CONTACTS_ERROR_NONE;
+}
+
+int ctsvc_ipc_unset_disconnected_cb()
+{
+ if (1 == disconnected_cb_count--)
+ return pims_ipc_unset_server_disconnected_cb();
+ return CONTACTS_ERROR_NONE;
+}
+
+void ctsvc_ipc_set_disconnected(bool is_disconnected)
+{
+ _ctsvc_ipc_disconnected = is_disconnected;
+}
+
+static void _ctsvc_ipc_recovery_foreach_cb(gpointer key, gpointer value, gpointer user_data)
+{
+ GList *c;
+ struct ctsvc_ipc_s *ipc_data = value;
+
+ int ret = _ctsvc_ipc_create(&(ipc_data->ipc));
+ RETM_IF(CONTACTS_ERROR_NONE != ret, "_ctsvc_ipc_create() Fail(%d)", ret);
+
+ for (c=ipc_data->list_handle;c;c=c->next) {
+ contacts_h contact = c->data;
+ ret = _ctsvc_ipc_connect(contact, ipc_data->ipc);
+ WARN_IF(CONTACTS_ERROR_NONE != ret, "_ctsvc_ipc_connect() Fail(%d)", ret);
+ }
+}
+
+void ctsvc_ipc_recovery()
+{
+ CTS_DBG("ctsvc_ipc_recovery (_ctsvc_ipc_disconnected=%d)", _ctsvc_ipc_disconnected);
+
+ if (false == _ctsvc_ipc_disconnected)
+ return;
+
+ g_hash_table_foreach(_ctsvc_ipc_table, _ctsvc_ipc_recovery_foreach_cb, NULL);
+}
+
+
#include "ctsvc_client_handle.h"
#include "ctsvc_client_service_helper.h"
-static int ctsvc_connection = 0;
-static __thread int ctsvc_connection_on_thread = 0;
+static int _ctsvc_connection = 0;
+static __thread int _ctsvc_connection_on_thread = 0;
+
+int ctsvc_client_get_thread_connection_count()
+{
+ return _ctsvc_connection_on_thread;
+}
int ctsvc_client_connect_with_flags(contacts_h contact, unsigned int flags)
{
return ret;
}
+static void _ctsvc_ipc_disconnected_cb(void *user_data)
+{
+ ctsvc_ipc_set_disconnected(true);
+}
+
+static void _ctsvc_ipc_initialized_cb(void *user_data)
+{
+ ctsvc_ipc_recovery();
+ ctsvc_ipc_recover_for_change_subscription();
+ ctsvc_ipc_set_disconnected(false);
+}
+
int ctsvc_client_connect(contacts_h contact)
{
CTS_FN_CALL;
}
base->connection_count++;
- if (0 == ctsvc_connection) {
+ if (0 == _ctsvc_connection) {
ret = ctsvc_socket_init();
if (ret != CONTACTS_ERROR_NONE) {
CTS_ERR("ctsvc_socket_init() Fail(%d)", ret);
ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
return ret;
}
-
ctsvc_view_uri_init();
ctsvc_ipc_create_for_change_subscription();
+ ctsvc_ipc_set_disconnected_cb(_ctsvc_ipc_disconnected_cb, NULL);
}
else
- CTS_DBG("System : Contacts service has been already connected(%d)", ctsvc_connection + 1);
+ CTS_DBG("System : Contacts service has been already connected(%d)", _ctsvc_connection + 1);
- ctsvc_connection++;
+ if (1 == base->connection_count)
+ ctsvc_inotify_subscribe_ipc_ready(contact, _ctsvc_ipc_initialized_cb, NULL);
+
+ _ctsvc_connection++;
ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
return CONTACTS_ERROR_NONE;
ctsvc_base_s *base = (ctsvc_base_s *)contact;
if (1 == base->connection_count) {
- ret = ctsvc_ipc_disconnect(contact, ctsvc_connection);
+ ret = ctsvc_ipc_disconnect(contact, _ctsvc_connection);
if (ret != CONTACTS_ERROR_NONE) {
ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
CTS_ERR("ctsvc_ipc_disconnect() Fail(%d)", ret);
return ret;
}
+ ctsvc_inotify_unsubscribe_ipc_ready(contact);
ctsvc_client_handle_remove((contacts_h)base);
}
else {
base->connection_count--;
}
- if (1 == ctsvc_connection) {
+ if (1 == _ctsvc_connection) {
ctsvc_ipc_destroy_for_change_subscription();
ctsvc_view_uri_deinit();
ctsvc_inotify_close();
ctsvc_socket_final();
+ ctsvc_ipc_unset_disconnected_cb();
}
- else if (1 < ctsvc_connection)
- CTS_DBG("System : connection count is %d", ctsvc_connection);
+ else if (1 < _ctsvc_connection)
+ CTS_DBG("System : connection count is %d", _ctsvc_connection);
else {
- CTS_DBG("System : please call contacts_connect(), connection count is (%d)", ctsvc_connection);
+ CTS_DBG("System : please call contacts_connect(), connection count is (%d)", _ctsvc_connection);
ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
return CONTACTS_ERROR_INVALID_PARAMETER;
}
- ctsvc_connection--;
+ _ctsvc_connection--;
ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
return CONTACTS_ERROR_NONE;
ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
if (0 == base->connection_count) {
- ret = ctsvc_ipc_connect_on_thread(contact);
+ ret = ctsvc_ipc_connect(contact);
if (ret != CONTACTS_ERROR_NONE) {
- CTS_ERR("ctsvc_ipc_connect_on_thread() Fail(%d)", ret);
+ CTS_ERR("ctsvc_ipc_connect() Fail(%d)", ret);
ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
return ret;
}
}
base->connection_count++;
- if (0 == ctsvc_connection_on_thread) {
+ if (0 == _ctsvc_connection_on_thread) {
ret = ctsvc_socket_init();
if (ret != CONTACTS_ERROR_NONE) {
CTS_ERR("ctsvc_socket_init() Fail(%d)", ret);
ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
return ret;
}
-
ctsvc_view_uri_init();
ctsvc_ipc_create_for_change_subscription();
+ ctsvc_ipc_set_disconnected_cb(_ctsvc_ipc_disconnected_cb, NULL);
}
- else if (0 < ctsvc_connection_on_thread)
+ else if (0 < _ctsvc_connection_on_thread)
CTS_DBG("System : Contacts service has been already connected");
- ctsvc_connection_on_thread++;
+ if (1 == base->connection_count)
+ ctsvc_inotify_subscribe_ipc_ready(contact, _ctsvc_ipc_initialized_cb, NULL);
+
+ _ctsvc_connection_on_thread++;
ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
ctsvc_mutex_lock(CTS_MUTEX_CONNECTION);
if (1 == base->connection_count) {
- ret = ctsvc_ipc_disconnect_on_thread(contact, ctsvc_connection_on_thread);
+ ret = ctsvc_ipc_disconnect(contact, _ctsvc_connection_on_thread);
if (ret != CONTACTS_ERROR_NONE) {
CTS_ERR("ctsvc_ipc_disconnect_on_thread() Fail(%d)", ret);
ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
return ret;
}
+ ctsvc_inotify_unsubscribe_ipc_ready(contact);
ctsvc_client_handle_remove((contacts_h)base);
-
}
else {
base->connection_count--;
}
- if (1 == ctsvc_connection_on_thread) {
+ if (1 == _ctsvc_connection_on_thread) {
ctsvc_ipc_destroy_for_change_subscription();
ctsvc_view_uri_deinit();
ctsvc_inotify_close();
ctsvc_socket_final();
+ ctsvc_ipc_unset_disconnected_cb();
CTS_DBG("System : connection_on_thread was destroyed successfully");
}
- else if (1 < ctsvc_connection_on_thread) {
- CTS_DBG("System : connection count is %d", ctsvc_connection_on_thread);
+ else if (1 < _ctsvc_connection_on_thread) {
+ CTS_DBG("System : connection count is %d", _ctsvc_connection_on_thread);
}
else {
- CTS_DBG("System : please call contacts_connect_on_thread(), connection count is (%d)", ctsvc_connection_on_thread);
+ CTS_DBG("System : please call contacts_connect_on_thread(), connection count is (%d)", _ctsvc_connection_on_thread);
ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
return CONTACTS_ERROR_INVALID_PARAMETER;
}
- ctsvc_connection_on_thread--;
+ _ctsvc_connection_on_thread--;
ctsvc_mutex_unlock(CTS_MUTEX_CONNECTION);
bool blocked;
}noti_info;
+struct socket_init_noti_info {
+ int wd;
+ int subscribe_count;
+ void (*cb)(void *);
+ void *cb_data;
+};
+
+static GHashTable *_ctsvc_socket_init_noti_table = NULL;
static int __ctsvc_inoti_ref = 0;
static int __inoti_fd = -1;
static guint __inoti_handler = 0;
}
}
+static void _ctsvc_inotify_socket_init_noti_table_foreach_cb(gpointer key, gpointer value, gpointer user_data)
+{
+ GList *c;
+ struct socket_init_noti_info *noti_info = value;
+
+ int wd = GPOINTER_TO_INT(user_data);
+ if (noti_info->wd == wd)
+ noti_info->cb(noti_info->cb_data);
+}
+
static gboolean __ctsvc_inotify_gio_cb(GIOChannel *src, GIOCondition cond, gpointer data)
{
int fd, ret;
while (0 < (ret = read(fd, &ie, sizeof(ie)))) {
if (sizeof(ie) == ret) {
+ if (_ctsvc_socket_init_noti_table)
+ g_hash_table_foreach(_ctsvc_socket_init_noti_table, _ctsvc_inotify_socket_init_noti_table_foreach_cb, GINT_TO_POINTER(ie.wd));
+
if (__noti_list)
__ctsvc_inotify_handle_callback(__noti_list, ie.wd, ie.mask);
return NULL;
}
+int ctsvc_inotify_subscribe_ipc_ready(contacts_h contact, void (*cb)(void *), void *user_data)
+{
+ const char *noti_path = CTSVC_NOTI_IPC_READY;
+ struct socket_init_noti_info *noti_info = NULL;
+
+ if (NULL == _ctsvc_socket_init_noti_table)
+ _ctsvc_socket_init_noti_table = g_hash_table_new_full(g_str_hash, g_str_equal, free, free);
+ else
+ noti_info = g_hash_table_lookup(_ctsvc_socket_init_noti_table, noti_path);
+
+ if (NULL == noti_info) {
+ int wd = __ctsvc_inotify_get_wd(__inoti_fd, noti_path);
+ if (-1 == wd) {
+ CTS_ERR("__ctsvc_inotify_get_wd() Failed(noti_path=%s, errno : %d)", noti_path, errno);
+ if (errno == EACCES)
+ return CONTACTS_ERROR_PERMISSION_DENIED;
+ return CONTACTS_ERROR_SYSTEM;
+ }
+
+ int ret = __ctsvc_inotify_watch(__inoti_fd, noti_path);
+ if (CONTACTS_ERROR_NONE != ret) {
+ CTS_ERR("__ctsvc_inotify_watch() Failed");
+ return ret;
+ }
+
+ noti_info = calloc(1, sizeof(struct socket_init_noti_info));
+ if (NULL == noti_info) {
+ CTS_ERR("calloc() return NULL");
+ return ret;
+ }
+
+ noti_info->wd = wd;
+ noti_info->cb = cb;
+ noti_info->cb_data = user_data;
+ g_hash_table_insert(_ctsvc_socket_init_noti_table, strdup(noti_path), noti_info);
+ }
+ noti_info->subscribe_count++;
+ return CONTACTS_ERROR_NONE;
+}
+
+int ctsvc_inotify_unsubscribe_ipc_ready(contacts_h contact)
+{
+ RETVM_IF(NULL == _ctsvc_socket_init_noti_table, CONTACTS_ERROR_INVALID_PARAMETER, "_ctsvc_socket_init_noti_table is NULL");
+
+ const char *noti_path = CTSVC_NOTI_IPC_READY;
+ struct socket_init_noti_info *noti_info = NULL;
+
+ noti_info = g_hash_table_lookup(_ctsvc_socket_init_noti_table, noti_path);
+ RETVM_IF(NULL == noti_info, CONTACTS_ERROR_INVALID_PARAMETER, "g_hash_table_lookup() return NULL");
+
+ if (1 == noti_info->subscribe_count) {
+ int wd = noti_info->wd;
+ inotify_rm_watch(__inoti_fd, wd);
+ g_hash_table_remove(_ctsvc_socket_init_noti_table, noti_path); // free noti_info automatically
+ }
+ else {
+ noti_info->subscribe_count--;
+ }
+
+ return CONTACTS_ERROR_NONE;
+}
+
+
int ctsvc_inotify_subscribe(contacts_h contact, const char *view_uri,
void *cb, void *data)
{