From 1887491417fc271b892104fb2d3c74533d1492ae Mon Sep 17 00:00:00 2001 From: "pr.jung" Date: Thu, 22 Dec 2016 22:09:14 +0900 Subject: [PATCH] common: Add ProxyPool for dbus method call - Reuse proxy for same destination and interface Change-Id: I89a57e81afb0a7eb386067671704acd7d805550b Signed-off-by: pr.jung --- src/dbus.c | 217 +++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 147 insertions(+), 70 deletions(-) diff --git a/src/dbus.c b/src/dbus.c index b5d5757..e49e71b 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -28,13 +28,24 @@ #define DBUS_REPLY_TIMEOUT (-1) #define SIGNAL_VIBRATOR_INITIATED "InitiateVibrator" +#define DBUS_MAXIMUM_NAME_LENGTH 255 struct pending_call_data { dbus_pending_cb func; void *data; }; +struct proxy_node { + GDBusProxy *proxy; + char *dest; + char *path; + char *interface; +}; + static guint haptic_id = 0; +static GList *proxy_pool; +static pthread_mutex_t dmutex = PTHREAD_MUTEX_INITIALIZER; +static int bus_init; //LCOV_EXCL_START System Error static int g_dbus_error_to_errno(int code) @@ -105,29 +116,93 @@ static GVariant *append_g_variant(const char *sig, char *param[]) return g_variant_builder_end(&builder); } -int dbus_method_sync(const char *dest, const char *path, - const char *interface, const char *method, - const char *sig, char *param[]) +static struct proxy_node *find_matched_proxy_node(const char *dest, + const char *path, + const char *interface) +{ + GList *elem; + struct proxy_node *node; + int plen; + + if (!dest || !path || !interface) + return NULL; + + plen = strlen(path) + 1; + + /* find matched proxy object */ + for (elem = proxy_pool; elem; elem = elem->next) { + node = elem->data; + if (!node) + continue; + if (!strncmp(node->dest, dest, DBUS_MAXIMUM_NAME_LENGTH) && + !strncmp(node->path, path, plen) && + !strncmp(node->interface, interface, + DBUS_MAXIMUM_NAME_LENGTH)) + return node; + } + + return NULL; +} + +static void on_name_vanished(GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + GList *elem; + GList *next; + struct proxy_node *node; + + pthread_mutex_lock(&dmutex); + for (elem = proxy_pool, next = g_list_next(elem); elem; + elem = next, next = g_list_next(elem)) { + node = elem->data; + if (!node) + continue; + proxy_pool = g_list_delete_link(proxy_pool, elem); + g_object_unref(node->proxy); + free(node->dest); + free(node->path); + free(node->interface); + free(node); + } + pthread_mutex_unlock(&dmutex); +} + +static GDBusProxy *get_proxy_from_proxy_pool(const char *dest, + const char *path, + const char *interface, + GError **err) { GDBusConnection *conn; GDBusProxy *proxy; - GError *err = NULL; - GVariant *output; - int result; + struct proxy_node *node; -#if !GLIB_CHECK_VERSION(2, 35, 0) - g_type_init(); -#endif + if (!dest || !path || !interface) { + if (err) + g_set_error(err, G_IO_ERROR, + G_IO_ERROR_INVALID_ARGUMENT, + "Cannot determine destination address"); + return NULL; + } - conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); - if (!conn) { -//LCOV_EXCL_START System Error - _E("g_bus_get_sync error : %s-%s (%d-%s)", - interface, method, err->code, err->message); - result = g_dbus_error_to_errno(err->code); - g_clear_error(&err); - return result; -//LCOV_EXCL_STOP + /* find matched proxy node in proxy pool */ + node = find_matched_proxy_node(dest, path, interface); + if (node) + return node->proxy; + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, err); + if (!conn) + return NULL; + + if (!bus_init) { + bus_init++; + g_bus_watch_name_on_connection(conn, + DEVICED_BUS_NAME, + G_BUS_NAME_WATCHER_FLAGS_NONE, + NULL, + on_name_vanished, + NULL, + NULL); } proxy = g_dbus_proxy_new_sync(conn, @@ -137,10 +212,49 @@ int dbus_method_sync(const char *dest, const char *path, path, /* object path */ interface, /* interface name */ NULL, /* GCancellable */ - &err); + err); + if (!proxy) + return NULL; + + node = malloc(sizeof(struct proxy_node)); + if (!node) { + g_object_unref(proxy); + if (err) + g_set_error(err, G_IO_ERROR, + G_IO_ERROR_FAILED, + "Cannot allocate proxy_node memory"); + return NULL; + } + + node->proxy = proxy; + node->dest = strdup(dest); + node->path = strdup(path); + node->interface = strdup(interface); + + proxy_pool = g_list_append(proxy_pool, node); + + return proxy; +} + +int dbus_method_sync(const char *dest, const char *path, + const char *interface, const char *method, + const char *sig, char *param[]) +{ + GDBusProxy *proxy; + GError *err = NULL; + GVariant *output; + int result; + +#if !GLIB_CHECK_VERSION(2, 35, 0) + g_type_init(); +#endif + + pthread_mutex_lock(&dmutex); + proxy = get_proxy_from_proxy_pool(dest, path, interface, &err); if (!proxy) { //LCOV_EXCL_START System Error - _E("g_dbus_proxy_new_sync error : %s-%s (%d-%s)", + pthread_mutex_unlock(&dmutex); + _E("fail to get proxy from proxy pool : %s-%s (%d-%s)", interface, method, err->code, err->message); result = g_dbus_error_to_errno(err->code); g_clear_error(&err); @@ -155,19 +269,19 @@ int dbus_method_sync(const char *dest, const char *path, DBUS_REPLY_TIMEOUT, /* timeout */ NULL, /* GCancellable */ &err); + pthread_mutex_unlock(&dmutex); + if (!output) { //LCOV_EXCL_START System Error if (!err) { _E("g_dbus_proxy_call_sync error : %s-%s", interface, method); - g_object_unref(proxy); return -EPERM; } _E("g_dbus_proxy_call_sync error : %s-%s (%d-%s)", interface, method, err->code, err->message); result = g_dbus_error_to_errno(err->code); g_clear_error(&err); - g_object_unref(proxy); return result; //LCOV_EXCL_STOP } @@ -176,7 +290,6 @@ int dbus_method_sync(const char *dest, const char *path, g_variant_get(output, "(i)", &result); g_variant_unref(output); - g_object_unref(proxy); return result; } @@ -186,7 +299,6 @@ int dbus_method_sync_with_reply(const char *dest, const char *method, const char *sig, char *param[], GVariant **info) { - GDBusConnection *conn; GDBusProxy *proxy; GError *err = NULL; GVariant *output; @@ -196,28 +308,12 @@ int dbus_method_sync_with_reply(const char *dest, g_type_init(); #endif - conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); - if (!conn) { -//LCOV_EXCL_START System Error - _E("g_bus_get_sync error : %s-%s (%d-%s)", - interface, method, err->code, err->message); - result = g_dbus_error_to_errno(err->code); - g_clear_error(&err); - return result; -//LCOV_EXCL_STOP - } - - proxy = g_dbus_proxy_new_sync(conn, - G_DBUS_PROXY_FLAGS_NONE, - NULL, /* GDBusinterfaceinfo */ - dest, /* bus name */ - path, /* object path */ - interface, /* interface name */ - NULL, /* GCancellable */ - &err); + pthread_mutex_lock(&dmutex); + proxy = get_proxy_from_proxy_pool(dest, path, interface, &err); if (!proxy) { //LCOV_EXCL_START System Error - _E("g_dbus_proxy_new_sync error : %s-%s (%d-%s)", + pthread_mutex_unlock(&dmutex); + _E("fail to get proxy from proxy pool : %s-%s (%d-%s)", interface, method, err->code, err->message); result = g_dbus_error_to_errno(err->code); g_clear_error(&err); @@ -232,25 +328,22 @@ int dbus_method_sync_with_reply(const char *dest, DBUS_REPLY_TIMEOUT, /* timeout */ NULL, /* GCancellable */ &err); + pthread_mutex_unlock(&dmutex); if (!output) { if (!err) { //LCOV_EXCL_START System Error _E("g_dbus_proxy_call_sync error : %s-%s", interface, method); - g_object_unref(proxy); return -EPERM; } _E("g_dbus_proxy_call_sync error : %s-%s (%d-%s)", interface, method, err->code, err->message); result = g_dbus_error_to_errno(err->code); g_clear_error(&err); - g_object_unref(proxy); return result; //LCOV_EXCL_STOP } - g_object_unref(proxy); - *info = output; return DEVICE_ERROR_NONE; } @@ -280,7 +373,6 @@ static void cb_pending(GDBusProxy *proxy, //LCOV_EXCL_STOP if (output) g_variant_unref(output); - g_object_unref(proxy); } int dbus_method_async_with_reply(const char *dest, const char *path, @@ -288,7 +380,6 @@ int dbus_method_async_with_reply(const char *dest, const char *path, const char *sig, char *param[], dbus_pending_cb cb, int timeout, void *data) { - GDBusConnection *conn; GDBusProxy *proxy; GError *err = NULL; struct pending_call_data *pdata; @@ -298,28 +389,12 @@ int dbus_method_async_with_reply(const char *dest, const char *path, g_type_init(); #endif - conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); - if (!conn) { -//LCOV_EXCL_START System Error - _E("g_bus_get_sync error : %s-%s (%d-%s)", - interface, method, err->code, err->message); - result = g_dbus_error_to_errno(err->code); - g_clear_error(&err); - return result; -//LCOV_EXCL_STOP - } - - proxy = g_dbus_proxy_new_sync(conn, - G_DBUS_PROXY_FLAGS_NONE, - NULL, /* GDBusinterfaceinfo */ - dest, /* bus name */ - path, /* object path */ - interface, /* interface name */ - NULL, /* GCancellable */ - &err); + pthread_mutex_lock(&dmutex); + proxy = get_proxy_from_proxy_pool(dest, path, interface, &err); if (!proxy) { //LCOV_EXCL_START System Error - _E("g_dbus_proxy_new_sync error : %s-%s (%d-%s)", + pthread_mutex_unlock(&dmutex); + _E("fail to get proxy from proxy pool : %s-%s (%d-%s)", interface, method, err->code, err->message); result = g_dbus_error_to_errno(err->code); g_clear_error(&err); @@ -329,6 +404,7 @@ int dbus_method_async_with_reply(const char *dest, const char *path, pdata = malloc(sizeof(struct pending_call_data)); if (!pdata) { + pthread_mutex_unlock(&dmutex); _E("malloc error : %s-%s", //LCOV_EXCL_LINE interface, method); return -ENOMEM; @@ -345,6 +421,7 @@ int dbus_method_async_with_reply(const char *dest, const char *path, NULL, /* GCancellable */ (GAsyncReadyCallback)cb_pending, /* GAsyncReadyCallback */ pdata); /* user data */ + pthread_mutex_unlock(&dmutex); return 0; } -- 2.7.4